UriComponent Builder, Kakao map API 를 통한 geo coding

JungWooLee·2022년 8월 3일
0

SpringBoot ToyProject

목록 보기
3/14
post-thumbnail

이어서 진행하기

나의 좌표 X, Y 알아오기

첫번째로 음식점 정보를 갖고오고자 할때 필수적인 파라미터로 위도, 경도 좌표가 필수가 된다

자동으로 인덱스페이지 접속시 위도 경도를 매핑하는 것을 생각했었는데 그 부분을 해결하지 못해 STACK OVERFLOW에 질문을 등록한 상태이다.

만약 방법이 있다 하더라도 현재 좌표가 아닌 다른 좌표 근처의 음식점 정보를 얻고자 하는 경우가 있기에 지오코딩을 이용한 주소값 불러오기를 테스트 후 적용시키고자 한다

지오코딩(GEOCODING)

지오코딩이란 고유 명칭(주소 등)을 가지고 위도와 경도의 좌표값을 얻는 것을 의미한다.
구글의 지오코딩과 카카오와 비교해보았는데 빌링 정보도 입력하여야 하는 구글은 다소 손이 갈것같아 카카오로 선택!

  • Kakao Geocode API 활용
  1. 회원가입, 키 발급
    https://developers.kakao.com/ 에서 내 애플리케이션 생성 후 승인키를 발급 받을 수 있다.

  1. 발급후 간단하게 POSTMAN 에서 테스트

Query Parameter : 에 검색하고자 하는 도로명 주소를 입력 후
header
- key : Authorization
- value : KakaoAK (한칸띄고) {REST API키 or Admin키}

KakaoAk={key} 로 계속 실패해서 삽질을 다소 하였지만 잘 동작하는것을 확인

다만 걱정인것이 1:1 매핑이 되질 않는다는 점인데 이부분에 대해서는 도로명이 아닌 예전 주소로 해결할 수 있을지 모르겠다.
프론트 단에서 지도를 띄워 설정하도록 할것이니 이부분은 프론트 작업이후로 보류 해둘것 같다

  1. Spring Boot 에서 테스트

Service

public interface RestaurantService {
    void getRestaurantData(String url);
    void getRestaurantDetail(String url);

    void getXY(String query); //  지오코딩을 통한 x,y 좌표구하기
}

Properties

부트에서는 properties 의 이름을 application-xxx.properties 로 만들게 되면 xxx라는 이름의 profile 이 생성되어 이를 통해 관리 할 수 있습니다. 즉, profile = xxx 라는 식으로 호출하면 해당 properties의 설정들을 가져올 수 있습니다.

API KEY 와 같은 민감 정보들은 프로퍼티로 관리하여 git ignore 설정 후 타인이 접근하지 못하도록 막기위해 사용되었습니다

차후 OAuth 관련 프로퍼티들을 생성할때에 자주 사용될 예정입니다

Impl

	@Override
    public void getXY(String query) {
            Float[] coordinate = new Float[2];
            String apiUrl = "https://dapi.kakao.com/v2/local/search/address.json";
            String jsonString = null;

            try {
                query = URLEncoder.encode(query, "UTF-8");

                String address = apiUrl + "?query=" + query;

                URL url = new URL(address);
                URLConnection conn = url.openConnection();
                conn.setRequestProperty("Authorization", authorization_key);

                BufferedReader rd = null;
                rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
                StringBuffer docJson = new StringBuffer();

                String line;

                while ((line = rd.readLine()) != null) {
                    docJson.append(line);
                }

                jsonString = docJson.toString();
                rd.close();

                JSONObject jsonObject = new JSONObject(jsonString);
                JSONArray documentsArray = jsonObject.getJSONArray("documents");
                JSONObject documentsObject = documentsArray.getJSONObject(0);

                String longtitude = documentsObject.getString("x");
                String latitude = documentsObject.getString("y");

                coordinate[0] = Float.parseFloat(longtitude);
                coordinate[1] = Float.parseFloat(latitude);

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

Test

  • 보통 쿼리 param 으로 url을 통한 Request 시에 파라미터를 인코딩해주어야 합니다.

    포스트맨에서 실험시

  • 하지만 UriComponetsBuilder 를 통하여 생성된 파라미터는 자동으로 인코딩이 되기에 따로 인코딩하는 과정을 생략하였습니다

  • 이전에 프로퍼티에 저장하였던 api key같은 경우 아래의 방법과 같이 불러올 수 있습니다

@Value("${kakaoAk.key}")
private String authorization_key;

디버깅 후 파싱을 진행
보통은 분기점을 걸어두고 파싱하기전에 입력창을 통하여 몇번 시도를 거치는 편입니다;;

파싱된 JsonObject 에서 x,y 좌표를 받아올 것입니다.


기존 네이버지도를 통한 좌표값은 소수점아래 7자리를 받는 것을 알 수 있기에 7자리만 받도록 합니다

마지막으로 최종 점검 Test

	@Value("${kakaoAk.key}")
    private String authorization_key;
    private final Logger log = LoggerFactory.getLogger(this.getClass().getSimpleName());
    
    
    @Test
    public void givenRouteReturnXY() throws Exception{
        //given
        String route = "양덕로 60";
        String url = "https://dapi.kakao.com/v2/local/search/address.json";
        UriComponents uri = UriComponentsBuilder.newInstance()
                .fromHttpUrl(url)
                .queryParam("query",route)
                .build();

        //when
        HttpHeaders httpHeaders = utility.getDefaultHeader();
        httpHeaders.add("Authorization", String.format("KakaoAK %s",authorization_key));
        HttpEntity requestMessage = new HttpEntity(httpHeaders);
        ResponseEntity response = restTemplate.exchange(
                uri.toUriString(),
                HttpMethod.GET,
                requestMessage,
                String.class);
        //then
        JSONObject datas = new JSONObject(response.getBody().toString());
        JSONObject addressData = datas.getJSONArray("documents").getJSONObject(0).getJSONObject("address");
        double x = Math.round(Double.parseDouble(addressData.getString("x")) *10000000)/10000000.0;
        double y = Math.round(Double.parseDouble(addressData.getString("y")) *10000000)/10000000.0;
        log.info("x는 "+x);
        log.info("y는 "+y);
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
    }

0개의 댓글