페어 활동 기록_Day12_한빈_상준 - boostcampwm-2022/web33-Mildo GitHub Wiki
✂️ 분배된 이슈
- 지도 초기 화면을 서울 중심으로 출력
🚩 구현 목표
- 사용자가 모바일 환경에서 네이버 지도 화면을 확인할 수 있어야 함
- 기존 이슈를 적절하게 나눠서 세부 목표 작성
- branch name : feature/map
🍀 세부 목표
사용자 위치에 따른 지도 초기 화면 설정(#11)
- 브라우저에서 사용자 위치 정보 허용 요청
- 지도 초기 화면이 서울 중심지인 경우
- 사용자가 위치 정보 거부했을 때
- 사용자의 위치가 서울 이외의 지역일 때
- 지도 초기 화면이 사용자 위치인 경우
- 사용자의 위치가 서울일 때
지도 반경 제한하기(#13)
- 네이버 지도 API 옵션(maxBounds, minZoom) 사용법 숙지하기
- 서울 이외의 지역으로 이동 금지
- 줌 기능 제한 걸기
로딩 화면 보여주기(#14)
- 로딩 컴포넌트 생성
- 이미지 주소를 URL 기반으로 비동기 처리
- 좌표 및 위치 로직을 Map에서 MainPage로 이동
- 좌표 위치에 따른 로딩 컴포넌트 or 맵 컴포넌트 렌더링 구현
🖥️ 구현 내용
사용자 위치에 따른 지도 초기 화면 설정(#11)
- 네이버 지도 API의 Reverse Geocoding으로 사용자 거주 지역(시군구) 확인
- Reverse Geocoding은 위·경도를 사용해 사용자의 구체적인 거주 지역을 확인할 수 있음
- 네이버 지도 API는 client에서 요청 시 cors가 의도적으로 발생함
- BE에서 네이버 API 관련 router를 생성하여 우회적으로 해당 정보를 가져옴
- server/src/apis/routers/naver.router.ts
- 요청 헤더에 필요한 정보는 .env 파일에 저장
- 지역에 따른 초기 화면 설정 구현
- Reverse Geocoding의 반환 값이 ‘서울특별시’이거나 ‘과천시’인 경우 해당 위치를 초기 화면으로 설정
- 주요 장소 50곳 중 서울대공원은 과천시에 위치하고 있음
- 이외의 지역일 경우 시청역으로 초기 화면 설정
- Reverse Geocoding의 반환 값이 ‘서울특별시’이거나 ‘과천시’인 경우 해당 위치를 초기 화면으로 설정
지도 반경 제한하기(#13)
- 네이버 지도 API 렌더 옵션으로 maxBounds, minZoom 값을 넣어주면 됨
로딩 화면 보여주기(#14)
- components에 MapLoading 컴포넌트 생성
- 외부 사진을 사용하여 로딩을 표시
- MapLoading을 적용하는 과정에서 Map의 좌표를 MainPage로 이동
- 좌표가 Map에 있을 때 컴포넌트가 한 번 버벅이는 현상이 있었는데, MainPage로 좌표를 이동시키고 props로 전달하니 해당 현상이 사라짐
- 좌표가 0일 경우 MapLoading을 보여주고, 좌표가 들어오면 Map을 보여줌
- 좌표 정보가 허용되지 않았을 경우 예외 처리 리팩토링이 필요함
- 지금 코드에서 서울 사용자의 경우 서울 중심지 화면을 잠깐 보여주고 본인 위치로 이동하는 문제가 발생함
- 이렇게 코드를 짠 이유는 사용자가 위치 허용을 거부했을 때를 구분할 수 없기 때문임
- MainPage.jsx 33 ~ 56
🩺 의사결정
지도 반경 제한하기(#13)
- 주요 지역 50곳 중 서울대공원 1곳은 지역이 서울이 아닌 과천임
- 지도 반경 제한 범위를 서울보다 살짝 넓게 설정함
🚧 Trouble Shooting
사용자 위치에 따른 지도 초기 화면 설정(#11)
- 문제 1 : client에서 BE에 네이버 지도 사용자 위치 API 요청 시 CORS 오류 발생
-
원인 : 어떤 쪽에서 CORS 방지를 위한 코드를 넣지 않음
-
해결 : 서버 응답 헤더에 ‘Access-Control-Allow-origin’을 설정하고, app.ts 파일에 cors 라이브러리를 설치하고 클라이언트 주소를 허용함
// server/src/apis/controllers/naver.controller.ts // 클라이언트의 URL을 넣어줘야 함 getGeoCodingFromCoords: async (req: Request, res: Response) => { const { lat, lng } = req.query; const url = `https://naveropenapi.apigw.ntruss.com/map-reversegeocode/v2/gc?coords=${lng},${lat}&sourcecrs=epsg:4326&orders=legalcode&output=json`; try { const data = await getAxiosFromNaverApi(url); if (process.env.CLIENT_URL) { res.setHeader('Access-Control-Allow-origin', process.env.CLIENT_URL); } res.status(200).send(data); } catch (error) { console.log(error); res.status(500).send({ ok: false, message: '좌표값을 기반으로 주소를 가져오지 못했습니다! :(' }); } } // server/app.ts 11 // 클라이언트의 URL을 넣어줘야 함 app.use(cors({ origin: process.env.CLIENT_URL, credentials: true })); -
기타 : Client의 요청 헤더에 ‘Access-Control-Allow-origin’ 설정하는 방법도 있는데 우리 코드에서는 효과가 없었음
-
- 문제2 : 위도/경도를 기반으로 주소를 찾지 못하는 ‘undefined’ 오류
- 원인 : 네이버 지도 API 요청 URL의 쿼리 문제였음
- 해결법 : URL의 orders 쿼리를 roadaddr에서 legalcode로 변경하였는데, 전자는 도로명 주소로 받아오는 건데 서울 이외 지역에서는 안먹히고, 후자는 그냥 주소인데 전국에서 사용이 가능했음
- 기타 : 네이버 지도 API 사용 시 공식 사용법 가이드를 꼼꼼하게 읽어볼 필요가 있음
로딩 화면 보여주기(#14)
- 문제1 : 좌표 로직을 Map.tsx에서 MainPage.tsx로 옮긴 후 API를 무한 요청하는 문제
- 원인 : MainPage의 useEffect에서 dependency 설정을 안함
- 해결법 : useEffect의 dependency에서 geolocation을 추가
🎸 기타
- 사용자 위치 정보 허용을 거부 했을 때 예외 처리를 더 정확하게 할 필요가 있음