๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Couch Coding

Couch Coding ( ์นด์šฐ์น˜ ์ฝ”๋”ฉ ) - ReactKakaoMapSDK ์ด์šฉํ•˜์—ฌ ๋งˆ์ปค, ์ปค์Šคํ…€ ์˜ค๋ฒ„๋ ˆ์ด ์ƒ์„ฑํ•˜๊ธฐ (์นด์นด์˜ค๋งต)

 

์šฐ๋ฆฌ ํŒ€์ด ํ˜„์žฌ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š” CampUs ์„œ๋น„์Šค๋Š” ์ง€๋„๋ฅผ ํ†ตํ•ด ์บ ํ•‘์žฅ์˜ ์ขŒํ‘œ๋ฅผ ํ™•์ธํ•˜๊ณ  ์บ ํ•‘์žฅ์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋Š” ์„œ๋น„์Šค์ด๋‹ค

์œ„ ์‚ฌ์ง„์ฒ˜๋Ÿผ ์บ ํ•‘์žฅ์„ ๊ฒ€์ƒ‰ํ•˜๋ฉด ๊ทธ ๊ฒฐ๊ณผ์— ๋”ฐ๋ฅธ ์ขŒํ‘œ๊ฐ€ ์ง€๋„์— ๋“ฑ๋ก๋˜๊ณ  ๋งˆ์ปค๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ์‚ฌ์ง„๊ณผ ๊ฐ™์•„ '์ปค์Šคํ…€ ์˜ค๋ฒ„๋ ˆ์ด'๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋ง ํ•œ๋‹ค. 

 

์ด์ „์— kakaoMap API๋ฅผ ํ†ตํ•ด ๋ฆฌ์•กํŠธ์—์„œ ๊ฐœ๋ฐœ์„ ํ–ˆ์„ ๋•Œ ๋ฆฌ์•กํŠธ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ์กฐ๊ธˆ ๋ถˆํŽธํ•˜๋‹ค๊ณ  ๋А๋‚€์ ์ด ์žˆ์–ด์„œ 

ํŽธ๋ฆฌํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—†์„๊นŒ ์ฐพ์•„๋ณด๋‹ค๊ฐ€ 

 

 

https://github.com/JaeSeoKim/react-kakao-maps-sdk

 

GitHub - JaeSeoKim/react-kakao-maps-sdk: React components for using kakao map api

React components for using kakao map api. Contribute to JaeSeoKim/react-kakao-maps-sdk development by creating an account on GitHub.

github.com

 

 

react-kakao-maps-sdk ๋ผ๊ณ ํ•˜๋Š” ๋ฆฌ์•กํŠธ์—์„œ ์นด์นด์˜ค๋งต API๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ตœ์ ํ™”๋œ ๊ธฐ๊ฐ€๋ง‰ํžŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ๋‹ค....!

 

์‚ฌ์šฉ๋ฒ•์€ ๋ฌด์ฒ™ ๊ฐ„๋‹จํ•˜๋‹ˆ ์ƒ˜ํ”Œ์„ ๋ณด๋ฉด์„œ ๋”ฐ๋ผํ•˜๊ธธ ๋ฐ”๋ž€๋‹ค. 

 

 

์šฐ๋ฆฌ๋Š” ์ด์ œ ๋งˆ์ปค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž !

 

// CampLocation.jsx
import { Map } from 'react-kakao-maps-sdk';
import EventMarker from '../SearchLocation/EventMarker/EventMarker';

const CampLocation = ({
  campList, // ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ›์€ ๋ฐฐ์—ด๋กœ ์ด๋ฃจ์–ด์ง„ ์บ ํ•‘์žฅ๋ฆฌ์ŠคํŠธ
}) => {
  return (
    <Wrap PropState={PropState}>
      <MapStyle // ์ง€๋„๋ฅผ ํ‘œ์‹œํ•  Container
        center={{
          // ์ง€๋„์˜ ์ค‘์‹ฌ์ขŒํ‘œ
          lat: campList[0].mapY,
          lng: campList[0].mapX
        }}
        level={3} // ์ง€๋„์˜ ํ™•๋Œ€ ๋ ˆ๋ฒจ
      >
        // ์บ ํ•‘์žฅ๋ฆฌ์ŠคํŠธ๋ฅผ mapํ•จ์ˆ˜๋กœ ๋Œ๋ ค์„œ ๊ฐ ์บ ํ•‘์žฅ ๋ฐ์ดํ„ฐ๋ฅผ EventMarker ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌ
        {campList.map((camp) => <EventMarker key={camp.id} camp={camp} />)}
      </MapStyle>
    </Wrap>
  );
};

 

CampLocation ๋ผ๋Š” ์ด๋ฆ„์˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋‹ค.

์ง€๋„์˜ ์ค‘์‹ฌ์ขŒํ‘œ๋Š” ์ฒ˜์Œ ์ง€๋„๊ฐ€ ๋ณด์—ฌ์ง€๋Š” ์ขŒํ‘œ์ด๊ณ  ๋‚˜๋Š” ์ด ์ค‘์‹ฌ ์ขŒํ‘œ๋ฅผ ๋ฆฌ์ŠคํŠธ์˜ ์ฒซ๋ฒˆ์งธ ์บ ํ•‘์žฅ์ด ๊ธฐ์ค€์ด ๋˜๊ฒŒ ํ•˜์˜€๋‹ค.

 

CampList๋ผ๋Š” ์บ ํ•‘์žฅ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง„ ๋ฐฐ์—ด์„ map ํ•จ์ˆ˜๋กœ EventMarker ๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ๊ฐ ์บ ํ•‘์žฅ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

