안녕하세요, 웹 프론트엔드 개발자 가든입니다 ;)
해커톤에 참가하면서 프로젝트를 개발하고 있는데 병원 조회 기능을 개발하면서 네이버 지도를 사용할 일이 생겼습니다.
이번 포스팅에서는 네이버 지도 Api를 직접 사용해 Next.js에 지도를 불러오고 기본으로 제공하는 마커 찍기 기능까지 구현해보려고 합니다. 언어는 타입스크립트 사용하면서 구현중입니다 !Next.js에 구현하는 레퍼런스가 많이 없길래 자세히 구현하는 과정을 기록해보았습니다
아직 디자인이 다 나오지 않아서 마커를 커스텀하고, 해당 정보에 대한 세부 정보를 조회할 수 있는 기능은 다음 포스팅에서 만나도록 하겠습니다!
먼저 네이버 클라우드에 가입하고 Application Services
페이지에 접속합니다.
위의 이용 신청하기 버튼을 누르면 나의 애플리케이션을 등록하면 됩니다.
저는 아래와 같이 제 웹사이트를 등록했습니다.
이때 서비스 URL은 제 로컬 서버랑 제 서비스 배포 서버 url을 넣어줬습니다.
사용할 지도 API 목록에서 선택해서 등록하면 아래와 같이 제 웹 서비스가 잘 등록 된 것을 확인할 수 있습니다. (벌써 65회나 썻네요 ㄹㅇㅋㅋ...)
이제 프로젝트에 네이버 맵 타입 관련 패키지를 설치해주어야합니다.
자신의 프로젝트에서 아래의 명령어를 사용해주세요
npm add -D @types/navermaps
그리고 프로젝트에 전역으로 네이버맵을 사용할 수 있도록 설정해야합니다.
_app.tsx
파일에 아래와 같이 전역으로 사용이 가능하도록 발급받은 키를 적용해주세요
mport type { AppProps } from 'next/app';
import Script from 'next/script';
import '../app/globals.css';
import Layout from '../app/layout';
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Script
strategy="afterInteractive" //"beforeInteractive"으로 찾았는데 경고메세지 떠가지고 after로 수정해줬습니다.
src={`https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=${process.env.NEXT_PUBLIC_MAP_KEY}`}
></Script>
<Layout>
<Component {...pageProps} />
</Layout>
</>
);
}
위와 같이 했는데 Next 버전(전 14로 구현중입니다) 별로 서버를 사용하는게 달라서 에러 메세지나 나면서 실패했다? 이를 해결하기 위해 _document.tsx
가 없다면 생성해줍니다. _document.tsx
파일에 아래와 같이 코드를 작성해주세요.
import Document, { Html, Head, Main, NextScript, DocumentContext } from 'next/document';
import { extractCritical } from '@emotion/server';
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx);
const styles = extractCritical(initialProps.html);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
<style data-emotion-css={styles.ids.join(' ')} dangerouslySetInnerHTML={{ __html: styles.css }} />
</>
),
};
}
render() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
이제 본격적으로 화면에 맵을 띄워보겠습니다. 구현하려는 페이지에 다음과 같이 작성해주세요
import React, { useEffect } from 'react';
import styled from '@emotion/styled';
const Main = styled.div`
@@ -7,18 +8,33 @@ const Main = styled.div`
align-items: center;
padding: 6rem;
min-height: 100vh;
`;
export default function Map() {
useEffect(() => {
const initMap = () => {
const mapOptions = {
center: new naver.maps.LatLng(37.3595704, 127.105399),
zoom: 10,
};
new naver.maps.Map('map', mapOptions);
};
if (window.naver && window.naver.maps) {
initMap();
} else {
const mapScript = document.createElement('script');
mapScript.onload = () => initMap();
mapScript.src = `https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=발급받은 클라이언트 아이디`;
document.head.appendChild(mapScript);
}
}, []);
return (
<Main>
<div id="map" style={{ width: '100%', height: '500px' }}></div>
</Main>
);
}
결과는 두근두근,,,
잘 불러와진 것을 확인할 수 있습니다 굿굿
이제 제가 원하는 장소들에 대해서 마커를 찍어보려고 합니다.
장소를 띄우기 위해서는 위도, 경도
값을 각 장소에 받아와야합니다 이건 서버 분들이 데이터로 넘겨주실테지만 저희는 우선 띄워봐야하기 때문에 예시 데이터로 해보겠습니다.
병원 데이터.json
{
"name": "김종화푸른소아과의원",
"address": "경기도 용인시 수지구 문정로 46",
"lat": 37.324467,
"lng": 127.094711
},
{
"name": "김진영내과의원",
"address": "경기도 용인시 수지구 신봉2로 3",
"lat": 37.323318,
"lng": 127.077351
},
...생략
위의 데이터가 준비 되셨다면 바로 적용해서 마커를 아래와 같이 찍어보겠습니다.
useEffect(() => {
const loadMap = () => {
const mapOptions = {
center: new naver.maps.LatLng(37.3595704, 127.105399),
zoom: 10,
};
const map = new naver.maps.Map('map', mapOptions);
hospitals.forEach(hospital => {
new naver.maps.Marker({
position: new naver.maps.LatLng(hospital.lat, hospital.lng),
map: map,
title: hospital.name,
});
});
setIsMapLoaded(true);
};
캬 다음과 같이 제가 지정한 위치들에 마커가 잘 찍힌 것을 확인할 수 있습니다.
제가 지도를 구경하다가 제 주변의 병원을 조회하는 기능이 추가 되었으면 좋겠다고 생각해 제 현재 위치 재조회 기능을 추가 해봤습니다.
// 사용자의 현재 위치 표시히는 기능입니다!
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
const currentLocation = new naver.maps.LatLng(position.coords.latitude, position.coords.longitude);
new naver.maps.Marker({
position: currentLocation,
map: map,
title: "Your Location",
});
// 지도 첫 접속 시 사용자의 현 위치로 중심이 오도록 추가했습니다!
map.setCenter(currentLocation);
});
}
다음은 버튼을 추가해서 다른데 구경하다가 내 위치로 돌아오도록 구현했습니다.
const handleCurrentLocationClick = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
const currentLocation = new naver.maps.LatLng(
position.coords.latitude,
position.coords.longitude
);
mapRef.current.setCenter(currentLocation);
});
}
};
완성된 화면은 다음과 같습니다 ;) 마커는 경기도 쪽에있지만 현재 위치 재조회 버튼을 누르면 제가 있는 성수쪽으로 이동하는 것을 확인 할 수 있습니다!
이상 포스팅을 바치겠습니다 다음에는 마커를 커스텀하고 해당 장소에 추가적인 기능을 구현하는 개발 일지로 돌아오겠습니다 :)