커넥트립

카카오맵으로 동행 유저 위치 한눈에 — setBounds 분투기

채팅방에서 "내 위치 추적" 토글을 켜면 동행 유저들의 마지막 위치가 한 화면에 들어와야 했다. 문서대로면 setBounds 한 줄이면 끝나는데, 그 한 줄이 토글 시점에는 먹히지 않았다.

원하는 것

채팅방 햄버거 바에서 위치 추적 토글을 켜는 즉시, 동행 유저들의 마지막 위치가 한눈에 들어오도록 지도를 렌더하고 싶었다.

위치 추적 토글 화면
위치 추적 토글 — 켜면 동행들의 위치를 보여주려 했다.

문제: 토글 시 setBounds가 안 먹는다

토글을 켜면 처음 설정한 center에 지도가 멈춰 있고 setBounds가 적용되지 않았다. 공식 문서는 기본 지도가 이미 떠 있는 상태에서 setBounds하는 코드였는데, 나는 기본 지도 없이 숨겨두다가 토글한 순간에만 지도를 띄우고 bounds를 맞춰야 했다. 그래서 공식 코드를 변형해야 했다.

해결: isShow + bounds 재설정 컴포넌트

isShow 상태로 토글 시에만 지도를 출력하고, 별도의 bounds 재설정 컴포넌트에서 LatLngBounds로 모든 마커를 감싸 setBounds했다. 렌더 시점과 bounds 적용 시점을 분리한 게 핵심이다.

function SetBounds() {
  const [isShow, setIsShow] = useState(false);
  const [points] = useState([
    { lat: 33.452278, lng: 126.567803 },
    { lat: 33.452671, lng: 126.574792 },
    { lat: 33.451744, lng: 126.572441 },
  ]);
 
  return (
    <>
      {isShow && (
        <Map center={{ lat: 33.450701, lng: 126.570667 }} level={3} style={{ width: "100%", height: 350 }}>
          {points.map((p) => (
            <MapMarker key={`${p.lat}-${p.lng}`} position={p} />
          ))}
          <ReSettingMapBounds points={points} />
        </Map>
      )}
      <button onClick={() => setIsShow(true)}>위치 보기</button>
    </>
  );
}
 
const ReSettingMapBounds = ({ points }) => {
  const map = useMap();
  const bounds = useMemo(() => {
    const b = new kakao.maps.LatLngBounds();
    points.forEach((p) => b.extend(new kakao.maps.LatLng(p.lat, p.lng)));
    return b;
  }, [points]);
 
  useEffect(() => {
    map.setBounds(bounds);
  }, [map, bounds]);
 
  return null;
};
setBounds로 동행 위치 표시
토글 시 setBounds로 동행 유저 마커를 한눈에.

배운 점

공식 예제는 "이미 떠 있는 지도"를 전제한다. 내 요구(토글 시에만 띄우고 즉시 bounds 맞추기)에 맞춰 렌더 시점과 bounds 적용 시점을 분리하니 풀렸다.

참고