병원 상세페이지에 주소를 좌표로 바꾸어 표시하기 위해 카카오맵을 사용하기로 했다.
이전 글에 이어서 이번 게시글에서는 카카오맵을 Next.js 14 App Router 환경에서 방법을 정리해보려고 한다.
1. 패키지 설치하기
React와 카카오맵을 같이 사용할 때 많이들 카카오가 아닌 개인이 만든 sdk를 추가 설치해 사용한다.
npm install react-kakao-maps-sdk
yarn add react-kakao-maps-sdk
또한 TS를 같이 사용하는 경우 같은 분이 정리한 'kakao.maps.d.ts'를 추가 설치하면 좋다. 그러면 전역에 `kakao` 객체를 알아서 추가해준다.
npm install kakao.maps.d.ts --save-dev
yarn add kakao.maps.d.ts --dev
설치 후에는 `tsconfig.json` 파일에 아래를 추가해준다.
// tsconfig.json
{
...,
"compilerOptions": {
...,
"types": [
...,
"kakao.maps.d.ts"
]
}
}
만약 TS를 사용하는데 위 패키지를 사용하지 않는다면 아래 코드를 RootLayout에 추가해준다.
# src/app/layout.tsx
declare global {
interface Window {
kakao: any;
}
}
위 과정을 거치지 않으면 kakao나 maps를 찾을 수 없다는 런타임 에러가 발생한다.
2. api 키 저장하기
카카오맵에서 준 javascript 키를 `.env`파일에 아래와 같이 추가한다.
# .env(.local)
...
NEXT_PUBLIC_KAKAOMAP_API_KEY=발급받은 키
3. Next.js의 Script 컴포넌트 사용하기
검색해보니 크게 두 가지 방법으로 api를 연결하는 것을 알 수 있었다. 1. JS 문법을 사용해 직접 head 태그 내부에 script 태그를 추가해 api를 연결하는 방법과 2. Next.js의 Scripts 컴포넌트를 사용하는 방법이다.
나는 Script 컴포넌트를 사용해 api를 연결했다. RootLayout에 아래와 같이 추가했다.
# src/app/layout.tsx
const KAKAOMAP_API_URL = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.NEXT_PUBLIC_KAKAOMAP_API_KEY}&libraries=services&autoload=false`;
const RootLayout = ({
children
}: Readonly<{
children: React.ReactNode;
}>) => {
return (
<html lang="kr">
...
<body ...>
<Script src={KAKAOMAP_API_URL} strategy="beforeInteractive" />
...
{children}
...
</body>
</html>
);
};
export default RootLayout;
여기서 조금 더 자세히 살펴보자.
- `strategy="beforeInteractive"`
strategy는 성능 최적화를 위해 추가된 속성이다. `beforeInteractive`는 어떤 다른 코드보다도 먼저 script를 실행한다는 옵션이다. 기본값은 'afterInteractive'인데 이는 빠르게 불러오긴하지만 어떤 코드가 실행된 후일 수도 있다.
- `autoload=false`
`KAKAOMAP_API_URL`을 보면 `autoload=false`라는 조건이 들어있는 것을 볼 수 있는데, 이는 script를 동적으로 불러올 경우, script가 준비되기 전에 코드에서 api를 사용할 수도 있기 때문이다. 이 조건을 추가했다면 코드에서 `kakao.maps.load`를 통해 script를 불러와 사용하면 된다.
- `libraries=services`
`KAKAOMAP_API_URL`을 보면 ` libraries=services `라는 조건이 들어있는 것을 볼 수 있는데, 이는 사용할 라이브러리를 추가한 것이다. 나는 라이브러리 중 services의 geocoder를 사용할 것이므로 해당 조건을 추가했다.
4. 카카오맵 api 사용하기
이제 정말 카카오맵을 사용해보자.
먼저 script가 준비된 후 실행해야하므로 `useEffect`를 사용해야 한다. 또한 위에서 언급했듯이 `autoload=false` 옵션을 추가했으므로 `useEffect` 내부에서 `kakao.maps.load`를 사용해야 한다.
위에서 계속 `kakao.~`을 사용했는데, 이렇게 사용하려면 window에서 kakao 객체를 꺼내와야한다. 나는 그냥 `window.kakao.~`로 작성했다.
기본 틀은 아래와 같다.
"use client";
import { useEffect } from "react";
import { Map, MapMarker } from "react-kakao-maps-sdk";
const HospitalMap = ({ orgAddr }: { orgAddr: string }) => {
useEffect(() => {
window.kakao.maps.load(() => {
...
});
}, []);
return (
<section>
<p>위치</p>
<Map center={coords} level={1}>
<MapMarker position={coords} />
</Map>
</section>
);
};
export default HospitalMap;
위 코드에서 `Map`과 `MapMarker`는 sdk에서 불러온 컴포넌트이다. 따라서 카카오맵 공식 문서와 사용방법이 조금 다르다.
5. Geocoder 사용하기
script가 준비된 후 geocoder 객체를 생성해 `.addressSearch` 메서드에 주소와 콜백함수를 넣어 실행한다.
useEffect(() => {
window.kakao.maps.load(() => {
// geocoder 객체 생성
const geocoder = new window.kakao.maps.services.Geocoder();
// orgAddr 좌료를 검색하고자 하는 주소 (병원 주소)
geocoder.addressSearch(orgAddr, (result, status) => {
// 정상적으로 검색이 완료된 경우
if (status === window.kakao.maps.services.Status.OK) {
setCoords({ lat: Number(result[0].y), lng: Number(result[0].x) });
}
});
});
}, []);
// 최초 렌더링 후 실행되므로 빈 의존성 배열
geocoder의 검색 결과(`result`)는 사실 유사한 다른 검색 결과도 포함하므로 한개가 아닐 수도 있다. (option에 따라 정확히 일치하는 결과만 받을 수도 있다.) 편의상 맨 첫번째 결과를 사용했다.
콜백 함수의 인자가 any라서 VSCode에서 빨간줄도 쳐주고, build 시에도 에러를 받았는데, 타입을 import할 수가 없어 gpt를 사용해 result와 status에 대한 type을 생성해 사용했다.
참고
'Frontend > Projects' 카테고리의 다른 글
[Next.js] 카카오맵 api 사용하기 - 1 (0) | 2025.01.07 |
---|---|
[Next.js] useRouter 페이지 로딩 속도 개선 (0) | 2024.11.19 |
[React] TanStack Query 낙관적 업데이트 (+ 연관 문제 해결) (0) | 2024.11.10 |
[React] mutationFn에 여러 parameter를 갖는 함수 사용하기 (0) | 2024.10.15 |
[Next.js] supabase server side auth 설정하기 (4) | 2024.10.14 |