From bb2d88804f8591020b642f4f155b09007dba8072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=8B=9C=EC=9A=B4?= Date: Tue, 23 Jul 2024 21:02:39 +0900 Subject: [PATCH 1/3] =?UTF-8?q?INV-29=20=EC=B9=B4=EC=B9=B4=EC=98=A4?= =?UTF-8?q?=EB=A7=B5=20SDK=20=EC=97=B0=EB=8F=99=20/=20=EC=A3=BC=EC=86=8C?= =?UTF-8?q?=20=EA=B2=80=EC=83=89(=EC=9A=B0=ED=8E=B8=EB=B2=88=ED=98=B8)=20A?= =?UTF-8?q?PI=20=EC=97=B0=EA=B2=B0=20(#3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: playground에 kakao 지도 sdk 추가 * feat: kakao map type 선언 및 컴포넌트로 분리 * feat: 위치 검색 기능 추가 * fix: build 에러 해결 * fix: 빌드 시, zustand 종속성 문제 해결 * fix: interface type import로 변경 * chore: eslint 스타일 적용 * feat: 위 경도 커스터마이징 가능 * refactor: url 환경변수화 * refactor: 전역 상태에서 context provider 기반으로 리팩토링 * fix: conflict reslove 및 컨벤션에 맞춘 전역상태 설정 * fix: build error 해결 - 타입 import 적용 * refactor: 위치변경시 맵이 리랜더링 되지 않고 위치만 변경되게 수정 * feat: KAKAO MAP 환경변수 추가 설정 --- .env.template | 6 ++ .../_components/AddressSearchButton/index.tsx | 34 ++++++++ .../_components/KakaoAddressContext/index.tsx | 45 +++++++++++ .../map/_components/KakaoMap/index.tsx | 78 +++++++++++++++++++ .../MapUtilsButton/UtilsContainer/index.tsx | 1 + .../map/_components/MapUtilsButton/index.tsx | 0 .../(playground)/playground/map/layout.tsx | 24 ++++++ src/app/(playground)/playground/map/page.tsx | 37 +++++++++ src/lib/env.ts | 4 + src/types/global/kakao.d.ts | 24 ++++++ 10 files changed, 253 insertions(+) create mode 100644 src/app/(playground)/playground/map/_components/AddressSearchButton/index.tsx create mode 100644 src/app/(playground)/playground/map/_components/KakaoAddressContext/index.tsx create mode 100644 src/app/(playground)/playground/map/_components/KakaoMap/index.tsx create mode 100644 src/app/(playground)/playground/map/_components/MapUtilsButton/UtilsContainer/index.tsx create mode 100644 src/app/(playground)/playground/map/_components/MapUtilsButton/index.tsx create mode 100644 src/app/(playground)/playground/map/layout.tsx create mode 100644 src/app/(playground)/playground/map/page.tsx create mode 100644 src/types/global/kakao.d.ts diff --git a/.env.template b/.env.template index 480d766..6282d32 100644 --- a/.env.template +++ b/.env.template @@ -21,3 +21,9 @@ KAKAO_REDIRECT_URI= NAVER_CLIENT_ID= NAVER_CLIENT_SECRET= NAVER_REDIRECT_URI= + +## KAKAO MAP +### @see https://developers.kakao.com/console/app/1102339/config/appKey +KAKAO_MAP_BASE_URL= +KAKAO_MAP_API_KEY= +DAUMCDN_POSTOCDE_URL= \ No newline at end of file diff --git a/src/app/(playground)/playground/map/_components/AddressSearchButton/index.tsx b/src/app/(playground)/playground/map/_components/AddressSearchButton/index.tsx new file mode 100644 index 0000000..3d6c6ab --- /dev/null +++ b/src/app/(playground)/playground/map/_components/AddressSearchButton/index.tsx @@ -0,0 +1,34 @@ +"use client"; + +import { useKakaoAddress } from "~/app/(playground)/playground/map/_components/KakaoAddressContext"; + +export default function AddressSearchButton() { + const { setCoordinate } = useKakaoAddress(); + + const handleClickButton = () => { + new window.daum.Postcode({ + oncomplete: (addressData: any) => { + const geocoder = new window.kakao.maps.services.Geocoder(); + geocoder.addressSearch( + addressData.address, + (result: any, status: any) => { + const currentPositions = new window.kakao.maps.LatLng( + result[0].y, + result[0].x, + ); + setCoordinate(currentPositions.Ma, currentPositions.La); + }, + ); + }, + }).open(); + }; + + return ( + + ); +} diff --git a/src/app/(playground)/playground/map/_components/KakaoAddressContext/index.tsx b/src/app/(playground)/playground/map/_components/KakaoAddressContext/index.tsx new file mode 100644 index 0000000..28207b1 --- /dev/null +++ b/src/app/(playground)/playground/map/_components/KakaoAddressContext/index.tsx @@ -0,0 +1,45 @@ +"use client"; + +import type { ReactNode } from "react"; +import { createContext, useContext, useState } from "react"; + +export interface Coordinate { + latitude: number; + longitude: number; +} + +interface KakaoAddressContextType { + coordinate: Coordinate; + setCoordinate: (latitude: number, longitude: number) => void; +} + +const KakaoAddressContext = createContext( + undefined, +); + +export function KakaoAddressProvider({ children }: { children: ReactNode }) { + const [coordinate, setCoordinateState] = useState({ + latitude: 37.566828, + longitude: 126.9786567, + }); + + const setCoordinate = (latitude: number, longitude: number) => { + setCoordinateState({ latitude, longitude }); + }; + + return ( + + {children} + + ); +} + +export function useKakaoAddress() { + const context = useContext(KakaoAddressContext); + if (context === undefined) { + throw new Error( + "useKakaoAddress must be used within a KakaoAddressProvider", + ); + } + return context; +} diff --git a/src/app/(playground)/playground/map/_components/KakaoMap/index.tsx b/src/app/(playground)/playground/map/_components/KakaoMap/index.tsx new file mode 100644 index 0000000..1da4e3b --- /dev/null +++ b/src/app/(playground)/playground/map/_components/KakaoMap/index.tsx @@ -0,0 +1,78 @@ +"use client"; + +import { useEffect, useRef } from "react"; +import { useKakaoAddress } from "~/app/(playground)/playground/map/_components/KakaoAddressContext"; + +interface KakaoMapProps { + width: string; + height: string; + level?: number; + addCenterPin?: boolean; + latitude?: number; + longitude?: number; +} + +export default function KakaoMap({ + width, + height, + level = 3, + addCenterPin = false, + latitude, + longitude, +}: KakaoMapProps) { + const { coordinate } = useKakaoAddress(); + const mapRef = useRef(null); + const mapInstanceRef = useRef(null); + const markerRef = useRef(null); + + useEffect(() => { + if (!mapRef.current) return; + + const initializeMap = () => { + const center = new window.kakao.maps.LatLng( + latitude ?? coordinate.latitude, + longitude ?? coordinate.longitude, + ); + + const mapInstance = new window.kakao.maps.Map( + mapRef.current as HTMLElement, + { + center, + level, + }, + ); + + mapInstanceRef.current = mapInstance; + + if (addCenterPin) { + const marker = new window.kakao.maps.Marker({ position: center }); + marker.setMap(mapInstance); + markerRef.current = marker; + } + }; + + if (window.kakao && window.kakao.maps) { + window.kakao.maps.load(initializeMap); + } + }, []); + + useEffect(() => { + if (mapInstanceRef.current) { + const newCenter = new window.kakao.maps.LatLng( + latitude ?? coordinate.latitude, + longitude ?? coordinate.longitude, + ); + mapInstanceRef.current.setCenter(newCenter); + + if (addCenterPin && markerRef.current) { + markerRef.current.setPosition(newCenter); + } + } + }, [coordinate]); + + return ( +
+
+
+ ); +} diff --git a/src/app/(playground)/playground/map/_components/MapUtilsButton/UtilsContainer/index.tsx b/src/app/(playground)/playground/map/_components/MapUtilsButton/UtilsContainer/index.tsx new file mode 100644 index 0000000..398f5b4 --- /dev/null +++ b/src/app/(playground)/playground/map/_components/MapUtilsButton/UtilsContainer/index.tsx @@ -0,0 +1 @@ +export default function UtilsContainer() {} diff --git a/src/app/(playground)/playground/map/_components/MapUtilsButton/index.tsx b/src/app/(playground)/playground/map/_components/MapUtilsButton/index.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/app/(playground)/playground/map/layout.tsx b/src/app/(playground)/playground/map/layout.tsx new file mode 100644 index 0000000..5c94016 --- /dev/null +++ b/src/app/(playground)/playground/map/layout.tsx @@ -0,0 +1,24 @@ +import Script from "next/script"; +import { env } from "~/lib/env"; + +export default function KaKaoMapPageLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + <> +