본문 바로가기
Web Development/API

[ 카카오맵 API ] 반응형으로 지도 구현하기 ( 지도가 다른 위치를 표시하는 오류 해결)

by Krystal K 2023. 7. 26.

반응형으로 지도 구현하기 (with Kakao Map)

 

이 글은

브라우저창의 크기가 변할 때 카카오맵 지도가 정확한 위치를 벗어나 다른 위치를 보여주는 문제를

해결하는 과정을 담고 있습니다.


[ 최종적으로 구현한 모습 ]

[ 구현해야 할 필수 기능 ]

1. 페이지에 지도 표시

2. 지도 중앙에 마커 표시

3. 지도 반응형으로 구현하기

 

 카카오맵  & 네이버맵 API 비교 및 카카오맵으로 지도 기능 구현하기

위의 글에서

Naver maps API와 Kakao maps API 비교 및

kakao maps API를 이용해 지도를 구현하는 과정을 다루었습니다.

 

[ 마주한 문제점 ]

프로젝트를 진행하는 과정에서 커스텀한 마커까지 완벽하게 구현했지만 새로운 문제점을 발견하게 되었습니다.

반응형을 확인해보니 지도의 마커 표시가 사라지거나,

지도가 지정된 위치가 아닌 엉뚱한 곳을 표시하는 문제가 지속적으로 발생했습니다. 

 

 

문제점 분석

이러한 문제가 발생한 원인을 찾아보았습니다.

카카오맵 API에서 지도를 불러오는 과정을 이해하면 쉽게 해결되는 문제였습니다.

 

 카카오맵 API 공식문서에 해당 내용을 검색해보았습니다.

지도 영역 크기 동적 변경하기

위의 페이지에서 해당 문제에 대한 정보를 얻을 수 있었습니다.

 

아래의 이미지는 카카오맵 API 공식 문서의 예시를 캡쳐한것으로

브라우저 창의 크기가 줄어들면 지도의 크기도 줄어드는 것이 보입니다.

하지만 카카오 스페이스 닷원이라는 위치가 중앙에 오지 않고 사라져 버립니다.

이러한 문제에 대해 카카오맵에서는 이렇게 안내하고 있습니다.

 

여기서 눈여겨 봐야할 부분은

"크기를 변경한 이후에는 반드시 map.relayout 함수를 호출해야 합니다."

이 부분입니다.

 

카카오맵은 좌표와 지도의 레벨을 바탕으로 초기에 지정해준 지도 사이즈와 계산해서 지도를 불러옵니다.

화면에 표시되는 지도의 크기와 지도의 레벨을 기준으로 정확한 위치를 계산해서 보여주는 방식입니다. 

 

반응형의 경우, 화면의 크기에 따라 지도의 크기가 변하게 됩니다.

따라서, 브라우저 창의 크기가 축소되면 지도의 크기도 줄어들게 됩니다.

그러나 현재 지도는 여전히 초기에 설정한 크기를 기준으로 계산되어

화면의 크기를 줄이면 마커가 보이지 않는 영역으로 이동하는 문제가 있습니다.

이에 따라 카카오맵 API는 변경된 맵의 크기에 따라 위치를 계산하여 보여주어야 합니다.

이렇게 하면 반응형 디자인에 따라 화면 크기가 조절되어도 지도가 항상 정확한 위치를 중앙에 표시할 수 있습니다.

 

 

해결 방안

위의 문제를 해결하기 위해  카카오맵을 변하는 지도의 크기를 가지고 계산하도록 하는 과정이 필요했습니다.

그리고 카카오맵 API 공식문서에서 제공하는 코드와 다른 방식으로 코드를 작성한 부분들이 있어

카카오맵에서 제시한 방법과 조금 다르게 해결했습니다.

 

우선 반응형으로 페이지를 작업하면서 지도에 이렇게 스타일을 주었습니다.

화면의 크기에 따라 지도 크기가 조절 되도록하고 페이지에서 flex로 정렬하여 여백이 자동으로 조절되도록 했습니다. 

 

