카카오 맵을 통해 스코프를 깨우치다

박재성·2022년 9월 22일
0

sw 헤커톤에서 개발했던 픽깅이를 다시 만들기 위해 코드를 지우고 다시 짜고 있다. 리펙터링을 하기에는 코드 자체가 너무 지저분했고 잔버그가 너무 많았기 때문에 지도 관련 부분을 전부 지우고 다시 개발하고 있다.

기존 네이버 맵에서 카카오맵으로 변경해서 개발했고, 맵 사용이 처음이어서 문서를 열심히 보면서 하나하나 만들어 가고 있었다.

그동안 이런 개발을 할 일이 없었나 떠올리면 지금같은 상황이 벌어지지 않았다.

문제 상황

일단 지도에 마커를 띄우고 마커에 이벤트를 걸어서 커스텀 오버레이를 띄우면 된다. 카카오에서 제공하는 문서를 보면서, 착한 사람이 리액트에서 편하게 쓰라고 만들어준 라이브러리를 이용하면 아주 쉽게 오버레이를 띄울 수 있다.

하지만 마커를 많이 띄우고 각각에 이벤트를 걸어줘야 한다.

일단 평소 하던데로 map을 이용해서 마커와 커스텀 오버레이를 화면이 나오게 했다.

isShowing 상태를 만들어서 이벤트가 발생하면 상태값을 바꿔서 오버레이가 보이게 하는 로직을 짰다.

코드로 보면 이렇다.

{curSpots?.map((spot) => (
          <MapMarker
            key={spot.id}
			onClick={onClick}
            position={{
              lat: spot.coordinate[1],
              lng: spot.coordinate[0],
            }}
            content={spot.name}
          />
        ))}

매우 잘 나왔다. 하지만 문제가 있다. onClick을 사용하면 내가 생성한 모든 마커에 커스텀 오버레이가 나오게 된다. 해당 타겟의 오버레이가 아니라 전부 나오는 버그가 발생했다.

왜 발생했을까

문제가 발생해서 오히려 좋았다. 이유에 대해서 고민해보고 찾아볼 기회를 가졌으니까!

하나씩 짚어보자.

클릭 이벤트가 발생하면 해당 컴포넌트에서 선언한 state가 변화해서 렌더링이 일어날 것이다. 그럼 map 함수가 다시 실행이 되는데 이 때 해당 state 값에 따라 모든 데이터가 visible이 되는 상황을 맞이했다고 볼 수 있다.

그럼 어떻게

여기서 문제는 state가 모든 마커를 담당하고 있는 것이다. 하나의 마커가 하나의 상태를 가질 수 있도록 범위를 정해주면 다른 값에 의해 영향을 받지 않기 때문에 원하는 기능을 제대로 구현할 수 있을 것이라고 생각했다.

이때 스코프에 대해 확실하게 알 수 있었다. 딥다이브에서 읽었던 스코프, 클로저 등 어렵다고 느꼈던 개념들이 떠올랐다.

가장 중요한 것은 해당 state가 다른 값에 영향을 주지 않게 짜야 한다는 것.

따라서 마커를 만드는데 새로운 컴포넌트를 하나 더 생성해야 한다. 새로 만든 컴포넌트에는 커스텀 오버레이를 보이게 하는 로직이 들어간다.

const EventMarkerContainer = ({ position, content }: Props) => {
    const [isVisible, setIsVisible] = useState(false);
    const handleVisible = () => {
      setIsVisible((cur) => !cur);
    };
    return (
      <>
        <MapMarker
          onClick={handleVisible}
          position={position}
          image={{
            src: Spot,
            size: {
              width: 34,
              height: 34,
            },
          }}
        />
        
      </>
    );
  };

마커를 생성하는 컴포넌트를 따로 분리하면 isVisible을 독립적으로 사용할 수 있기 때문에 위 문제를 해결할 수 있다. 전체 구조를 다시 보면!


function Pickging() {
  {...}
  const EventMarkerContainer = () => {
     const [isVisible, setIsVisible] = useState(false);
     const handleVisible = () => {
      setIsVisible((cur) => !cur);
    };
  	return (
    	<MapMarker .../>
    )
  }
  return (
  	{curSpots?.map((spot) => (
          <EventMarkerContainer
            key={spot.id}
            position={{
              lat: spot.coordinate[1],
              lng: spot.coordinate[0],
            }}
            content={spot.name}
          />
        ))}
  )
}

고로 스코프를 잘 정해서 코딩하는 습관을 들이자고!

결과

받아오는 데이터가 이름밖에 없어서 띄어줄 정보가 없지만 타입에 따라 다른 이미지를 띄어주고, 해당 스팟에 가까이 갔을 떄 자동으로 오버레이를 띄어주게 구현하면 어떨까 생각이든다!

profile
개발, 정복

0개의 댓글