EventMarker ์ปดํฌ๋„ŒํŠธ๋Š” ๊ฐ ์บ ํ•‘์žฅ์˜ X, Y ์ขŒํ‘œ๋ฅผ ๊ฐ€์ง€๊ณ  ์ง€๋„์— ๋งˆ์ปค๋ฅผ ๊ฝ‚์•„์ฃผ๊ฒŒ ๋œ๋‹ค !

 

 

์šฐ์„  ์—ฌ๊ธฐ์„œ ํฌ์ธํŠธ๋Š”

 

import { Map } from 'react-kakao-maps-sdk';

 

์œ„ ์ฒ˜๋Ÿผ react-kakao-map-sdk๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๋ฆฌ์•กํŠธ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์ปดํฌ๋„ŒํŠธ ํ˜•์‹์œผ๋กœ import ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— 

๊ธฐ์กด ์นด์นด์˜ค๋งต API ๋ณด๋‹ค ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค ! ๐Ÿ‘๐Ÿ‘๐Ÿ‘

 

 

์ด์ œ EventMarker ์ปดํฌ๋„ŒํŠธ๋ฅผ ์•Œ์•„๋ณด์ž 

 

 

 

//EventMarker.jsx
import React, { useEffect, useState } from 'react';
import { CustomOverlayMap, MapMarker } from 'react-kakao-maps-sdk';
import defaultImg from '../../../Assets/Images/default_image.png';

const EventMarkerContainer = ({ camp }) => {
  const [isVisible, setIsVisible] = useState(false); // true๋ฉด ์ปค์Šคํ…€ ์˜ค๋ฒ„๋ ˆ์ด ๋ Œ๋”๋ง
  const [position, setPosition] = useState({
    lat: '',
    lng: '',
  });

  // ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋˜๋ฉด position State์— X,Y ์ขŒํ‘œ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค
  useEffect(() => { 
    setPosition({
      lat: camp.mapY,
      lng: camp.mapX,
    });
  }, [camp.mapX, camp.mapY]);

  return (
    <>
      // ์ง€๋„์ƒ์— ๋†“์ด๋Š” ๋งˆ์ปค
      <MapMarker
        position={position} // ๋งˆ์ปค๋ฅผ ํ‘œ์‹œํ•  ์œ„์น˜
        onClick={() => setIsVisible(true)} // ํด๋ฆญํ•˜๋ฉด ์ปค์Šคํ…€ ์˜ค๋ฒ„๋ ˆ์ด๊ฐ€ ๋ Œ๋”๋ง ๋œ๋‹ค !
      />
      {isVisible && ( //isVisible์ด true์ด๋ฉด ๋ Œ๋”๋ง 
        <CustomOverlayMap
          position={position} // ์ปค์Šคํ…€ ์˜ค๋ฒ„๋ ˆ์ด๊ฐ€ ๋‚˜ํƒ€๋‚  ์œ„์น˜
          style={{
            width: '300px',
            transform: 'translate(-20px, -100px)',
            backgroundColor: 'white',
            borderRadius: '5px',
            boxShadow: '0px 1px 2px #888',
          }}
        >
          <div className="wrap">
            <div className="info">
              <Title>
                {camp.facltNm}
                <CloseBtn onClick={() => setIsVisible(false)} title="๋‹ซ๊ธฐ">
 	
        ....
        ....
        ....
        ....

 

 

๋ง ๊ทธ๋Œ€๋กœ '์ปค์Šคํ…€ ์˜ค๋ฒ„๋ ˆ์ด' ์ด๊ธฐ ๋•Œ๋ฌธ์— ์Šคํƒ€์ผ์€ ๋งˆ์Œ๋Œ€๋กœ ์ปค์Šคํ…€์ด ๊ฐ€๋Šฅํ•˜๋‹ค 

 

useEffect์—์„œ position์ด๋ผ๋Š” state์— ๊ฐ ์บ ํ•‘์žฅ์˜ X, Y ์ขŒํ‘œ๋ฅผ ๋„ฃ์–ด์ฃผ๊ณ  ๋งˆ์ปค์™€ ์ปค์Šคํ…€ ์˜ค๋ฒ„๋ ˆ์ด ์ปดํฌ๋„ŒํŠธ์— 

position ์˜ต์…˜์„ ๋ถ€์—ฌํ•˜๋ฉด ์ง€๋„์ƒ์—์„œ ๋งˆ์ปค์™€ ์ปค์Šคํ…€ ์˜ค๋ฒ„๋ ˆ์ด๋ฅผ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค !

 

์•„๋ž˜๋Š” ํ˜„์žฌ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š” ์„œ๋น„์Šค์˜ ๋งˆ์ปค์™€ ์ปค์Šคํ…€ ์˜ค๋ฒ„๋ ˆ์ด๋ฅผ ๊ตฌํ˜„ํ•œ ๋ชจ์Šต์ด๋‹ค .

 


๊ธฐ์กด์˜ ์นด์นด์˜ค๋งต API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋А๊ผˆ๋˜ ๋ถˆํŽธํ•œ ์ ์„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉ ํ•จ์œผ๋กœ์จ ํŽธ๋ฆฌํ•จ์„ ๋А๋ผ๊ฒŒ ๋˜์—ˆ๋‹ค 

 

๋‹ค์Œ์— ์–ธ์  ๊ฐ€ ์ง€๋„๋ฅผ ์ด์šฉํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๊ฒŒ๋˜๋ฉด ๋˜ ์“ฐ์ง€ ์•Š์„๊นŒ ?