๐Ÿ“์ถ”๊ฐ€๊ตฌํ˜„: ํด๋Ÿฌ์Šคํ„ฐ๋Ÿฌ๋กœ ๋ Œ๋”๋ง ์ตœ์ ํ™”ํ•˜๊ธฐ

Yeonnยท2025๋…„ 3์›” 8์ผ
0

๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

๋ชฉ๋ก ๋ณด๊ธฐ
4/10
post-thumbnail

์บ ํ•‘ํ•‘ ํ”„๋กœ์ ํŠธ์—์„œ ์นด์นด์˜ค API๋กœ ์ง€๋„ ๊ตฌํ˜„์„ ํ–ˆ๋‹ค !

์ง€๋„ ํŽ˜์ด์ง€์—์„œ๋Š” ๋‘ ๊ฐ€์ง€ ๊ฒ€์ƒ‰์ด ๊ฐ€๋Šฅํ•œ ๋ฐ,
Nav ๋ฐ”๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•˜๋ฉด ๋จผ์ € ์œ ์ €์˜ ์œ„์น˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์บ ํ•‘์žฅ์ด ๊ฒ€์ƒ‰๋œ๋‹ค.
๋‘ ๋ฒˆ์งธ๋กœ ๊ฒ€์ƒ‰๋ฐ”๋ฅผ ํ†ตํ•ด ์ง€์—ญ์„ ๊ฒ€์ƒ‰ํ•˜๋ฉด ํ•ด๋‹น ์ง€์—ญ์— ์œ„์น˜ํ•œ ์บ ํ•‘์žฅ์ด ๊ฒ€์ƒ‰๋œ๋‹ค.

๋จผ์ € ๋งˆ์ปค๋กœ ์ง€๋„์— ์บ ํ•‘์žฅ๋“ค์„ ์ฐ์–ด์ฃผ๋Š” ๊ตฌํ˜„๋งŒ ํ–ˆ๋‹ค.

๐Ÿ—บ๏ธ ์ง€๋„ ์ƒ์„ฑํ•˜๊ธฐ

next.js์˜ Script ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํฌํ•จ์‹œ์ผœ์ฃผ๊ณ ,
beforeInteractive๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŽ˜์ด์ง€ ๋ Œ๋”๋ง ์ „์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋กœ๋“œํ•˜๋„๋ก ํ•˜์—ฌ ๋กœ๋”ฉ ์†๋„๋ฅผ ํ–ฅ์ƒ์‹œ์ผฐ๋‹ค.
autoload=false๋ฅผ ํ†ตํ•ด ์นด์นด์˜ค ๋งต SDK๊ฐ€ ์ž๋™์œผ๋กœ ๋กœ๋“œ๋˜์ง€ ์•Š๋„๋ก ํ•ด์„œ ์Šคํฌ๋ฆฝํŠธ ๋กœ๋“œ ํ›„ ํ•„์š” ์‹œ์ ์—
๋งต์„ ์ดˆ๊ธฐํ™” ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ์œผ๋กœ์จ ๋งต ๋กœ๋”ฉ์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค.
๋˜ libraries=clusterer๋ฅผ ํ†ตํ•ด ํด๋Ÿฌ์Šคํ„ฐ๋ง ๊ธฐ๋Šฅ์„ ํ•จ๊ป˜ ๋กœ๋“œํ•œ๋‹ค.

	 <Script
          strategy="beforeInteractive"
          src={`https://dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.NEXT_PUBLIC_KAKAO_MAP_KEY}&autoload=false&libraries=clusterer`}
        />

๐Ÿ’ก Kakao Map Script ์ตœ์ ํ™”

  • beforeInteractive
    : ํŽ˜์ด์ง€ ๋ Œ๋”๋ง ์ „์— ์Šคํฌ๋ฆฝํŠธ ๋กœ๋“œํ•˜์—ฌ ํŽ˜์ด์ง€ ๋ Œ๋”๋ง ์†๋„ ์ตœ์ ํ™”
  • autoload=false
    : ์นด์นด์˜ค ๋งต์ด ์ž๋™์œผ๋กœ ๋กœ๋“œ๋˜์ง€ ์•Š๋„๋ก ์„ค์ •ํ•˜์—ฌ ๋งต ๋กœ๋”ฉ ์ œ์–ด ๊ฐ€๋Šฅ

