#3 Naver Geocoding API 적용

2eoseo·2021년 3월 31일
5

목적

출발지와 목적지 주소를 입력하여 해당 주소 근처의 따릉이 정류소를 보여주기 위해 네이버 지도 API를 쓰기로 했다.

네이버 지도 API에서 제공하는 여러 API 중 Geocoding API를 사용하면 유저가 입력한 주소의 위도, 경도 좌표 값을 알아낼 수 있다.

네이버 지도 API의 상세기능을 보면 제공하는 여러 API에 대한 설명을 볼 수 있다. Naver Geocoding API는

주소의 텍스트를 입력받아 좌표를 포함한 상세정보들을 제공합니다.

이렇게 설명되어 있다.

일단, API를 사용하기 전에 서비스를 제공하는 네이버 클라우드 플랫폼의 콘솔에서 애플리케이션 등록을 해야한다. 등록 화면에서 애플리케이션 이름을 쓰고 아래 스크린샷처럼 필요한 API를 체크한 뒤, 개발을 진행하는 웹 서비스 URL을 추가해주면 된다. 나는 localhost:3000에서 쓰려고 하기 때문에 http://localhost:3000을 추가해주었다.

애플리케이션 등록을 하고나면 해당 애플리케이션의 인증 정보를 볼 수 있는데 여기에서 프로젝트에 환경 변수로 등록해야 하는 2개의 키를 확인할 수 있다

  1. Client ID (X-NCP-APIGW-API-KEY-ID)
  2. Client Secret (X-NCP-APIGW-API-KEY)

이 2개의 키를 환경 변수에 적절한 이름으로 등록해 놓았다.

참고로 웹뿐만 아니라 안드로이드/iOS 앱에서도 API를 쓸 수 있다.

CORS 정책 위반

Geocoding API 참조서에 친절하게 적힌 API 사용 방법에 따라 fetch API로 좌표값을 가져오려고 했다. 그런데 프론트엔드 개발자라면 흔히 볼 수 있는 CORS 정책 위반 경고 표시가 뜨면서 정보를 가져올 수 없었다.

CORS(Cross-Origin Resource Sharing) 정책 위반은 다른 출처를 가진 URL에 리소스 요청을 할 때 발생한다.

아래 사진에 URL을 구성하는 요소들이 나와 있는데, 여기서 요청을 하는 URL과 요청을 받는 URL의 Protocol, Host(+ Port)가 다르면 다른 출처로 인지하여 서로 통신을 하지 못하게 한다. 이런 정책이 있는 이유는 아무나 웹페이지의 소스코드를 읽고 다른 사용자의 개인정보를 탈취하거나 부정한 방법으로 API를 사용할 수도 있기 때문이다. 게다가 이런 정책이 없는데 나처럼 다른 회사의 API를 사용하고 과금이 되는 서비스까지 이용하게 된다면 악의로 사용된 API 요청 건까지 요금이 처리될 수도 있다.

물론, 서버 측에서 조건 없이 승인을 하면 통신할 수 있는 것이 맞는데, CORS 정책 위반 여부는 브라우저에서 확인하는 것이라 어찌되었든 같은 출처를 가지게 만들던가 서버 측에서 Access-Control-Allow-Origin에 요청하는 웹사이트의 URL을 담은 응답을 보내주게 만들어야 한다.

네이버 개발자 포럼에 올라온 CORS 관련 질문의 답변을 보면 해결할 수 있는 방법을 알려준다.

그러면 지금 만드는 프로젝트에 서버를 만들고 거기에서 API 호출을 할 수 있도록 만들어야 하는데, 일단 프록시 서버를 이용하여 해결할 수 있는 방법(로컬 환경에 한해서만)을 찾아 어떤 식으로 작동되는건지 알아보기 위해 적용해보았다.

프록시 서버 적용

npm install http-proxy-middleware axios

http-proxy-middleware 모듈을 사용하면 src/setupProxy.js에 작성한 것처럼 https://naveropenapi.apigw.ntruss.com/api로 설정하여 프록시로 호출할 수 있게 만들어준다.

axios는 나중에 요청 취소를 하는 기능도 추가할 것 같아 fetch API 대신 사용해보려고 설치했다.

API 호출

// navermaps.js
import axios from "axios";

const geocodingUrl = "/api/map-geocode/v2/geocode";

export async function geocoding(query) {
  const coord = await axios
    .get(`${geocodingUrl}`, {
      params: {
        query,
      },
      headers: {
        "X-NCP-APIGW-API-KEY-ID": `${process.env.REACT_APP_NCP_CLIENT_ID}`,
        "X-NCP-APIGW-API-KEY": `${process.env.REACT_APP_NCP_CLIENT_SECRET}`,
      },
    })
    .then(res => {
      // TODO: check if response is ok
      return res.data;
    })
    .then(data => {
      if (data.addresses.length > 1) {
        console.log(`${query}에는 여러 주소가 있어요.`);
      } else if (data.addresses.length === 0) {
        console.log(`${query}에 해당되는 좌표가 없어요.`);
        return [-1, -1];
      }
      return [data.addresses[0].x, data.addresses[0].y];
    });

  return coord;
}

geocoding 함수를 App.js에서 호출하면 입력한 출발지, 목적지의 좌표 값을 가져오게 만들었다.

한계

원래 위치를 검색할 때 우리에게 익숙한 상호명으로 좌표값을 가져오려고 했는데, Geocoding API에서는 행정, 법정 주소로만 좌표값을 알아낼 수 있다. 그래서 일단은 입력한 주소로 좌표값을 가져오는 것으로 만들려고 한다. 그래서 실제로 사용할 때는 불편함이 있을 것 같다. 나중에 상호명으로 좌표값을 가져올 수 있는 방법이 있는지 찾아봐야겠다.

-참고자료-
CORS는 왜 이렇게 우리를 힘들게 하는걸까?
React로 영화 정보를 검색해보자 - 두번째 네이버 API 사용 / CORS 설정 하기

2개의 댓글

comment-user-thumbnail
2021년 6월 17일

잘 읽어봤어요. CORS 에러 해결을 위해 http-proxy-middleware 코드도 같이 첨부되어있었으면 더 좋았겠어요.
Naver Cloud API 는 문서화가 잘 되어있는데 CORS 이슈 때문에 이글을 보게되었습니다.

1개의 답글