🔥 스파르타 TIL (프로젝트)

NAVER Geocoding API 사용해서 위도, 경도 추가하기

승승장규 2025. 3. 19. 23:26

원하는 주소에 원하는 데이터를 요청하는 과정에서 위도, 경도를 추가해야 하는 상황이 생겼다.

처음에는 위도, 경도를 같이 요청 보냈지만, 추후에 확장성과 주소를 수정해야 하는 상황이 생길 때마다 위도, 경도도 바꿔줘야 하는 불편함이 생길 것 같아서 주소를 입력하면 위도, 경도가 자동으로 추가될 수 있는 시스템을 만들기로 하였다.

 

우선 naver map을 사용하기 위해서 정보를 등록해야 한다.

 

 

NAVER CLOUD PLATFORM

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

www.ncloud.com

 

이 사이트에 접속해서 회원가입을 진행하고 로그인에 성공하면

 

오른쪽 상단에 콘솔이 뜨게 되는데 콘솔을 클릭하면 DashBoard를 볼 수 있다.

 

 

이제 여기서 왼쪽 사이드 바에 AI NAVER API를 볼 수 있는데, 세부사항에 Application을 클릭하게 되면 

 

Application을 등록할 수 있는 화면이 뜨게 된다. 이제 Application 등록을 클릭하면

 

여기서 서비스 설명/요금안내와 개발 가이드를 참고해서 내가 만드는 서비스에 필요한 기능을 체크박스에 체크를 통해 추가하면 된다.

이후 서비스 환경 등록에 redirect url을 작성하면 모든 준비가 끝나게 되고, client_id와 client_secret 키는 복사해서 잘 보관해 두면 된다.

 

public class GeocodingService {

    @Value("${naver.client-id}")
    private String clientId;

    @Value("${naver.client-secret}")
    private String clientSecret;

    @Value("${naver.geocode-url}")
    private String geocodeUrl;

    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

    public GeocodingService(RestTemplateBuilder builder) {
        this.restTemplate = builder.build();
        this.objectMapper = new ObjectMapper();
    }

    // 네이버 API로 주소를 좌표로 변환하는 메서드
    public double[] getCoordinates(String address) {
        try {
            // 요청 헤더 설정
            HttpHeaders headers = new HttpHeaders();
            headers.set("X-NCP-APIGW-API-KEY-ID", clientId);
            headers.set("X-NCP-APIGW-API-KEY", clientSecret);
            headers.setContentType(MediaType.APPLICATION_JSON);

            String requestUrl = geocodeUrl + "?query=" + address;

            // 요청 보내기
            HttpEntity<String> entity = new HttpEntity<>(headers);
            ResponseEntity<String> response = restTemplate.exchange(
                    requestUrl,
                    HttpMethod.GET,
                    entity,
                    String.class
            );
            String responseBody = response.getBody();

            // 응답 데이터가 있는지 테스트로 직접 확인
            JsonNode root = objectMapper.readTree(responseBody);
            if (root.has("addresses") && root.path("addresses").size() > 0) {
                double latitude = root.path("addresses").get(0).path("y").asDouble();
                double longitude = root.path("addresses").get(0).path("x").asDouble();
                return new double[]{latitude, longitude};
            } else if (root.has("status") && "OK".equals(root.path("status").asText())) {
                throw new IllegalArgumentException("실제 주소 정보가 없습니다.");
            }
            return new double[]{0.0, 0.0};

        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }
}

 

실제로 주소를 요청하면 이 비즈니스 로직을 통해 위도, 경도를 받아서 저장할 수 있다. 

 

{
"name": "강원특별자치도 센터", 
"address": "강원특별자치도 춘천시 중앙로 1"
}
{
  "status": "OK",
  "meta": {
    "totalCount": 1,
    "page": 1,
    "count": 1
  },
  "addresses": [
    {
      "roadAddress": "강원특별자치도 춘천시 중앙로 1 강원특별자치도청",
      "jibunAddress": "강원특별자치도 춘천시 봉의동 15 강원특별자치도청",
      "englishAddress": "1, Jungang-ro, Chuncheon-si, Gangwon-do, Republic of Korea",
      "addressElements": [
        {
          "types": [
            "SIDO"
          ],
          "longName": "강원특별자치도",
          "shortName": "강원특별자치도",
          "code": ""
        },
        {
          "types": [
            "SIGUGUN"
          ],
          "longName": "춘천시",
          "shortName": "춘천시",
          "code": ""
        },
        {
          "types": [
            "DONGMYUN"
          ],
          "longName": "봉의동",
          "shortName": "봉의동",
          "code": ""
        },
        {
          "types": [
            "RI"
          ],
          "longName": "",
          "shortName": "",
          "code": ""
        },
        {
          "types": [
            "ROAD_NAME"
          ],
          "longName": "중앙로",
          "shortName": "중앙로",
          "code": ""
        },
        {
          "types": [
            "BUILDING_NUMBER"
          ],
          "longName": "1",
          "shortName": "1",
          "code": ""
        },
        {
          "types": [
            "BUILDING_NAME"
          ],
          "longName": "강원특별자치도청",
          "shortName": "강원특별자치도청",
          "code": ""
        },
        {
          "types": [
            "LAND_NUMBER"
          ],
          "longName": "15",
          "shortName": "15",
          "code": ""
        },
        {
          "types": [
            "POSTAL_CODE"
          ],
          "longName": "24266",
          "shortName": "24266",
          "code": ""
        }
      ],
      "x": "127.7297500",
      "y": "37.8853990",
      "distance": 0
    }
  ],
  "errorMessage": ""
}

 

실제로 naver map api를 통해 x, y로 위도, 경도를 받아올 수 있다.

 

데이터베이스를 확인해 보면 

 

자동으로 위도, 경도가 입력된 것을 볼 수 있다. 향후 확장성과 데이터를 수정할 때 위도, 경도 데이터를 같이 수정하는 상황은 없기 때문에 이렇게 자동으로 변경시킨다면 많은 장점이 있을 것 같다.