도로명 주소를 카카오 지도에 마커 표시하기 위해 "주소로 장소 표시하기" 기능을 사용하였습니다.
🧾 목차
1. 과정
2. 결과화면
3. 전체 코드
4. 트러블 슈팅
1. 과정
1. 카카오 지도 스크립트 로드
2. 주소로 장소 표시하기 (libraries=services)
3. 타입 지정
1-1. 카카오 지도 스크립트 로드
카카오 맵은 카카오 지도에 사용되는 기능들 (= 기초 설정) 파일을 이미 만들어 놓고 우리는 그것을 로드하여 사용하면 됩니다.
이걸 v3 스크립트라고 합니다.
v3 스크립트를 동적으로 로드하기위해 사용한다.
스크립트의 로딩이 끝나기 전에 v3의 객체에 접근하려고 하면 에러가 발생하기 때문에
로딩이 끝나는 시점에 콜백을 통해 객체에 접근할 수 있도록 해 준다.
비동기 통신으로 페이지에 v3를 동적으로 삽입할 경우에 주로 사용된다.
v3 로딩 스크립트 주소에 파라메터로 autoload=false를 지정해 주어야 한다.
(참고: https://apis.map.kakao.com/web/documentation/#load_load)
이해한 바로는 autoload=false 설정은 자동 로드가 아닌 필요 시 동적 로드 설정이며,
비동기적으로 로드가 진행되므로, 완료된 시점을 캐치하기 위하여 kakao.maps.load()를 사용하여 콜백 함수를 실행.
그래서 지도 그리는 부분은 콜백 함수로 넣는다!
이걸 코드로 구현하자면, 다음과 같습니다.
- v3 스크립트를 동적으로 추가
- autoload=false
- v3가 모두 로드된 후, drawMap()를 실행
useEffect(() => {
if (!roadNameAddress) return;
// v3 스크립트 동적 추가
const script = document.createElement("script");
script.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${import.meta.env.VITE_KAKAO_MAP_APP_KEY}&autoload=false&libraries=services`;
script.async = true;
document.head.appendChild(script);
const onLoadKakaoMap = () => {
// v3가 모두 로드된 후, 이 콜백함수가 실행
window.kakao.maps.load(() => {
drawMap(roadNameAddress);
});
};
script.addEventListener("load", onLoadKakaoMap);
return () => {
document.head.removeChild(script);
};
}, [roadNameAddress]);
1-2. 주소로 장소 표시하기 (libraries=services)
1번에서 스크립트를 로드했다면 이제는 화면에 실제 지도를 그려야합니다.
const drawMap = (address: string) => {
const mapContainer = document.getElementById("map");
if (!mapContainer) return;
const mapOption = {
center: new window.kakao.maps.LatLng(33.450701, 126.570667), // 초기 좌표
level: 5 // 확대 수준
};
const map = new window.kakao.maps.Map(mapContainer, mapOption);
const geocoder = new window.kakao.maps.services.Geocoder();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
geocoder.addressSearch(address, (result: any, status: any) => {
if (status === window.kakao.maps.services.Status.OK) {
const coords = new window.kakao.maps.LatLng(result[0].y, result[0].x);
// 마커 생성
new window.kakao.maps.Marker({
map: map,
position: coords
});
// 지도 중심 이동
map.setCenter(coords);
} else {
console.error("주소 검색에 실패했습니다:", status);
}
});
};
꼭 확인해야 하는 점은 "주소로 장소 표시하기" 기능은 카카오맵에서도 라이브러리로 따로 분류가 되어있습니다. 이를 위해서 스크립트의 파라미터로 libraries=services가 추가되어있는지 다시 한번 확인합니다.

1-3. 타입 지정
kakao 객체의 존재를 타입스크립트가 알지 못하기 때문에
window.kakao의 타입을 지정합니다.
declare global {
interface Window {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
kakao: any;
}
}
export {};
결과화면

전체 코드
import { useEffect } from "react";
import styled from "styled-components";
import Empty from "../common/Empty/Empty";
interface Props {
roadNameAddress: string | null;
}
const ActiveCenterMap = ({ roadNameAddress }: Props) => {
useEffect(() => {
if (!roadNameAddress) return;
// 스크립트 동적 추가
const script = document.createElement("script");
script.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${import.meta.env.VITE_KAKAO_MAP_APP_KEY}&autoload=false&libraries=services`;
script.async = true;
document.head.appendChild(script);
const onLoadKakaoMap = () => {
window.kakao.maps.load(() => {
drawMap(roadNameAddress);
});
};
script.addEventListener("load", onLoadKakaoMap);
return () => {
document.head.removeChild(script);
};
}, [roadNameAddress]);
const drawMap = (address: string) => {
const mapContainer = document.getElementById("map");
if (!mapContainer) return;
const mapOption = {
center: new window.kakao.maps.LatLng(33.450701, 126.570667), // 초기 좌표
level: 4 // 확대 수준
};
const map = new window.kakao.maps.Map(mapContainer, mapOption);
const geocoder = new window.kakao.maps.services.Geocoder();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
geocoder.addressSearch(address, (result: any, status: any) => {
if (status === window.kakao.maps.services.Status.OK) {
const coords = new window.kakao.maps.LatLng(result[0].y, result[0].x);
// 마커 생성
new window.kakao.maps.Marker({
map: map,
position: coords
});
// 지도 중심 이동
map.setCenter(coords);
} else {
console.error("주소 검색에 실패했습니다:", status);
}
});
};
return (
<Wrapper>
{roadNameAddress ? (
<>
<Info>
<div className="center-address">{roadNameAddress}</div>
</Info>
<Map id="map"></Map>
</>
) : (
<Empty
name="search"
color="review"
size="15px"
descriptions="코치님의 활동 센터 정보가 없어요"
/>
)}
</Wrapper>
);
};
const Wrapper = styled.div`
background-color: #111111;
border-radius: 24px;
padding: 20px;
min-height: 330px;
`;
const Info = styled.div`
display: flex;
flex-direction: column;
gap: 10px;
margin-bottom: 30px;
.center-address {
font-size: 13px;
font-weight: 400;
line-height: 20px;
letter-spacing: -0.65px;
}
`;
const Map = styled.div`
width: 100%;
height: 180px;
`;
export default ActiveCenterMap;
트러블 슈팅
1. v3 스크립트 로드 관련 문제
v3 스크립트 로드 작업은 비동기 작업니다.
로드가 완료되어야 지도의 기능들을 완벽히 사용할 수 있기 때문에, 완료 시점을 캐치하여 콜백함수를 실행하는 것이 중요합니다.
✔ 체크 리스트
- autoload=false
- kakao.maps.load(콜백함수)
제대로 설정이 되어있지 않다면 ~~생성자가 없습니다. 뭐가 없습니다 이런식으로 계속 오류가 뜨게됩니다.
2. 라이브러리 기능 사용 문제
카카오맵 중에서도 라이브러리로 따로 분류된 기능들이 있습니다.
그런 경우에는 반드시 라이브러리 관련해서도 스크립트 로드를 해야합니다.
✔ 체크 리스트
- libraries=services
'코치코치' 카테고리의 다른 글
white-space: pre-line 스타일 추가로 줄바꿈 인식 (0) | 2024.11.30 |
---|---|
코치 폴더 구조 리팩토링 (Feat. cursor ai) (0) | 2024.11.24 |
검색 시 새로고침 제거 (react-hook-form) (0) | 2024.11.13 |
정보구조도(IA) (2) | 2024.10.25 |
SVG 공통 컴포넌트 사용하기 (0) | 2024.10.20 |