Vite React Kakao Map
Vite React Daum Address Api

이번 글을 통해 배워갈 내용
- 개요
- 기초세팅
- 리액트 카카오맵 다음지도 연동 컴포넌트
- 리액트 카카오맵
- 리액트 다음지도 API
개요
해당 프로젝트는 리액트에
카카오맵과 다음 지도 연동 기능을 같이 추가한 다음
연동해서 활용하는 미니 프로젝트입니다|
주소를 선택하면
지도에 자동으로 선택되는 컴포넌트를 만들었습니다

기초세팅
(카카오 데브에서 가입, CORS 등에 세팅은 스킵합니다)
먼저 카카오 Developers를 방문해서
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
자바스크립트 키를 찾습니다

1-1 env 파일에 환경변수를 추가해 줍니다
VITE_KAKAOMAP_JAVASCRIPT_APP_KEY= "위에 있는 Javascript 키 값"
1-2
index.html 파일에 script 두 개를 추가합니다
<script type="text/javascript" strategy="beforeInteractive" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=%VITE_KAKAOMAP_JAVASCRIPT_APP_KEY%&libraries=services,clusterer,drawing"></script>
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
1-3
리액트 타입스크립트기반에서
카카오맵과 다음 주소를 쓰기 위해서
kakao.maps.d.ts와 react-daum-postcode를 설치했습니다
https://www.npmjs.com/package/react-daum-postcode
react-daum-postcode
Daum Postcode service for React. Latest version: 3.1.3, last published: 9 months ago. Start using react-daum-postcode in your project by running `npm i react-daum-postcode`. There are 19 other projects in the npm registry using react-daum-postcode.
www.npmjs.com
https://www.npmjs.com/package/kakao.maps.d.ts
kakao.maps.d.ts
Kakao Map API Type Definitions. Latest version: 0.1.39, last published: 7 months ago. Start using kakao.maps.d.ts in your project by running `npm i kakao.maps.d.ts`. There are 2 other projects in the npm registry using kakao.maps.d.ts.
www.npmjs.com
# react-daum-postcode
# npm
npm install react-daum-postcode
# yarn
yarn add react-daum-postcode
# kakao.maps.d.ts
# npm
npm install kakao.maps.d.ts --save-dev
# yarn
yarn add kakao.maps.d.ts --dev
리액트 카카오맵 다음지도 연동 컴포넌트
AddressInput.tsx
(tailwind 기반으로 만들었습니다)
/**
Comment by CodeMaster KimC
For more information, visit: https://codemasterkimc.tistory.com
*/
import { FC, useState } from 'react';
import DaumAddr, { IAddr, initialAddressInfo } from './DaumAddrInput';
import KakaoMap from './KakaoMapDisplay';
interface IProps {}
const AddressInput: FC<IProps> = ({}) => {
const [kakaoAddr, setKakaoAddr] = useState<IAddr>(initialAddressInfo);
return (
<div>
<label className="block text-sm font-medium text-gray-900 mb-2">도로명 주소</label>
<DaumAddr kakaoAddr={kakaoAddr} setKakaoAddr={setKakaoAddr} />
<KakaoMap kakaoAddr={kakaoAddr} />
</div>
);
};
export default AddressInput;
리액트 카카오맵
KakaoMap.tsx
/**
Comment by CodeMaster KimC
For more information, visit: https://codemasterkimc.tistory.com
*/
import { FC, useEffect, useState } from 'react';
import { IAddr } from './DaumAddrInput';
declare global {
interface Window {
kakao: any;
}
}
interface IProps {
kakaoAddr: IAddr;
}
const KakaoMap: FC<IProps> = ({ kakaoAddr }) => {
const [map, setMap] = useState<any>();
const [marker, setMarker] = useState<any>();
const initMap = () => {
const container = document.getElementById('map');
const options: MapOptions = {
center: new window.kakao.maps.LatLng(37.532600, 127.024612),
level: 3,
draggable: false,
scrollwheel: false,
disableDoubleClick: false,
disableDoubleClickZoom: false,
tileAnimation: false,
keyboardShortcuts: false,
};
setMap(new window.kakao.maps.Map(container, options));
setMarker(new window.kakao.maps.Marker());
};
useEffect(() => {
window.kakao.maps.load(() => initMap());
}, []);
useEffect(() => {
const asyncFn = async () => {
if (!kakaoAddr || kakaoAddr.address === '') return;
try {
const result = await searchAddress(address);
if (result && result.length > 0) {
const { x, y } = result[0];
const currentPos = new window.kakao.maps.LatLng(y, x);
map.panTo(currentPos);
marker.setMap(null);
marker.setPosition(currentPos);
marker.setMap(map);
}
} catch (error) {
console.error('Error occurred during address search:', error);
}
};
asyncFn();
}, [kakaoAddr]);
return (
<div>
<div id="map" style={{ width: '500px', height: '400px' }}></div>
</div>
);
};
export default KakaoMap;
function searchAddress(address: string): Promise<gcAdrSrchResult[]> {
return new Promise((resolve, reject) => {
const geocoder = new window.kakao.maps.services.Geocoder();
geocoder.addressSearch(address, (result: gcAdrSrchResult[], status: string) => {
if (status === window.kakao.maps.services.Status.OK && result?.length > 0) {
resolve(result);
} else {
reject(new Error('Address search failed or no results found'));
}
});
});
}
interface MapOptions {
center: { latitude: number; longitude: number };
level: number;
mapTypeId?: number;
draggable?: boolean;
scrollwheel?: boolean;
disableDoubleClick?: boolean;
disableDoubleClickZoom?: boolean;
projectionId?: string;
tileAnimation?: boolean;
keyboardShortcuts?: boolean | object;
speed?: number;
}
interface gcAdrSrchResult {
address: {
address_name: string;
b_code: string;
h_code: string;
main_address_no: string;
mountain_yn: string;
region_1depth_name: string;
region_2depth_name: string;
region_3depth_h_name: string;
region_3depth_name: string;
sub_address_no: string;
x: string;
y: string;
};
address_name: string;
address_type: string;
road_address: {
address_name: string;
building_name: string;
main_building_no: string;
region_1depth_name: string;
region_2depth_name: string;
region_3depth_name: string;
road_name: string;
sub_building_no: string;
underground_yn: string;
x: string;
y: string;
zone_no: string;
};
x: string;
y: string;
}
리액트 다음지도 API
DaumAddrInput.tsx
/**
Comment by CodeMaster KimC
For more information, visit: https://codemasterkimc.tistory.com
*/
import { FC } from 'react';
interface IProps {
kakaoAddr: IAddr;
setKakaoAddr: React.Dispatch<React.SetStateAction<IAddr>>;
}
const DaumAddrInput: FC<IProps> = ({ kakaoAddr, setKakaoAddr }) => {
const onClickAddr = () => {
new window.daum.Postcode({
oncomplete: function (data: IAddr) {
setKakaoAddr(data);
console.log(data);
document.getElementById('addrDetail')?.focus();
},
}).open();
};
if (kakaoAddr.address) {
return (
<div className="text-white bg-blue-400" onClick={onClickAddr}>
{kakaoAddr.address}
</div>
);
}
return (
<button type="button" className="w-16 p-2 text-white bg-slate-300" onClick={onClickAddr}>
주소 찾기
</button>
);
};
export default DaumAddrInput;
export interface IAddr {
address: string;
addressEnglish: string;
addressType: string;
apartment: string;
autoJibunAddress: string;
autoJibunAddressEnglish: string;
autoRoadAddress: string;
autoRoadAddressEnglish: string;
bcode: string;
bname: string;
bname1: string;
bname1English: string;
bname2: string;
bname2English: string;
bnameEnglish: string;
buildingCode: string;
buildingName: string;
hname: string;
jibunAddress: string;
jibunAddressEnglish: string;
noSelected: string;
postcode: string;
postcode1: string;
postcode2: string;
postcodeSeq: string;
query: string;
roadAddress: string;
roadAddressEnglish: string;
roadname: string;
roadnameCode: string;
roadnameEnglish: string;
sido: string;
sidoEnglish: string;
sigungu: string;
sigunguCode: string;
sigunguEnglish: string;
userLanguageType: string;
userSelectedType: string;
zonecode: string;
}
declare global {
export interface Window {
daum: any;
}
}
export const initialAddressInfo: IAddr = {
address: '',
addressEnglish: '',
addressType: '',
apartment: '',
autoJibunAddress: '',
autoJibunAddressEnglish: '',
autoRoadAddress: '',
autoRoadAddressEnglish: '',
bcode: '',
bname: '',
bname1: '',
bname1English: '',
bname2: '',
bname2English: '',
bnameEnglish: '',
buildingCode: '',
buildingName: '',
hname: '',
jibunAddress: '',
jibunAddressEnglish: '',
noSelected: '',
postcode: '',
postcode1: '',
postcode2: '',
postcodeSeq: '',
query: '',
roadAddress: '',
roadAddressEnglish: '',
roadname: '',
roadnameCode: '',
roadnameEnglish: '',
sido: '',
sidoEnglish: '',
sigungu: '',
sigunguCode: '',
sigunguEnglish: '',
userLanguageType: '',
userSelectedType: '',
zonecode: '',
};
참조
https://apis.map.kakao.com/web
https://codemasterkimc.tistory.com/50
300년차 개발자의 좋은 코드 5계명 (Clean Code)
이번 글을 통해 배워갈 내용 좋은 코드(Clean Code)를 작성하기 위해 개발자로서 생각해볼 5가지 요소를 알아보겠습니다. 개요 좋은 코드란 무엇일까요? 저는 자원이 한정적인 컴퓨터 세상에서 좋
codemasterkimc.tistory.com
'Javascript > React' 카테고리의 다른 글
| react-alert 대신 react-toastify 사용해서 알림 표시해보기 (0) | 2023.10.05 |
|---|---|
| React에 Redux Toolkit 사용해보기 Typescript Vite (0) | 2023.10.05 |
| React에 카카오 지도 넣는 방법 (초간단) (Client Side Render) (0) | 2023.06.18 |
| React로 이미지 업로드 및 필터 적용하고 출력해보기 (1) | 2022.11.19 |
| TypeScript와 함께 useReducer를 사용하는 방법 (0) | 2022.07.16 |