growing-devs / easy-to-real-estate-frontend

몰리턴 웹 서비스 고도화 프로젝트의 프론트엔드 repository
MIT License
0 stars 3 forks source link

지도 컴포넌트 구현 #15

Closed 05Castle closed 1 year ago

05Castle commented 1 year ago

Description

상호작용 가능한 지도 컴포넌트 만들기

Todo List

변경 및 추가사항

panoID를 받아오지 못하는 위치가 있는 이슈(하단 코멘트 참고)에 대해서 로드뷰 방식을 동동이 사용방식으로 바꾸기로 함. https://apis.map.kakao.com/web/sample/roadviewWithMapButton/

해결해야 하는 사항

지도를 토글하거나 주소가 바뀐 후, 지도를 zoom out 하면 이전의 지도가 겹쳐 보이는 문제 확인. 지도를 생성하는 함수가 useEffect 안에 있는 상태에서, dependency 에 따라 재실행하면서 발생하는 것으로 보인다.

useEffect를 사용하지 않기 위한 방법을 찾아보려고 했는데, kakao객체 자체가 window 전역 객체 안에 있어서 화면이 렌더링 이후에 접근이 가능하다고 한다. 즉, 렌더링 이후에 값에 따라 재 렌더링 되기 위해 useEffect를 사용하는 것이 강제되는 것 같다.

api script에 autoload=false로 설정해서 스크립트가 동적으로 로드하는 것을 막고, 비동기적으로 지도 객체에 접속할 수 있도록 .load 메서드를 사용하는 방법으로 useEffect 없이 지도를 만드는 것에 성공했다. 하지만, 여전히 같은 오류가 발견되었다.

react-kakao-maps-sdk 라이브러리를 사용한 지도에서는 이러한 문제가 발생하지 않는 것으로 보아 분명 해결 방법이 있을 것 같다. https://react-kakao-maps-sdk.jaeseokim.dev/

05Castle commented 1 year ago

panoID가 없어서 로드뷰를 표시하지 못하는 문제 발견. 아파트 단지의 보안 정책에 따라 단지 내 로드뷰 촬영을 하지 못해서 발생한 문제 같다. 당장 떠오르는 대책은 3개.

  1. panoID를 받아오는 거리를 늘린다(현재 50m).
  2. panoID가 없으면 로드뷰 토글을 비활성화 한다.
  3. panoID가 없으면 로드뷰 전환했을 때, <50m이내 로드뷰 이미지가 없습니다>라고 표시한다.
05Castle commented 1 year ago

중복 렌더링 해결한 방법

// lat는 위도, lng 는 경도

const Map = ({ lat, lng }) => {

  useEffect(() => {
    const mapContainer = document.getElementById('map'); // 지도를 표시할 div
    const mapOption = {
      center: new window.kakao.maps.LatLng(lat, lng), // 지도의 중심좌표
      level: 3, // 지도의 확대 레벨
    };
    const mapComp = new window.kakao.maps.Map(mapContainer, mapOption); // 지도를 생성
  }, [lat]);

  return (
    <MapWrapper>
      <div id="map" />;
    </MapWrapper>
  );
};

위의 코드는 좌표가 바뀔때마다 map 객체가 계속 렌더링되면서 문제가 발생했음. 그래서 아래와 같이 코드를 수정.

const Map = ({ lat, lng }: positionProps) => {

  const mapContainerRef = useRef<HTMLDivElement>(null);
  const [kakaoMap, setKakaoMap] = useState<any>(null);

    // 의존성 빈 배열로 지도는 최초 한번만 생성
  useEffect(() => {
    const mapContainer = mapContainerRef.current;
    const mapOption = {
      center: new window.kakao.maps.LatLng(lat, lng), // 지도의 중심좌표
      level: 3, // 지도의 확대 레벨
    };
    const map = new window.kakao.maps.Map(mapContainer, mapOption); // 지도를 생성
    setKakaoMap(map); // 지도 객체를 state로 저장
  }, []);

    // 아래와 같이 useEffect 추가하여, 좌표가 변하면 중앙을 다시 세팅
  useEffect(() => {
    if (kakaoMap !== null) {
      const center = new window.kakao.maps.LatLng(lat, lng); // 새로운 지도의 중심좌표
      kakaoMap.setCenter(center);  // 지도의 중심 변경
      kakaoMap.setLevel(3) // 지도 확대 레벨 다시 3으로 조정
    }
  }, [lat]);

  return (
    <MapWrapper>
      <div id="map" ref={mapContainerRef} />;
    </MapWrapper>
  );
};

빈 배열의 useEffect로 map 객체를 한번만 생성하고, map 객체를 state로 저장.

좌표값을 의존성 배열로 하는 useEffect로 지도 중심과 레벨을 유동적으로 변하도록 함.