페어 활동 기록_Day11_한빈_상준 - boostcampwm-2022/web33-Mildo GitHub Wiki

✂️ 분배된 이슈

  • 네이버 지도 API 연결
  • 지도 초기 화면을 서울 중심으로 출력

🚩 구현 목표

  • 사용자가 모바일 환경에서 네이버 지도 화면을 확인할 수 있어야 함
  • 기존 이슈를 적절하게 나눠서 세부 목표 작성
  • branch name : feature/map

🍀 세부 목표

Mildo에 네이버 지도 API 가져와서 보여주기(#5)

  • typescript 타입 설정을 위한 @types/navermaps 설치
  • 맵 관련 컴포넌트 생성
    • 맵을 그릴 DOM 요소 생성
    • map 옵션 설정하기(위치, 줌 등)
    • DOM에 네이버 지도 그려주기
  • 컴포넌트 렌더링 확인

MainPage 컴포넌트를 생성하고, 내부에 Map 컴포넌트 넣기(#10)

  • pages 디렉토리 및 MainPage.tsx 파일 생성
  • MainPage에 Map 컴포넌트 넣기
  • 반응형 스타일링 적용

사용자 위치에 따른 지도 초기 화면 설정(#11)

  • 브라우저에서 사용자 위치 정보 허용 요청
  • 지도 초기 화면이 서울 중심지인 경우
    • 사용자가 위치 정보 거부했을 때
    • 사용자의 위치가 서울 이외의 지역일 때
  • 지도 초기 화면이 사용자 위치인 경우
    • 사용자의 위치가 서울일 때
  • 지도 사용 가능 범위 서울로 제한
    • 서울 이외의 지역으로 이동 금지
    • 줌 기능 제한 걸기

🖥️ 구현 내용

Mildo에 네이버 지도 API 가져와서 보여주기(#5)

  • CRA로 작성된 불필요한 파일 삭제
  • createRoot로 index.tsx 리팩토링
  • App.tsx에 전역 스타일 적용
    • styled-components의 createGlobalStyle 사용
    • 프로젝트 전체의 기본 margin과 padding을 0으로 설정

MainPage 컴포넌트를 생성하고, 내부에 Map 컴포넌트 넣기(#10)

  • MainPage에 반응형 디자인을 위한 width, height 적용
    • width에는 vw, height에는 vh 사용
    • 자식 컴포넌트인 Map은 width, height 모두 100%로 설정

사용자 위치에 따른 지도 초기 화면 설정(#11)

  • Map.tsx에서 react-hook-geolocation 라이브러리로 사용자 위치의 위·경도 확인
    • 브라우저 접속 시 위치 정보 허용에 대한 팝업이 나타남
    • 허용 시 사용자 위치의 위·경도를 확인 할 수 있음
      • 서울일 경우 useState로 관리
      • 서울이 아니거나 거부할 경우 서울 중심지를 기본 값으로 보여줌
        • 현재 서울 중심지 기본 값 : 126.9769, 37.5656
    • 참고 사이트 : https://www.npmjs.com/package/react-hook-geolocation
  • 네이버 지도 API의 Reverse Geocoding으로 사용자 거주 지역(시군구) 확인
    • Reverse Geocoding은 위·경도를 사용해 사용자의 구체적인 거주 지역을 확인할 수 있음
    • 서울일 경우와 서울이 아닌 경우를 나눠서 처리

📖 학습 내용

네이버 지도 API Reverse Geocoding 사용 방법

  • 네이버 지도 API에서 Reverse Geocoding 사용 요청

  • 네이버 지도 URL로 get API 요청을 보냄

    // 입력 좌표 coords=128.12345,37.98776
    // 다른 파라미터는 공식 페이지 참고
    const url = `https://naveropenapi.apigw.ntruss.com/map-reversegeocode/v2/gc
    ?coords={입력_좌표}&sourcecrs={좌표계}&orders={변환_작업_이름}&output={출력_형식}`;
    
    axios.get(url, headers : {
    	// 앱 등록 시 발급받은 Client ID
    	X-NCP-APIGW-API-KEY-ID:{Client ID}
    	// 앱 등록 시 발급 받은 Client Secret
    	X-NCP-APIGW-API-KEY:{Client Secret}
    });
    
  • 요청 결과의 JSON 데이터에서 사용자의 지역을 확인

    {
        "status": {
            "code": 0,
            "name": "ok",
            "message": "done"
        },
        "results": [
            {
                "name": "roadaddr",
                "code": {
                    "id": "1114016700",
                    "type": "L",
                    "mappingId": "09140167"
                },
                "region": {
                    "area0": {
                        "name": "kr",
                        "coords": {
                            "center": {
                                "crs": "",
                                "x": 0.0,
                                "y": 0.0
                            }
                        }
                    },
                    "area1": {
                        "name": "서울특별시",
                        "coords": {
                            "center": {
                                "crs": "EPSG:4326",
                                "x": 126.9783882,
                                "y": 37.5666103
                            }
                        },
                        "alias": "서울"
                    },
                    "area2": {
                        "name": "중구",
                        "coords": {
                            "center": {
                                "crs": "EPSG:4326",
                                "x": 126.997602,
                                "y": 37.563843
                            }
                        }
                    },
                    "area3": {
                        "name": "정동",
                        "coords": {
                            "center": {
                                "crs": "EPSG:4326",
                                "x": 126.972925,
                                "y": 37.5664
                            }
                        }
                    },
                    "area4": {
                        "name": "",
                        "coords": {
                            "center": {
                                "crs": "",
                                "x": 0.0,
                                "y": 0.0
                            }
                        }
                    }
                },
                "land": {
                    "type": "",
                    "number1": "101",
                    "number2": "",
                    "addition0": {
                        "type": "building",
                        "value": "시청역 1호선"
                    },
                    "addition1": {
                        "type": "zipcode",
                        "value": "04519"
                    },
                    "addition2": {
                        "type": "roadGroupCode",
                        "value": "111402005001"
                    },
                    "addition3": {
                        "type": "",
                        "value": ""
                    },
                    "addition4": {
                        "type": "",
                        "value": ""
                    },
                    "name": "세종대로",
                    "coords": {
                        "center": {
                            "crs": "",
                            "x": 0.0,
                            "y": 0.0
                        }
                    }
                }
            }
        ]
    }
    
  • 참고 사이트

‘openweathermap’으로 Reverse Geocoding 구현

  • 지도 URL로 get API 요청을 보냄
    • https://naveropenapi.apigw.ntruss.com/map-reversegeocode/v2/gc?coords=${geolocation.latitude},${geolocation.longitude}&sourcecrs=epsg:4326&orders=roadaddr&output=json
  • console에서 사용자의 거주 지역을 영어로 받아온 것을 확인

오산시

🚧 Trouble Shooting

Mildo에 네이버 지도 API 가져와서 보여주기(#5)

  • 문제 1

    • 원인 : ‘new’를 사용하여 새로운 인스턴스를 생성하였으나, 변수에 할당하지 않아 에러 발생

      • Map 컴포넌트의 Dom에 네이버 지도를 그려주기 위해서는 해당 문법을 사용하는데, 변수에 할당할 필요는 없었음
      [eslint] 
      src\components\Map.tsx
        Line 29:5:  Do not use 'new' for side effects  no-new
      
      Search for the keywords to learn more about each error.
      ERROR in [eslint] 
      src\components\Map.tsx
        Line 29:5:  Do not use 'new' for side effects  no-new
      
      Search for the keywords to learn more about each error.
      
      webpack compiled with 1 error
      No issues found.
      
    • 해결 방법 : 즉시 실행 함수로 ‘new’ 키워드를 사용함과 동시에 할당되지 않도록 설정

      (() => new naver.maps.Map(mapRef.current, mapOptions))();
      
  • 문제 2

    • 원인 : null에 해당 타임을 할당할 수 없다는 에러 발생

      ERROR in src/components/Map.tsx:29:31
      TS2345: Argument of type 'null' is not assignable to parameter of type 'string | HTMLElement'.
          27 |     // if (!mapRef.current || !naver) return;
          28 |
        > 29 |     (() => new naver.maps.Map(mapRef.current, mapOptions))();
             |                               ^^^^^^^^^^^^^^
          30 |   }, []);
          31 |
          32 |   return <MapComponent ref={mapRef} />;
      
    • 해결 방법 : 조건문을 사용해서 해당 변수가 null인 경우 리턴

      • let으로 할당하는 경우가 있으나 데이터의 무결성 문제로 사용하지 않음

사용자 위치에 따른 지도 초기 화면 설정(#11)

  • 문제 1
    • 원인 : client에서 네이버 지도 API Reverse Geocoding 요청 시 CORS 에러 발생
    • 해결 방법 1
      • openweathermap으로 구현할 시 client에서 Reverse Geocoding 요청을 할 수 있음
      • 그러나 외국 사이트여서 그런지 속도가 현저하게 느림
    • 해결 방법 2
      • server에서 네이버 지도 API 관련 router를 만들어서 사용
      • 속도는 빠르나 결국 CORS 에러 처리를 해줘야 함
    • 결론
      • 네이버 지도 API를 계속해서 사용하기
      • 제공하는 기능이 많아 서비스가 확대될 때 용이
      • 속도가 빠름
      • 한 달에 300만회까지는 Reverse Geocoding API 요청이 무료임

🎸 기타