diff --git a/.env.example b/.env.example
index b1ae6da..c8226b4 100644
--- a/.env.example
+++ b/.env.example
@@ -1,7 +1,12 @@
# 백엔드 API 주소 (dognation_BT)
VITE_API_BASE_URL=http://localhost:8080
-# 네이버 지도 (네이버 클라우드 플랫폼 > Maps 에서 발급)
+# 지도: 현재 카카오 지도 사용 (홈 화면). 네이버 키는 참고용으로 남겨둠.
+# 카카오 지도 (Kakao Developers > 내 애플리케이션 > 앱 키 > JavaScript 키)
+# 콘솔 > 플랫폼 > Web 에 서비스 도메인 등록 필요 (개발: http://localhost:9000)
+VITE_KAKAO_MAP_KEY=your_kakao_javascript_key
+
+# 네이버 지도 (네이버 클라우드 플랫폼 > Maps) — 현재 미사용, 코드는 유지
VITE_NAVER_MAP_CLIENT_ID=your_ncp_key_id
# 신규 키는 ncpKeyId(기본), 구형 키면 ncpClientId 로 변경
# VITE_NAVER_MAP_AUTH_PARAM=ncpKeyId
diff --git a/package-lock.json b/package-lock.json
index 143ff42..d183fa8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"@capacitor-community/apple-sign-in": "^7.1.0",
"@capacitor/app": "^8.0.0",
"@capacitor/core": "^8.3.4",
+ "@capacitor/geolocation": "^8.2.0",
"@quasar/extras": "^1.16.12",
"@stomp/stompjs": "^7.3.0",
"pinia": "^2.3.0",
@@ -158,6 +159,18 @@
"tslib": "^2.1.0"
}
},
+ "node_modules/@capacitor/geolocation": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/@capacitor/geolocation/-/geolocation-8.2.0.tgz",
+ "integrity": "sha512-N29QcoIPmme0xSxRkm7+3hjoHp6mBAOarxecvtCCZKyOBeKiJsFUq981cezg2XWBa6fhCXJMCCjQPngKK/dIag==",
+ "license": "MIT",
+ "dependencies": {
+ "@capacitor/synapse": "^1.0.4"
+ },
+ "peerDependencies": {
+ "@capacitor/core": ">=8.0.0"
+ }
+ },
"node_modules/@capacitor/ios": {
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-8.4.1.tgz",
@@ -168,6 +181,12 @@
"@capacitor/core": "^8.4.0"
}
},
+ "node_modules/@capacitor/synapse": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@capacitor/synapse/-/synapse-1.0.4.tgz",
+ "integrity": "sha512-/C1FUo8/OkKuAT4nCIu/34ny9siNHr9qtFezu4kxm6GY1wNFxrCFWjfYx5C1tUhVGz3fxBABegupkpjXvjCHrw==",
+ "license": "ISC"
+ },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
diff --git a/package.json b/package.json
index e4c813a..b4f3dac 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"@capacitor-community/apple-sign-in": "^7.1.0",
"@capacitor/app": "^8.0.0",
"@capacitor/core": "^8.3.4",
+ "@capacitor/geolocation": "^8.2.0",
"@quasar/extras": "^1.16.12",
"@stomp/stompjs": "^7.3.0",
"pinia": "^2.3.0",
diff --git a/src/components/KakaoMap.vue b/src/components/KakaoMap.vue
new file mode 100644
index 0000000..6e36440
--- /dev/null
+++ b/src/components/KakaoMap.vue
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/env.d.ts b/src/env.d.ts
index 67d58be..3535c9c 100644
--- a/src/env.d.ts
+++ b/src/env.d.ts
@@ -11,6 +11,7 @@ interface ImportMetaEnv {
readonly VITE_API_BASE_URL: string
readonly VITE_NAVER_MAP_CLIENT_ID: string
readonly VITE_NAVER_MAP_AUTH_PARAM?: string
+ readonly VITE_KAKAO_MAP_KEY: string
}
interface ImportMeta {
@@ -19,4 +20,5 @@ interface ImportMeta {
interface Window {
naver: typeof naver
+ kakao: typeof kakao
}
diff --git a/src/lib/kakaoMap.ts b/src/lib/kakaoMap.ts
new file mode 100644
index 0000000..f344311
--- /dev/null
+++ b/src/lib/kakaoMap.ts
@@ -0,0 +1,41 @@
+// 카카오 지도 JS SDK 동적 로더 (싱글턴)
+// JavaScript 키는 Kakao Developers > 내 애플리케이션 > 앱 키 > JavaScript 키.
+// .env 의 VITE_KAKAO_MAP_KEY 로 주입. 콘솔 > 플랫폼 > Web 에 서비스 도메인 등록 필요
+// (개발: http://localhost:9000 / 라이브리로드 IP, 배포: 실제 도메인·capacitor 스킴).
+let loadPromise: Promise | null = null
+
+export function loadKakaoMaps(): Promise {
+ if (typeof window !== 'undefined' && window.kakao?.maps) {
+ return Promise.resolve(window.kakao)
+ }
+ if (loadPromise) {
+ return loadPromise
+ }
+
+ const appKey = import.meta.env.VITE_KAKAO_MAP_KEY
+
+ loadPromise = new Promise((resolve, reject) => {
+ if (!appKey) {
+ reject(new Error('VITE_KAKAO_MAP_KEY 가 설정되지 않았습니다.'))
+ return
+ }
+ const script = document.createElement('script')
+ // autoload=false → 스크립트 로드 후 kakao.maps.load 로 명시적으로 초기화한다.
+ script.src = `https://dapi.kakao.com/v2/maps/sdk.js?appkey=${appKey}&autoload=false`
+ script.async = true
+ script.onload = () => {
+ // 키/도메인이 유효하지 않으면 load 콜백이 호출되지 않을 수 있어 타임아웃으로 방어.
+ const timer = setTimeout(
+ () => reject(new Error('카카오 지도 초기화 실패 · 키/도메인 등록을 확인하세요.')),
+ 8000,
+ )
+ window.kakao.maps.load(() => {
+ clearTimeout(timer)
+ resolve(window.kakao)
+ })
+ }
+ script.onerror = () => reject(new Error('카카오 지도 SDK 를 불러오지 못했습니다.'))
+ document.head.appendChild(script)
+ })
+ return loadPromise
+}
\ No newline at end of file
diff --git a/src/pages/HomePage.vue b/src/pages/HomePage.vue
index 5358b92..0126a9b 100644
--- a/src/pages/HomePage.vue
+++ b/src/pages/HomePage.vue
@@ -1,8 +1,8 @@
-
+
-
+
@@ -99,7 +99,7 @@ import { matchesApi } from '@/api/matches'
import { ApiError } from '@/api/http'
import { useAuthStore } from '@/stores/auth'
import { useDogsStore } from '@/stores/dogs'
-import NaverMap from '@/components/NaverMap.vue'
+import KakaoMap from '@/components/KakaoMap.vue'
import ChatDialog from '@/components/ChatDialog.vue'
const $q = useQuasar()
diff --git a/src/types/kakao-maps.d.ts b/src/types/kakao-maps.d.ts
new file mode 100644
index 0000000..92ac16a
--- /dev/null
+++ b/src/types/kakao-maps.d.ts
@@ -0,0 +1,67 @@
+// 카카오 지도 JS SDK 최소 타입 선언 (프로젝트에서 사용하는 API 서브셋).
+// 공식 @types 가 없어 필요한 부분만 선언한다.
+declare namespace kakao.maps {
+ class LatLng {
+ constructor(lat: number, lng: number)
+ getLat(): number
+ getLng(): number
+ }
+
+ class Map {
+ constructor(container: HTMLElement, options: { center: LatLng; level?: number })
+ panTo(latlng: LatLng): void
+ setCenter(latlng: LatLng): void
+ setLevel(level: number): void
+ getLevel(): number
+ addControl(control: ZoomControl, position: ControlPosition): void
+ }
+
+ // 지도 확대/축소 +/- 위젯
+ class ZoomControl {}
+
+ enum ControlPosition {
+ TOP,
+ TOPLEFT,
+ TOPRIGHT,
+ LEFT,
+ RIGHT,
+ BOTTOMLEFT,
+ BOTTOM,
+ BOTTOMRIGHT,
+ }
+
+ // 현재위치 표시용 원(파란 점)
+ class Circle {
+ constructor(options: {
+ center: LatLng
+ radius: number
+ strokeWeight?: number
+ strokeColor?: string
+ strokeOpacity?: number
+ fillColor?: string
+ fillOpacity?: number
+ })
+ setMap(map: Map | null): void
+ setPosition(latlng: LatLng): void
+ }
+
+ class Marker {
+ constructor(options: { position: LatLng; map?: Map; title?: string })
+ setMap(map: Map | null): void
+ getPosition(): LatLng
+ }
+
+ class InfoWindow {
+ constructor(options: { content?: string; removable?: boolean })
+ setContent(content: string): void
+ open(map: Map, marker?: Marker): void
+ close(): void
+ }
+
+ namespace event {
+ function addListener(target: unknown, type: string, handler: () => void): void
+ }
+
+ // autoload=false 로 로드한 뒤 SDK 초기화 콜백.
+ function load(callback: () => void): void
+}
\ No newline at end of file