[Project] React + JavaScript Naver Map Directions 5 API (1) - 요구사항 및 학습정리

SEONDY·2024년 11월 3일

Project

목록 보기
5/9
post-thumbnail

[Project] React + JavaScript Naver Map Directions 5 API (1) - 요구사항 및 학습정리

해결되지 않은 문제가 있어 수정 예정인 포스트입니다.😹

  • 프로젝트 주요 기능 중 하나인 관광지 경로 표시
    프로젝트를 진행하며, 관광지를 연결하는 경로 생성이 필요했다.
    네이버 Map API를 프론트엔드에서 관리했기 때문에, 추천 경로 또한 프론트엔드에서 네이버 Map API 요청을 통해 만드는 것으로 결정했다.
  • 페이지 컴포넌트가 유형에 따라 조금씩 바뀌는 부분이 있었다.
    컴포넌트를 재사용하기 위해 type을 넘겨주고, 해당 type에 따라 페이지의 구성과 API 요청을 다르게 설정하는 것이 필요했다.
  • 한 번에 모든 것을 진행하는 데 어려움을 느꼈기 때문에, 벨로그를 작성하며 요구 사항에 맞게 차근차근 진행하려 한다.

1. 요구 사항

  • 프로젝트에서 경로를 보여주는 페이지는 유형이 세 가지이다. (컴포넌트 재사용)
    이 페이지로 넘어올 때, routeType을 함께 전송해서 각 유형을 구분했다. (이유 : routeType에 따라 UI와 API 요청해야 하는 부분에 차이가 있었다.)
    • routeType은 다음과 같이 이전 페이지에서 navigate로 보내줬다.
      // routeType => SERVICE : 서비스 제공 루트 / CUSTOM : 사용자 커스텀 루트 / DONE : 만들어진 사용자 커스텀 루트
      navigate(`/route/${data.id}`, { state: { routeType: "SERVICE" } });

경로 유형 & 요구 사항

  1. 서비스에서 제공하는 경로 (routeType : SERVICE)
    홈 화면에서 백엔드 API 요청으로 받아온 경로 리스트 중, 하나의 요소를 선택했을 때, 해당 경로 데이터를 가지고 페이지로 이동한다.

    • 서비스 제공 경로일 때는 경로 추천을 하지 않는다.
      즉, 이미 정해져 있는 경로를 제공 (추천 경로를 만드는 과정을 거치지 않아도 된다.)
    • 이 페이지에서는 경로를 편집하는 것도 불가능하다.
      SERVICE 유형일 때는, 사용자에게 많은 권한을 주지 않는다. 해당 경로 북마크 저장 및 해제만 가능하다.
    • SERVICE 유형에서 필요한 Map API 요청은,
      • Map 섹션에 지도를 띄워준다. + 넘어온 경로 데이터를 routeData에 담아준다. (유형에 상관없이 동일)
      • Marker + Polyline으로 경로를 Map 섹션에 띄워준다.
      • 주어진 경로 간 거리 계산을 위한 Directions 5 API
        UI의 이정표 부분에 거리를 띄워줘야 했기 때문에 사용했다.
    • Marker + PolylineDirections API의 순서는 상관 없음
  2. 사용자가 만드는 경로 (routeType : CUSTOM)
    내 여행 화면의 장소 섹션에서 북마크한 장소를 선택하여 경로 만들기를 했을 때, 해당 경로 데이터를 가지고 페이지로 이동한다. (첫 번째로 선택한 장소가 출발지)

    • 사용자가 선택한 장소를 기반으로 경로를 제공한다. (추천 경로를 만드는 과정이 필요)
    • 페이지로 넘어오는 최초 1회에 한하여 추천 경로를 만든다.
      사용자가 주어진 추천 경로를 편집했을 경우에는 추가 변경이 필요하지 않다.
    • 이 페이지에서는 경로를 편집하는 것이 가능하다.
      사용자가 경로를 편집하고 저장하는 것이 가능하다.
    • 필요 시 추천 경로를 수정한 후, 저장을 누르면 백엔드에 API 요청한다.
    • CUSTOM 유형에서 필요한 Map API 요청은,
      • Map 섹션에 지도를 띄워준다. + 넘어온 경로 데이터를 routeData에 담아준다. (유형에 상관없이 동일)
      • 경로를 만들기 위한 Directions 5 API
        추천 경로 만들기 + UI의 이정표에 거리를 띄워주기 위함
      • Marker + Polyline으로 경로를 Map 섹션에 띄워준다.
    • 추천 경로 만들기
      사용자가 첫 번째로 선택한 장소 : 출발지
      • 출발지를 기준으로 나머지 장소와의 거리를 계산한다. (Directions 5 API 활용)
        출발지와 가장 가까운 장소를 다음 경로로 지정한다.
      • 이후, 마지막 경로 -1 까지 이를 반복한다. (마지막 장소는 정해져 있으므로)
        ex) 1번 출발지를 기준으로 가장 가까운 장소가 3번이라면, 3번을 기준으로 (1번을 제외한) 나머지 장소와의 거리를 계산, 가장 가까운 장소를 다음 경로로 지정
  1. 사용자가 만든 경로 (routeType : DONE)
    내 여행 화면의 경로 섹션에서 사용자가 만든 경로를 선택하면, 해당 경로의 key 값을 가지고 페이지로 이동한다.

    • 만든 경로일 때는 경로 추천을 하지 않는다.
      즉, 이미 저장한 경로를 제공 (추천 경로를 만드는 과정을 거치지 않아도 된다.)
    • 페이지에서 key 값을 가지고 경로 데이터를 백엔드 API에 요청한다.
    • CUSTOM 타입의 기존 저장 버튼 위치에 삭제 버튼이 필요하다.
    • 이 페이지에서는 경로를 편집하는 것이 가능하다.
      사용자가 경로를 편집하고 저장하는 것이 가능하다.
    • DONE 유형에서 필요한 Map API 요청은, (SERVICE와 동일)
      • Map 섹션에 지도를 띄워준다. + 넘어온 경로 데이터를 routeData에 담아준다. (유형에 상관없이 동일)
      • Marker + Polyline으로 경로를 Map 섹션에 띄워준다.
      • 주어진 경로 간 거리 계산을 위한 Directions 5 API
        UI의 이정표 부분에 거리를 띄워줘야 했기 때문에 사용했다.
    • Marker + PolylineDirections API의 순서는 상관 없음

  • 각 유형의 요구사항에 대해 정리했다. 내용을 정리하기 전 까지는, 유형이 2개만 필요하다고 생각했다. (SERVICE & CUSTOM)
    그런데 각 내용을 정리하다 보니, 이미 저장된 경로에 대한 UI + API 요청이 필요하다는 것을 알게 되었다. (이해한 내용을 정리하는 것의 중요성을 다시 한 번 느낌🥲)

