[Spring] 네이버 지도 길찾기 URL 제공 API

    728x90

    유저가 지정한 장소에 대해 네이버 지도앱의 길찾기 redirect URL을 구현하였다.

     

    먼저 네이버 지도앱의 길찾기 URL을 확인하였다.

    nmap://route/public?dlat={도착지 위도}&dlng={도착지 경도}dname={도착지 이름}

     

    위 URL을 만들기 위해 위/경도를 가져와야 했는데, 이 부분은 네이버 지도 api 중 geocoding을 활용하였다. 자세한 설명은 아래 공식문서를 확인하자

    https://api.ncloud-docs.com/docs/ai-naver-mapsgeocoding

     

    Geocoding 개요

     

    api.ncloud-docs.com

     

    Geocoding 사용법

    아래 내용은 위/경도 를 가져오기 위해 사용한 방법으로, URL을 만드는 것과는 연관성이 없다.

     

    현재 네이버 지도 api는 naver cloud platform에 속해있다. 따라서 회원가입을 진행해야 한다. (23년 7월 기준으로 나중에 또 바뀔거 같다. 자주 바뀌는듯..)

    https://www.ncloud.com/?language=ko-KR 

     

    NAVER CLOUD PLATFORM

    cloud computing services for corporations, IaaS, PaaS, SaaS, with Global region and Security Technology Certification

    www.ncloud.com

    로그인 후 대시보드에서 AI·NAVER API 를 클릭한다.

    그후 아래 화면에서 파란색 application 등록을 통해 새로 만들어준다. (staticMap도 사용할 줄 할고 해두었는데 사용하지 않았다.)

    추가로, 네이버가 maps api를 모두 유료화하였기 때문에 무료이용량 횟수를 잘 보고 한도 횟수를 제한해두는 것이 좋을 것 같다.

     

    현재 service는 아래와 같이 구현하였다. exception 일부는 또 수정해야 할 것 같다.

    @Slf4j
    @RequiredArgsConstructor
    @Service
    public class MapService {
    
        @Value("${api.naver-client-id}")
        String clientId;
    
        @Value("${api.naver-client-secret}")
        String clientSecret;
    
        public String getMapUrl(String reqLocation) throws BaseException {
    
            String resultUrl = null;
            try {
                String address = reqLocation;
                String addr = URLEncoder.encode(address, "UTF-8");
    
                log.debug("address = {}", address);
    
                String apiURL = "https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode?query=" + addr;
    
                URL url = new URL(apiURL);
                log.debug("url = {}", url);
                HttpURLConnection con = (HttpURLConnection) url.openConnection();
                con.setRequestMethod("GET");
    
                con.setRequestProperty("X-NCP-APIGW-API-KEY-ID", clientId);
                con.setRequestProperty("X-NCP-APIGW-API-KEY", clientSecret);
    
                int responseCode = con.getResponseCode();
    
                BufferedReader br;
    
                if (responseCode == 200) {
                    br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
                } else {
                    br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
                }
    
                String inputLine;
                StringBuffer response = new StringBuffer();
    
                while ((inputLine = br.readLine()) != null) {
                    response.append(inputLine);
                }
    
                br.close();
    
                ObjectMapper objectMapper = new ObjectMapper();
                log.debug("response = {} response.string = {}", response, response.toString());
    
                JsonNode jsonNode = objectMapper.readTree(response.toString());
                log.debug("jsonNode = {}", jsonNode);
                JsonNode addressesNode = jsonNode.get("addresses");
                log.debug("addressesNode = {}", addressesNode);
    
                if (addressesNode != null && addressesNode.isArray()) {
                    for (JsonNode addressNode : addressesNode) {
                        String roadAddress = getParsedUrl(addressNode.get("roadAddress").asText());
    //                    String jibunAddress = addressNode.get("jibunAddress").asText();
                        String latitude = addressNode.get("y").asText();
                        String longitude = addressNode.get("x").asText();
    
                        log.debug("latitude = {} and longitude = {}", latitude, longitude);
                        resultUrl = "nmap://route/public?dlat=" + latitude + "&dlng=" + longitude + "&dname=" + roadAddress;
                    }
                }
            } catch (UnsupportedEncodingException e) {
                log.debug("UnKnownAddrException 발생 ");
                throw new BaseException(ResponseStatus.UNKNOWN_ADDR);
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return resultUrl;
        }
    
        public String getParsedUrl(String roadAddress) throws UnsupportedEncodingException {
            String[] words = roadAddress.split(" ");
            String last_addr = words[words.length - 1];
            return URLEncoder.encode(last_addr, "UTF-8");
        }
    
    }

    일단은 쿼리스트링을 통해 정확한 주소를 입력받도록 하였는데, 완전 정확한 주소가 아니면 출력이 되지 않는 문제가 있어 이는 나중에 다시 해결해야 할 것 같다. 아마 카카오 api 로 변경해서 가져오도록 할 예정이다. 

     

    현재 해당 코드는 카카오 api를 통해 유저가 지정한 location(ex. 아산병원)에 대해 그 장소에 대한 좌표를 확인하고, 그 값을 쿼리스트링으로 보내도록 하였다. 아래는 서비스단의 코드이다.

    @Slf4j
    @RequiredArgsConstructor
    @Service
    public class MapService {
    
        @Value("${api.kakao-rest-api-key}")
        String restApiKey;
    
        public String getMapUrl(String reqLocation) throws BaseException {
    
            String resultUrl = null;
            try {
                String address = reqLocation;
                String addr = URLEncoder.encode(address, "UTF-8");
    
                log.debug("address = {}", address);
    
                // Geocoding 개요에 나와있는 API URL 입력.
                String apiURL = "https://dapi.kakao.com/v2/local/search/keyword.json?page=1&size=1&sort=accuracy&query="+addr;
    
                URL url = new URL(apiURL);
                log.debug("url = {}", url);
                HttpURLConnection con = (HttpURLConnection) url.openConnection();
                con.setRequestMethod("GET");
    
                // 헤더
                con.setRequestProperty("Authorization", "KakaoAK " + restApiKey);
    
                // 요청 결과 확인. 정상 호출인 경우 200
                int responseCode = con.getResponseCode();
    
                BufferedReader br;
    
                if (responseCode == 200) {
                    br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
                } else {
                    br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
                }
    
                String inputLine;
                StringBuffer response = new StringBuffer();
    
                while ((inputLine = br.readLine()) != null) {
                    response.append(inputLine);
                }
    
                br.close();
    
                ObjectMapper objectMapper = new ObjectMapper();
                log.debug("response = {} response.string = {}", response, response.toString());
    
                JsonNode jsonNode = objectMapper.readTree(response.toString());
                log.debug("jsonNode = {}", jsonNode);
                JsonNode itemsNode = jsonNode.get("documents");
                log.debug("documents = {}", itemsNode);
    
                if (itemsNode != null && itemsNode.isArray() && itemsNode.size() > 0) {
                    JsonNode firstItem = itemsNode.get(0);
                    String mapx = firstItem.get("y").asText();
                    String mapy = firstItem.get("x").asText();
    
                    log.debug("mapx = {} and mapy = {}", mapx, mapy);
                    resultUrl = "nmap://route/public?dlat=" + mapx + "&dlng=" + mapy + "&dname=" + addr;
                }
            } catch (UnsupportedEncodingException e) { // 에러가 발생했을 때 예외 status 명시
                log.debug("UnKnownAddrException 발생 ");
                throw new BaseException(ResponseStatus.UNKNOWN_ADDR);
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return resultUrl;
        }

    댓글