๐Ÿ“ ๋งˆ์ปค ์ƒ์„ฑํ•˜๊ธฐ

 useEffect(() => {
  if (!kakaoMap || campList?.length === 0) return;

  const positions = campList.map((camp) => ({
    id: camp.contentId,
    title: camp.facltNm,
    latlng: new window.kakao.maps.LatLng(
      camp.location.coordinates[1],
      camp.location.coordinates[0]
    ),
    address: camp.addr1,
    imgSrc: camp.firstImageUrl,
  }));

  positions.forEach((position) => {
    const marker = new window.kakao.maps.Marker({
      map: kakaoMap,
      position: position.latlng,
      title: position.title,
      address: position.address,
      contentId: position.id,
    });

    marker.setMap(kakaoMap);
  });
}, [campList, kakaoMap]);

์œ„์™€ ๊ฐ™์ด ๋ฐ์ดํ„ฐ์— ์žˆ๋Š” ์บ ํ•‘์žฅ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์ง€๋„์— ๋งˆ์ปค๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.

โ—๏ธ ๋ฌธ์ œ ๋ฐœ์ƒ

ํ•˜์ง€๋งŒ... ์ง€์—ญ ๊ฒ€์ƒ‰ ์‹œ '๊ฒฝ๊ธฐ๋„'์™€ ๊ฐ™์ด ๋งŽ์€ ์ˆ˜์˜ ์บ ํ•‘์žฅ์ด ์žˆ๋Š” ๊ณณ์˜ ๊ฒฝ์šฐ
์ง€๋„ ๋กœ๋”ฉ ๋ฐ ๋ Œ๋”๋ง ์†๋„์™€ ์ง€๋„๋ฅผ ํ™•๋Œ€/์ถ•์†Œํ•˜๊ฑฐ๋‚˜ ์ด๋™ํ•  ๋•Œ ๊ณผ๋„ํ•œ ์—ฐ์‚ฐ์œผ๋กœ ์ธํ•ด ํ™”๋ฉด์ด ๋ฉˆ์ถ”๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ–ˆ๋‹ค.

๐Ÿš€ ํด๋Ÿฌ์Šคํ„ฐ๋Ÿฌ ๋„์ž…ํ•˜๊ธฐ

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํ™”๋ฉด์— ๋งˆ์ปค๋ฅผ ์ค„์ด๊ณ  ๊ทธ๋ฃน์œผ๋กœ ๋ฌถ์–ด ์ฃผ๊ธฐ ์œ„ํ•ด
์นด์นด์˜ค ์ง€๋„์˜ ํด๋Ÿฌ์Šคํ„ฐ๋Ÿฌ( clusterer )๋ฅผ ์ ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

