Today Mini Learned :

기록하는 습관 들이기

PROJECT

[Issue - 모두모두 Webapp 개발] React에서 카카오맵 API를 이용해 현재 위치 받아오는 기능 구현 오류 해결

얌챠 2021. 9. 16. 16:27

💥 에러 발생 상황

모두모두 웹 페이지를 구현할 때, 자신의 출발 위치를 선택하기 위해 카카오맵 API를 사용해서 지도에 마커를 띄우는 기능이 있었다.

다음과 같이 지도 위에 특정 장소를 가리키는 마커를 띄운 상태

처음 위치는 카카오 본사로 되어 있었는데, 아무래도 사용자가 출발할 위치이기 때문에 현재 사용자의 위치를 초기 위치로 잡아주고 마커를 올리면 좋을 것 같다는 생각이 들었다. 그래서 gps를 사용하여 현재 위치를 읽어오는 기능을 구현했다.

문제는... 현재 위치를 가져오는 기능 자체는 문제가 없었는데 gps에서 현재 위치를 받아오는 것보다 Latitude와 Longtitude를 통해 맵을 구성하는 기능이 이 더 먼저 수행이 되어서 현재 위치가 아닌 기본값 위치로 맵에 마커가 생겼다.

빨간색 표시가 현재 위치를 가져오는 부분

curLatitude와 curLongtitude에는 기본값으로 정해둔 위치가 들어가 있었고, 현재 위치를 가져오면서 이 변수에 현재 위치 값을 저장하기도 전에 빨간 부분 바로 아랫줄이 먼저 작업을 완료해 버려서 문제가 생겼다.

 

❓ 에러가 발생한 이유

console.log로 각 작업 수행 시마다 로그를 찍어 봤더니 다음과 같이 나왔다

예상했던 것처럼 현재 위치를 받아오는 것이 더 느렸다. (그래서 현재 위치를 위도/경도 변수에 저장하기도 전에 맵을 구성해버려서 현재 위치가 중심이 되지 않았음) 아마도 위치를 받아오는 작업이 상대적으로 느리고, 위치를 받아오는 부분이 비동기적으로 수행되면서 이 작업이 끝나기 전에 아랫줄이 실행되는 것으로 보인다...!!

 

✔ 해결 방법

해당 동작이 비동기적으로 일어난다면 (현재 위치로 위도/경도를 설정하기도 전에 다음 작업을 실행한다면, 동기적으로 처리해주면 되지 않을까 해서 state로 저장되어 있는 위도/경도 값을 변경할 때 callback 함수를 통해 뭔가 작업을 해 주면 되지 않을까 했다.

근데... setState의 callback 함수 사용법을 찾아보면서 예시들을 보니 this.setState와 같이 작성하고, 클래스형 컴포넌트를 사용하고 있었다. 뭔가 이상해서 찾아보니 React Hook을 사용했던 나는 함수형 컴포넌트를 작성했기 때문에 다음 방법을 사용할 수 없었다.

 

대신, React Hook에서는 useEffect를 통해 해당 작업을 대신할 수 있다는 것에서 해결 방법을 생각해냈다. 

즉, 이 문제를 해결하기 위해 useEffect()에서 그냥 한번에 위치 파악하고 지도 그리는 게 아니라
1. getMyGps()라는 함수에 gps로 현 위치를 받아와 state에 위도/경도 값을 저장하는 기능을 넣음
2. mapDrawer()에는 state에 저장된 위도/경도로 지도를 그리는 기능만을 넣어둠
3. 페이지 렌더링이 끝나고 한 번 실행하는 useEffect에서 getMyGps() 수행 (위도/경도 받아오기!)
4. 어떤 창을 열지 지도가 있는 페이지가 열릴 때마다 실행되는 useEffect에서는 mapDrawer() 수행 (받아온 위도/경도로 지도 그리기!)
로 바꿔서 작성해봤다!

(useEffect는 여러 개 사용할 수 있다고 한다. 따라서 컴포넌트가 로딩되었을 때 한번 작업할 것들과, 특정 state가 바뀔 때마다 작업해 줄 것들을 분리해서 사용해 보기로 했다)

 

다음과 같이 처음 로딩 시에는 gps에서 현재 위치를 받아와서 위도/경도 state에 저장하고,

지도가 있는 창이 열릴 때에는 저장된 위도/경도 값을 이용해 지도를 그려 주었다.

 

다음과 같이 바꾸니 정상적으로 위치를 불러올 수 있었다!

 

+ 이번 기회에 비동기/동기 처리를 다뤄보고 싶었는데 다른 방법으로 해결이 되어서 아쉬웠다. 개인적으로 조금 더 공부해볼까 싶다.