서론
기술 스택
프런트엔드 초기 설정
카카오맵 API 연동
메모
이번 글에서는 프로젝트의 프런트엔드에 필요한 초기 설정을 진행하고, 카카오맵 API를 연동해보겠습니다.
사용자가 병원의 위치를 지도에서 확인할 수 있도록 React.js로 프런트엔드를 구성하고, 카카오맵 API를 연동할 예정입니다. 네이버맵 API와 카카오맵 API 중 고민한 결과, 지원하는 기능은 거의 비슷하지만 클라우드 없이 단독으로 사용할 수 있고 장소 검색 기능을 제공하는 카카오맵 API를 사용했습니다. 또한, 일부 기능을 서버 사이드 렌더링하기 위해 Next.js 프레임워크의 사용을 고려하고 있습니다.
Django와 DRF를 사용해 REST API를 개발하고, AWS의 EC2로 배포할 예정입니다. 또한, Production DB로 AWS의 RDS(MySQL)를, Data Lake와 Data Warehouse로 각각 S3, Redshift를 활용합니다.
poetry: 라이브러리 의존성 관리
django-filter: 사용자가 특정 조건으로 병원을 검색(필터링)할 수 있는 기능 구현
django-extensions: runserver_plus, shell_plus 등의 기능 사용
django-environ: DB 연결 관련 민감한 정보 환경변수 처리
drf-spectacular: DRF로 개발한 REST API 자동 문서화
mysqlclient: MySQL(RDS) 연결
아래 사진과 같이 프런트엔드와 백엔드를 나눠서 구현하기 위해 frontend와 backend 폴더를 생성했습니다.
cd frontend
명령어를 사용해 frontend 폴더로 이동하고, npx create-react-app .
명령어를 사용해 현재 위치에서 react app을 생성하면 아래 사진과 같이 자동으로 디렉토리를 구성하고 각종 파일들을 생성하는데, 해당 파일들은 당장 필요하지 않더라도 만약을 위해서 남겨두었습니다.
백엔드 라이브러리는 backend 폴더 내에서, 프런트엔드 라이브러리는 frontend 라이브러리에서 각각 관리하기 위해 package.json과 package-lock.json 파일을 프로젝트의 루트 디렉토리가 아닌 frontend 폴더 내에 배치했습니다. 반면, create-react-app
명령어 실행 시 자동으로 생성되는 .gitignore 파일은 관리의 편의성을 위해 루트 디렉토리에 배치했습니다.
다음으로 프런트엔드에 카카오맵 API를 연동해보겠습니다. 우선, 아래 사진과 같이 Kakao Developers 페이지에 로그인한 뒤 애플리케이션을 등록해야 합니다.
등록을 완료했으면 아래 사진과 같이 애플리케이션을 클릭해 상세 정보 페이지로 이동할 수 있고, 해당 페이지에서 애플리케이션에서 사용할 키를 확인할 수 있습니다.
이제 앱 설정 > 플랫폼으로 이동해서 플랫폼 정보를 입력해줘야 합니다. 저희 팀의 경우 웹서비스를 제공할 것이고, 일단 배포 전 로컬 환경에서 개발하고 테스트하기 위해 localhost:3000을 도메인으로 등록했습니다.
위의 과정을 통해 애플리케이션 등록과 설정을 완료했으니, 이제 코드에서 카카오맵 API를 호출하고 사용해보겠습니다. 우선, 아래 사진과 같이 src/components 안에 MapComponent.js 파일을 생성한 뒤 다음의 코드를 작성합니다.
import React, { useEffect } from 'react';
// const { kakao } = window;
const MapComponent = () => {
useEffect(() => {
// 카카오맵 API 연동
const script = document.createElement('script');
script.async = true;
script.src = `https://dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.REACT_APP_KAKAO_MAP_API_KEY}&autoload=false&libraries=services,clusterer,drawing`;
document.head.appendChild(script);
script.onload = () => {
window.kakao.maps.load(() => {
const container = document.getElementById('kakao-map');
// 중심좌표(위도, 경도), 확대 정도 설정
const options = {
center: new window.kakao.maps.LatLng(37.5665, 126.9780),
level: 3,
};
const map = new window.kakao.maps.Map(container, options);
// 지도 타입 컨트롤, 줌 컨트롤 추가
const mapTypeControl = new window.kakao.maps.MapTypeControl();
const zoomControl = new window.kakao.maps.ZoomControl();
map.addControl(mapTypeControl, window.kakao.maps.ControlPosition.TOPRIGHT);
map.addControl(zoomControl, window.kakao.maps.ControlPosition.RIGHT);
});
};
}, []);
return <div id="kakao-map" style={{ width: '100%', height: '400px' }} />;
};
export default MapComponent;
import React, { useEffect } from 'react';
// const { kakao } = window;
const MapComponent = () => {
useEffect(() => {
// 카카오맵 API 연동
const script = document.createElement('script');
script.async = true;
script.src = `https://dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.REACT_APP_KAKAO_MAP_API_KEY}&autoload=false&libraries=services,clusterer,drawing`;
document.head.appendChild(script);
위의 코드는 React에서 카카오맵 API를 불러오고, 연결하는 코드입니다. script.src를 보면, API 키가 일반적인 문자열의 형태가 아닌 것을 확인할 수 있습니다. Github에 코드를 업로드할 때 API Key 등의 중요 정보가 노출되는 것을 방지하기 위해 아래 사진과 같이 .env 파일에 환경 변수를 정의한 뒤, 템플릿 문법을 사용해 불러온 것입니다. 이때 주의할 점은, React에서 사용되는 환경변수는 REACT_APP으로 시작해야 하며, 변수명=값
형태 즉, 공백 없이 입력해야 합니다.
script.onload = () => {
window.kakao.maps.load(() => {
const container = document.getElementById('kakao-map');
// 중심좌표(위도, 경도), 확대 정도 설정
const options = {
center: new window.kakao.maps.LatLng(37.5665, 126.9780),
level: 3,
};
const map = new window.kakao.maps.Map(container, options);
// 지도 타입 컨트롤, 줌 컨트롤 추가
const mapTypeControl = new window.kakao.maps.MapTypeControl();
const zoomControl = new window.kakao.maps.ZoomControl();
map.addControl(mapTypeControl, window.kakao.maps.ControlPosition.TOPRIGHT);
map.addControl(zoomControl, window.kakao.maps.ControlPosition.RIGHT);
});
};
}, []);
return <div id="kakao-map" style={{ width: '100%', height: '400px' }} />;
};
export default MapComponent;
해당 코드는 카카오맵을 불러올 container를 정의해 옵션을 설정하고, 지도 타입 컨트롤과 줌 컨트롤을 추가한 MapComponent를 외부로 반환하는 코드입니다. 공식 문서에서는 kakao.maps와 같이 window라는 키워드를 붙이지 않고 사용하는데, 이 경우 Cannot read properties of undefined (reading 'maps’) 에러가 발생합니다.
이는 스크립트로 카카오맵 API를 가져오면 이는 window 전역 객체로 들어가는데, 함수형 컴포넌트에서 이를 바로 인식할 수 없기 때문에 발생한 문제입니다. const {kakao} = window;
라는 코드를 상단에 추가하면 해결이 가능하지만, 서버를 새로 시작할 때마다 주석 처리했다가 다시 풀어줘야 적용이 되는 점이 불편해서 kakao.maps 대산 window.kakao.maps와 같이 매번 window 키워드를 붙여서 사용했습니다.
npm start
명령어로 React 서버를 실행하면, 아래 사진과 같이 카카오맵 API가 연동되어 지도 타입 컨트롤, 줌 컨트롤이 추가된 지도를 잘 출력하는 것을 확인할 수 있습니다.
코드 작성 시 가독성뿐만 아니라 의도하지 않은 동작을 방지하기 위해 들여쓰기 신경쓸 것
템플릿 문법 사용 시 ''(따옴표)가 아닌 ``(백틱)으로 감싸야하는 것 주의