useEffect(() => {
  // ์ง€๋„ ๊ฐ์ฒด, ์บ ํ•‘์žฅ ๋ชฉ๋ก์ด ์—†์œผ๋ฉด ํ•จ์ˆ˜๋ฅผ ์ข…๋ฃŒํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ ๋ฐฉ์ง€
  if (!kakaoMap || campList?.length === 0) return;

  // ์บ ํ•‘์žฅ ์œ„์น˜ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ๋ฐ ์˜ค๋ฒ„๋ ˆ์ด ํ‘œ์‹œ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ์ €์žฅ
  const positions = campList?.map((camp) => ({
    id: camp.contentId,
    title: camp.facltNm,
    latlng: new window.kakao.maps.LatLng(
      camp.location.coordinates[1],
      camp.location.coordinates[0]
    ),
    address: camp.addr1,
    imgSrc: camp.firstImageUrl,
  }));

  // ๋งˆ์ปค ๊ฐ์ฒด ์ƒ์„ฑ: ์ง€๋„์— ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๊ณ  markders ๋ฐฐ์—ด์— ์ €์žฅ ! 
  // ํด๋Ÿฌ์Šคํ„ฐ๋ง์— ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ €์žฅํ•˜๋Š” ๊ฒƒ
  const markers = positions.map(function (position) {
      return new window.kakao.maps.Marker({
        position: position.latlng,
      });
    });

  // ๋งˆ์ปค ํด๋Ÿฌ์Šคํ„ฐ๋Ÿฌ ์ƒ์„ฑ
  const clusterer = new window.kakao.maps.MarkerClusterer({
    map: kakaoMap,
    averageCenter: true, // ํด๋Ÿฌ์Šคํ„ฐ์˜ ์ค‘์‹ฌ์ ์„ ๋งˆ์ปค ํ‰๊ท  ์œ„์น˜๋กœ ์ง€์ •
    minLevel: 9, // ์คŒ ๋ ˆ๋ฒจ์ด 9 ์ดํ•˜์ผ ๋•Œ ํด๋Ÿฌ์Šคํ„ฐ๋ง ์ ์šฉ
    markers: markers, // ์ƒ์„ฑํ•œ ๋งˆ์ปค ๋ฆฌ์ŠคํŠธ ์ถ”๊ฐ€
  });

  // ๊ธฐ์กด ๋งˆ์ปค ์ดˆ๊ธฐํ™”
  markers.forEach((marker) => marker.setMap(null));

  // ํด๋Ÿฌ์Šคํ„ฐ๋ง ์ •๋ณด ์ดˆ๊ธฐํ™”
  clusterer.clear();
  // ํด๋Ÿฌ์Šคํ„ฐ๋ง์ด ์ •์ƒ์ ์œผ๋กœ ๊ฐฑ์‹ ๋˜์ง€ ์•Š๋Š” ๋ฒ„๊ทธ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด 100ms ํ›„ ๊ฐ•์ œ ๊ฐฑ์‹ 
  setTimeout(() => clusterer.redraw(), 100);

  positions?.forEach((position) => {
    const marker = new window.kakao.maps.Marker({
      map: kakaoMap,
      position: position.latlng,
      title: position.title,
      address: position.address,
      contentId: position.id,
    });

    // ํด๋Ÿฌ์Šคํ„ฐ๋Ÿฌ์— ๋งˆ์ปค ์ถ”๊ฐ€
    clusterer.addMarker(marker);
    // ์ง€๋„์— ๋งˆ์ปค ์ถ”๊ฐ€
    marker.setMap(kakaoMap);

    setKakaoMarker(marker);
  });
}, [campList, kakaoMap]);

โœจ ํด๋Ÿฌ์Šคํ„ฐ๋Ÿฌ ๊ตฌํ˜„ ๊ฒฐ๊ณผ

์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋งˆ์ปค๊ฐ€ ๊ฐ€๊นŒ์ด ์žˆ์„ ๊ฒฝ์šฐ ํด๋Ÿฌ์Šคํ„ฐ๋ง ๋˜์–ด ๋งˆ์ปค๋“ค์ด ๊ทธ๋ฃนํ™” ๋˜์–ด ๋ Œ๋”๋ง๋œ๋‹ค.
๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ์ด ์ค„์–ด๋“ค์–ด์„œ ๋ Œ๋”๋ง ์†๋„๋„ ํ›จ์”ฌ ๋นจ๋ผ์ง€๊ณ  ๋ฉˆ์ถ”๋Š” ํ˜„์ƒ๋„ ์—†์–ด์กŒ๋‹ค !
์‹œ๊ฐ์ ์œผ๋กœ๋„ ์ •๋ณด๊ฐ€ ํ›จ์”ฌ ๋ˆˆ์— ์ž˜ ๋“ค์–ด์˜ค๊ณ  ํŒŒ์•…ํ•˜๊ธฐ ์‰ฌ์›Œ์กŒ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€