2. Directions 5 API

모든 유형에 공통적으로 사용되는 API를 학습한 후 구현을 진행하려 한다.

  • 요청을 위해서 쿼리 파라미터로 넘겨줘야 하는 정보가 있다.
    Directions 5 API 문서에 접속하면 자세히 확인할 수 있는데, 필수 쿼리 파라미터 + 사용할 쿼리 파라미터는 다음과 같다!

    필드타입필수 여부설명
    startString필수출발지(경도,위도) (start=경도,위도)
    goalString필수목적지(경도,위도) (goal=경도,위도)
    waypointsString선택경유지(경도,위도) (waypoints=경도,위도)
    • goal은 ':'로 구분하여 최대 10개의 목적지 입력 가능하다.
      입력한 목적지 중 가장 적은 비용으로 도달할 수 있는 목적지에 대한 경로를 조회한다.
    • waypoints는 '| (Pipe char)'로 구분하여 최대 5개의 경유지 입력 가능하다.
  • 해당 문서를 제대로 읽지 않아서 발생한 문제
    직접 요청하고 확인해봐야 알겠지만, 나는 각 장소의 거리를 하나하나 요청해서 받아오려고 했다. 그런데 goal 필드의 설명을 보니, 여러 개의 목적지를 보내서 최적(비용이 가장 적게 드는)의 경로를 return 받을 수 있다면... 생각보다 더 간단하게 구현할 수 있을 것이라고 생각한다.

API 테스트

  • 테스트를 위해 임시로 설정해 놓은 경로를 바탕으로 Map API 요청을 보냈다.
    axios
    .get("https://naveropenapi.apigw.ntruss.com/map-direction/v1", {
    params: {
      start: `${routeData[0].lat},${routeData[0].lng}`,
      goal: routeData
      .slice(1)
      .map((data) => `${data.lat},${data.lng}`)
      .join(":"),
    },
    headers: {
      "x-ncp-apigw-api-key-id": "발급받은 ID",
      "x-ncp-apigw-api-key": "발급받은 Secret",
    },
    })
    .then((response) => {
    console.log("데이터", response.data);
    })
    .catch((error) => console.log("Error", error));
    goal 파라미터로 routeData의 경도와 위도를 :로 이어서 보내려고 했다.
    그런데 오류가 발생해 response를 받을 수 없었다.

3. Directions 5 API 요청에서 만난 오류

API 테스트를 진행했을 때 발생한 첫 번째 문제 : CORS 문제

네이버 API URL과 내가 작업하는 URL(localhost)이 일치하지 않기 때문에 발생한 문제이다.

  • 이를 해결하기 위해서 프록시 설정을 했다.
    프록시 서버란? : 인터넷 상의 여러 네트워크들에 접속할 때 중계 역할을 해주는 프로그램 또는 컴퓨터

    • 참고한 글 1

    • 참고한 글 2

      package.json에 proxy를 추가했다.

      추가하고, get 요청을 .get("/map-direction/v1", { 이렇게 보냈는데!
      나는 왜... html을 반환하는걸까? 콘솔에 찍어보면 html 내용이 보인다.

  • 그런데 결국 이렇게 설정한 것은, CORS를 개발환경에서만 해결하는 것이라고 한다.
    http-proxy-middleware를 설치해 프록시 서버를 설정해도 배포를 한 후에는 적용되지 않는다고... (추가 확인 필요🥲)

  • 백엔드 개발자님께 질문을 남긴 상태이다...😹😹😹
    해결한 후 글을 수정하고, 유형1(routeType : SERVICE)을 구현할 예정이다.



참고 사이트

2개의 댓글

comment-user-thumbnail
2025년 9월 1일

혹시 cors문제 어떤식으로 해결하셨는지 알 수 있을까요?? 저도 같은 문제에 막혀서 궁금합니다!

1개의 답글