본문 바로가기

Java/Spring

[Spring] 길찾기 서비스 #4

What to do?

kakao API 기능 구현

카카오 API 문서에 보고, DTO를 설계하고, Service코드를 작성


환경변수 등록

카카오 API를 활용하기 위해서는 API키가 필요하다.

이전 포스팅(#1)에서 만든 kakao 앱의 API키를 가져오자.

kakao 개발자 사이트

 

IntellJ에서 Edit Configuration버튼을 눌러서, KAKAO API키를 환경변수로 등록한다.

 

application.yaml 파일에서 API KEY를 주입받을수 있도록 하자.

kakao:
  api:
    base-url: "https://dapi.kakao.com/v2/local/search/address.json"
    secret-key: ${KAKAO_API_SECRET_KEY}

base-url은 뒤에서 설명하겠지만 API 문서에서 나온 GET요청을 쏘는 주소다.


KaKao API 문서 살펴보기

kakao 개발자 사이트에서 지도 관련된 API 문서를 확인해보자

 

요청을 보내는 샘플코드다.

sample request

요약해보면 다음과 같다.

  • 헤더
    • 인증토큰 :  KakaoAK ${REST_API_KEY} 
  • parameter
    • query="검색할 주소"

 

응답은 다음과 같은 형태로 온다

sample response

meta데이터와 documents라는 키값으로 json이 반환되는걸 확인할 수 있다.

이에 맞게 ⓐ MetaDTO, ⓑ documentDTO을 먼저 정의하고, ⓒ responseDTO는 metaDTO, List<doumentDTO>를 가지도록 정의할 것이다.


Domain 정의하기

API 문서와 맞게 Dto를 정의해보자.

 

MetaDto

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class MetaDto {
    /**
     * total_count(Integer)    검색어에 검색된 문서 수
     * pageable_count(Integer) total_count 중 노출 가능 문서 수(최대: 45)
     * is_end(Boolean) 현재 페이지가 마지막 페이지인지 여부, 값이 false면 다음 요청 시 page 값을 증가시켜 다음 페이지 요청 가능
     */
    @JsonProperty("total_count")
    private Integer totalCount;
}

DocumentDto

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class DocumentDto {
    /**
     * address_name(String)    전체 지번 주소 또는 전체 도로명 주소, 입력에 따라 결정됨
     * address_type(String)    address_name의 값의 타입(Type)
     * 다음 중 하나:
     * REGION(지명)
     * ROAD(도로명)
     * REGION_ADDR(지번 주소)
     * ROAD_ADDR(도로명 주소)
     * x(String)   X 좌표값, 경위도인 경우 경도(longitude)
     * y(String)   Y 좌표값, 경위도인 경우 위도(latitude)
     * address(Address)    지번 주소 상세 정보, 아래 Address 참고
     * road_address(RoadAaddress)  도로명 주소 상세 정보, 아래 RoadAaddress 참고
     */
    @JsonProperty("address_name")
    private String addressName;
    @JsonProperty("x")
    private Double longitude;
    @JsonProperty("y")
    private Double latitude;
}

KakaoApiResponseDto

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class KakaoApiResponseDto {
    @JsonProperty("meta")
    private MetaDto meta;
    @JsonProperty("documents")
    private List<DocumentDto> documents;
}

Configuration

RestTemplate을 Bean으로 등록해준다.

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

Service

 

  • buidUri
    • 한글 주소를 입력받아 uri로 인코딩
  • searchAddress
    • 한글 주소를 입력받아 buildUri 메써드로 URI로 변경
    • 해당 URI로 검색한 결과를 Dto로 반환
@Slf4j
@Service
@RequiredArgsConstructor
public class KakaoApiService {
    private String KAKAO_BASE_URL = "https://dapi.kakao.com/v2/local/search/address.json";
    @Value("${kakao.api.secret-key}") private String KAKAO_SECRET_KEY;
    private final RestTemplate restTemplate;

    public URI buildUri(String address) {
        UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(KAKAO_BASE_URL);
        uriBuilder.queryParam("query", address);
        URI uri = uriBuilder.build().encode().toUri();
        log.info("KakaoApiService.buildUri - address: [{}], uri: [{}]", address, uri);
        return uri;
    }

    public KakaoApiResponseDto searchAddress(String address) {
        if(ObjectUtils.isEmpty(address)) return null;
        URI uri = buildUri(address);
        HttpHeaders headers = new HttpHeaders();
        headers.set(HttpHeaders.AUTHORIZATION, "KakaoAK " + KAKAO_SECRET_KEY);
        return restTemplate
                .exchange(uri, HttpMethod.GET, new HttpEntity<>(headers), KakaoApiResponseDto.class)
                .getBody();
    }
}

Test 

 

  • Spock 라이브러리를 사용해 테스트 코드 작성
    • 한글주소를 인코딩하고 다시 디코딩한 결과가 원래 한글주소와 같은지 확인
class KakaoApiServiceTest extends Specification {

    private KakaoApiService kakaoService

    def setup(){
        kakaoService = new KakaoApiService()
    }

    def "buildUri"() {
        given:
            String 한글주소 = "서울 상도동"
            def charset = StandardCharsets.UTF_8

        when:
            def uri = kakaoService.buildUri(한글주소)
            def 인코딩 = uri.toString()
            def 디코딩 = URLDecoder.decode(인코딩, charset)

        then:
            디코딩 ==  "https://dapi.kakao.com/v2/local/search/address.json?query=" + 한글주소
    }
}

 

'Java > Spring' 카테고리의 다른 글

[Tableau] Plot #2  (0) 2022.11.10
[Spring] 게시판 만들기 #1  (0) 2022.11.07
[Spring] 길찾기 서비스 #3  (0) 2022.11.05
[Spring] 길찾기 서비스 #2  (0) 2022.11.05
[Spring] 길찾기 서비스 #1  (0) 2022.11.05