따라서 지도의 크기는 브라우저창의 크기에 영향을 받는 상태입니다.

임의로 지도의 값을 변경할 필요가 없습니다.

 

이제 브라우저창의 크기에 따라 변경되는 지도의 크기를 다시 계산해서 지도가 표시되도록 해야합니다.

 

우선 브라우저창의 크기가 변하는 것을 체크하기 위해     

window.addEventListener("resize", handleWindowResize)를 사용했습니다.

그리고 이벤트(사이즈가 변하는)가 발생할 때마다 지도를 재호출하기 위해

handleWindowResize 함수를 실행하도록 하고 그 함수는 windowSize라는 state 값을 변경 시키도록 했습니다.

 

  const [windowSize, setWindowSize] = useState(window.innerWidth);

  useEffect(() => {
    const handleWindowResize = () => {
      setWindowSize(window.innerWidth);
    };

    window.addEventListener("resize", handleWindowResize);

    return () => {
      window.removeEventListener("resize", handleWindowResize);
    };
  }, []);

 

 

그리고 windowSize가 변경될 때마다 지도가 재호출 되도록

지도를 그리는 함수들을 useEffect로 묶고 의존성 배열에  windowSize를 넣었습니다.

 

    map.setCenter(coords);
  }, [windowSize]);

 

 결과

브라우저창 크기가 변경 될 때 마다 지도가 재호출되어 올바른 위치를 표시했습니다.

수정된 코드

const KakaoMap = () => {
  const [windowSize, setWindowSize] = useState(window.innerWidth);

  useEffect(() => {
    const handleWindowResize = () => {
      setWindowSize(window.innerWidth);
    };

    window.addEventListener("resize", handleWindowResize);

    return () => {
      window.removeEventListener("resize", handleWindowResize);
    };
  }, []);

  useEffect(() => {
    const container = document.getElementById("map");
    const options = {
      center: new kakao.maps.LatLng(latitude, longitude),
      level: 3,
    };

    const map = new kakao.maps.Map(container, options);

    let coords = new kakao.maps.LatLng(latitude, longitude);

    const imageSrc = "/images/map/makerImage.png",
      imageSize = new kakao.maps.Size(64, 69),
      imageOption = { offset: new kakao.maps.Point(27, 69) };

    const markerImage = new kakao.maps.MarkerImage(
      imageSrc,
      imageSize,
      imageOption
    );

    let marker = new kakao.maps.Marker({
      map: map,
      position: coords,
      image: markerImage,
    });

    let content = `<div style=" padding: 10px; width:auto; color:white; background:#89B922; border-radius:5px; border:1px solid white; box-shadow: 0 0 11px rgba(33, 33, 33, 0.2);">${courtName}</div>`

    let customOverlay = new kakao.maps.CustomOverlay({
      map: map,
      content: content,
      position: coords,
			xAnchor: 0.5, 
			yAnchor: 2.9 
    });

    map.setCenter(coords);
  }, [windowSize]);

  return <Location id="map" />;
};

export default KakaoMap;

const Location = styled.div`
  width: 100%;
  height: 40vw;
  border: 1px solid black;
`;
 

배운점

 

지도를 그리는 것에만 초첨을 맞춰서 마커를 표시하고, 반응형으로 크기를 조절하는 부분만 고려했습니다.

결국 지도의 중요한 역할은 정확한 위치를 표시해주는 것인데

그러기위해서 필요한 과정을 이해하고 API를 사용했다면 하지 않았을 실수라는 생각이 들었습니다.

 

이번에 겪은 문제도 어떤 원리인지 파악하고 나니 해답이 바로 보였습니다.

어떤 기능을 가져와서 구현할 때, 그 기능이 돌아가는 구체적인 과정을 먼저 파악하는 것이 중요하다는 것을 배웠습니다.

어떤 매커니즘인지 파악하면 사전에 발생할 수 있는 문제점들을 예측하고 예방할 수 있기 때문입다.

 

 

728x90