221031 리액트 카카오맵 마커 클릭 이벤트(장소정보 띄우기)

샨티(shanti)·2022년 10월 31일
1
post-thumbnail

하루를 마무리 하기 전, 오늘 있었던 일들을 잔잔히 되짚어봅니다.
성공과 실패의 모든 요소에서 '배울 점'을 찾아내어 기록하고,
더 성장하는 내일의 나를 위해 'action plan'을 세웁니다.

결과물

빠르게 결과물 부터 공유한다.
지금은 화면을 캡쳐하는 방식으로 TIL에 첨부하고 있는데, 담번엔 움직이는 이미지로 첨부하는 방법을 공부해서 추가해보려 한다. 매일 매일 새로운 것을 배워나가는 중 하하하.

  1. 임의로 입력한 5개의 장소에 대한 복수 마커 띄우기

  2. 특정 마커 위에 마우스 오버 시 인포 윈도우 띄우기

  3. 특정 마커 클릭 시 장소 요약정보를 담은 팝업 띄우기(사진 제공해준 봄이 고마워~ ㅎㅎㅎㅎㅎ)


오버레이가 아닌 팝업 형태를 구현하기 위하여...

어제 TIL에도 작성했던 사항이지만 우선 구조를 꽤 많이 바꿨던지라 기능이 돌아가지 않는 상태였다. 오늘(월요일)이 스프린트 회의였기 때문에 어떻게든 기능을 구현해야 했는데 설상가상 아이까지 아픔...ㅋ 뀨..

기능 구현이 제대로 안되면 이전 커밋으로 돌려서 되는 사항이라도 시연해야겠다는 생각으로 오늘 아침 일찍 도장에 도착해서 천천히 코드를 뜯어보았다.

한-참을 씨름했는데 어처구니 없이 useRef를 활용했던 코드 하나에 빠진 내용이 있어서 지도가 계속 뜨지 않던 상황이었다...
힘이 쭉 빠졌지만 그래도 계속 에러 화면만 보다가 지도가 하얗게 딱!! 나오니 좀 시원했다.

이제 난관은 마커 클릭 이벤트.

마커를 뿌려주는 것까지는 다시 되살려놨는데 마커를 열나게 클릭해도 뜨질 않는 것이었다.
정말 useEffect 뿐만 아니라 각 컴포넌트, store, apiService까지. 파일마다 한 줄 한 줄 console.log를 넣어놓고 계속 돌려보는데 이상하게 팝업 컴포넌트만 불려지지 않고 있었다.

정말 너-무 답답했다.
점점 스프린트 회의 시간은 다가오고... 왜 이렇게 안되는건가...

커밋을 되돌리는 방법만 남은건가? 하고 절망했을 때 갑자기 읭.. 스러운게 있었다.

분명 나는 팝업 컴포넌트가 들어있는 Map.jsx 파일을 임포트하여 MapPage.jsx에서 보여주고 있었는데 Map이 뭔가 이상했다.

// 문제의 코드 전체

import { useEffect, useRef, useState } from 'react';

import styled from 'styled-components';

import useMapStore from '../hooks/useMapStore';

import { loadKakaoMap } from '../utils/KakaoMap';

const Map = styled.div`
  display: relative;
  max-width: 700px;
  min-width: 500px;
  max-height: 700px;
  min-height: 500px;
  width: 50%;
  height: 50vw;
`;

export default function MapPage() {
  const [state, setState] = useState(false);

  const mapStore = useMapStore();

  const kakaoMap = useRef(null);

  const makeClickListener = (placeId) => {
    mapStore.fetchSelectedPlaceInformation(placeId);
    setState(true);
  };

  useEffect(() => {
    mapStore.fetchAllPositions();
    const { positions } = mapStore;
    loadKakaoMap(kakaoMap.current, positions, makeClickListener);
  }, []);

  const { selectedPlace } = mapStore;

  const handleCloseClick = () => {
    setState(false);
  };

  return (
    <div>
      <h1>Map Page</h1>
      <p>지도</p>
    
    // 문제의 그 영역....
      <Map ref={kakaoMap} />
    </div>
  );
}

return에 있는 저 <Map>은 컴포넌트의 Map이 아니다.............. 아.........
컴포넌트가 아니라 상단에 있는 styled-components로 잡아줬던 div였는데...
저걸 Map 컴포넌트를 임포트 했다고 착각하는 바람에...
정말 오전 시간 몽땅과 오후시간 몽땅을 날려먹었다.

너무 허무하고 어처구니가 없었다.
하지만 한편으론 크게 배웠다고 생각했다.

애초에 중복 사항이 생긴 것을 인지하고 제대로 된 네이밍을 했더라면 이런 식으로 시간을 쏟아붓진 않았을텐데. 적어도 생산적인 일을 하며 시간을 보냈을텐데 코다 한줄 한줄 console.log를 찍는 것도 모자라 import도 하지 않아놓고 왜 팝업이 안뜨냐며... 난리난리를... ㅎ ㅏ ㅎ ㅏ.

어쨌든 3기 동료분의 CSS 도움까지 받아서 오버레이가 아닌 컴포넌트를 띄워주는 방식으로 팝업을 구현할 수 있었다.

// MapPage.jsx 1차 구현

import { useEffect, useRef, useState } from 'react';

import styled from 'styled-components';

import useMapStore from '../hooks/useMapStore';

import { loadKakaoMap } from '../utils/KakaoMap';

import PlaceInformationPopup from '../components/PlaceInformationPopup';

const MapArea = styled.div`
  display: relative;
  max-width: 700px;
  min-width: 500px;
  max-height: 700px;
  min-height: 500px;
  width: 50%;
  height: 50vw;
`;

export default function MapPage() {
  const [state, setState] = useState(false);

  const mapStore = useMapStore();

  const kakaoMap = useRef(null);

  const makeClickListener = (placeId) => {
    mapStore.fetchSelectedPlaceInformation(placeId);
    setState(true);

    // TODO. 클릭 시 마커 이미지 바꿔보기
    // marker.setImage(selectedMarkerImage);
  };

  useEffect(() => {
    mapStore.fetchAllPositions();

    const { positions } = mapStore;

    loadKakaoMap(kakaoMap.current, positions, makeClickListener);
  }, []);

  const { selectedPlace } = mapStore;

  const handleCloseClick = () => {
    setState(false);
  };

  return (
    <div>
      <h1>
        Map Page
      </h1>
      <p>지도</p>
      <MapArea ref={kakaoMap}>
        {state && (
          <PlaceInformationPopup
            selectedPlace={selectedPlace}
            handleCloseClick={handleCloseClick}
          />
        )}
      </MapArea>
    </div>
  );
}

어쨌든 돌아가는 상태로 스프린트 회의를 마친 후에 이번주 태스크를 잡았는데 스토리 포인트가 100이 넘어간다 (ㅋㅋㅋㅋㅋ)
말이 되는 상황인지 모르겠지만 남은 시간을 생각하면 그래도 스퍼트를 내야..

이번주는 CSS를 좀 약하게 하더라도 지도와 관련된 사항을 프론트-백 연동 시켜서 모두 구현해야 한다.
정말로.. 생각했던 것보다는 지도가 꽤 어렵고 난관도 많지만 오늘 했던 것 처럼 실수를 발견하고 수정해나가고, 그 실수를 반복하지 않는 방향으로! 지도 기능을 만들어보겠다.

profile
가벼운 사진, 그렇지 못한 글

0개의 댓글