Flutter: 네이버 지도

미디움에서 처음으로 플러터로 네이버 지도 써본 경험을 공유하기 위해 한국말로 포스트를 진행해봅니다. 코드는 iOS꺼는 따로 안만들겠습니다.

Getting Started

Naver Cloud Platform

우선 Naver Cloud Platform 콘솔에서 애플리케이션을 등록합니다. Android 앱 패키지 이름은 AndroidManifest.xml에서 맨 위 package에서 확인할 수 있으며, iOS Bundle ID는 project/ios/Runner.xcodeproj/project.pbxproj 밑 쪽 PRODUCT_BUNDLE_IDENTIFIER에서 확인 할 수 잇습니다.

Flutter

플러터로 시작하기 위한 준비를 하고…(naver map flutter pub.dev)

$ flutter pub add naver_map_pluginimport 'package:naver_map_plugin/naver_map_plugin.dart';

근데…null sound safety를 지원하지 않는다고 해서 flutter run — no-sound-null-safety으로 실행을 해야되네요. 그리고 에뮬레이터 보다는 실제 기기로 하는걸 추천합니다. 에뮬레이터는 너무 느리네요.

Android

AndroidManifest.xml에 meta-data 지정한다. Client_ID는 naver cloud console에서 인증정보에서 볼 수 있습니다.

<manifest>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application>
<meta-data
android:name="com.naver.maps.map.CLIENT_ID"
android:value="YOUR_CLIENT_ID_HERE" />
</application>
</manifest>
AndroidManifest.xml

iOS

Geolocator & LocationClass

저는 현재 위치를 첫 위치로 설정하고 싶어서 (네이버 지도는 설정 없이 열면 광화문으로 나오네요) geolocator package를 썼습니다. Geolocator에서는 Position을 사용하고, 네이버 지도에서는 LatLng 클래스를 사용해서 불편하니 custom class인 Location Class을 네이버의 LatLng extend해서 더 편리하게 개발하도록 하겠습니다.

Starting the App

  1. 앱을 켰을때 배경에서는 네이버 지도가 처음 설정한 initLocation으로 그려집니다.
  2. 그 사이 provider에서 geolocator을 사용하여 위치 정보를 허용했으면 프로바이더에 있는 상태가 변경되며 네이버 지도 위치가 현재 위치로 그려지고, 아니면 그대로 있습니다. (map_provider의 setCurrentLocation 메소드)

여기까지는 네이버 지도가 크게 어려운 건 없습니다.

위에있는 비디오는 첫 앱을 실행했을 경우 (아직 위치 정보 허용 전), 아래있는 비디오는 허용을 하고서 다시 앱을 켰을 경우입니다.

Custom Classes

제가 좋아하는 홍대 근처 카페와 음식점을 공유하려고 합니다. 조금 복잡하게 생각했는데요, 실제 서버랑 통신해서 한다고 생각하고 해서 그럽니다. 저는 class를 사랑하는 사람, 역시 또 custom class를 몇개 만들었습니다. 클래스에 대해서 추가 설명은 안하겠습니다. 꼭 implements, extends, super constructor 등 공부해서 클래스를 마음껏 사용하시길 바랍니다.

Store-Related Classes

일단은 서버에서 받는 각 카페와 음식점 정보를 Store이라는 상위 클래스로 받으려고 합니다. 하위 클래스로 Restaurant과 Cafe가 있습니다.

Custom Marker

네이버 지도에 원하는 위치들을 표현 하려면 네이버의 Marker클래스를 써야됩니다. 일일이 하기 귀찮으니 편리성을 위해 Marker를 extend해서 새로운 클래스를 만들었습니다. OverlayImage와 marker를 눌렀을 경우의 콜백 (onMarkerTab)은 view에서 할당할 것입니다.

Mark the Map

OverlayImage & initState

네이버의 Marker class에서 마커 아이콘은 OverlayImage인데 기본 constructor가 없고 Future<OverlayImage>를 반환하는 OverlayImage.fromAssetImage밖에 없습니다. 게다가 이 named constructor은 BuildContext를 매개변수로 받습니다 (구글맵도 그렇더라고요). 그래서 이미 생성해 놓은 저의 custom marker class들을 init state에서 위에 보이는 createImage 메소드를 실행해줍니다. 중요한건 WidgetsBinding.instance.addPostFrameCallback 안에서 해야되고, if (!this.mounted) return; 다음에 해야됩니다.

간단하게 설명하쟈면, stateful widget을 만들때 “frame rendering”하는걸 시작하고 element를 만들기 시작합니다. 이때 BuildContext가 만들어지고 순서대로 init → didChangeDependencies →build가 실행됩니다. 그러면 WidgetsBinding.instance.addPostFrameCallback 안에 있는 함수는 frame rendering이 시작되고서 실행되고, 이 stateful widget이 “mount”가 되는 순간 , BuildContext를 받아서 쓸 수 있습니다. 그래서 아래와 같이 initState를 만들었습니다. createImage 메소드로 마커 아이콘을 만들어 주고, setOnMarkerTab 메소드로 마커를 눌렀을 시 실행되는 콜백을 보냅니다.

NaverMapController

마커를 눌렀을때 화면 가운대 지도가 마커 위치로 움직이기 위해 naver.NaverMapController을 미리 nullabe하게 만들어놓고 아래 코드처럼 onMapCreate에서 할당합니다. 그리고 위 initState에서 moveCamera 메소드를 사용해 움직이게 합니다.

BottomSheet

BottomSheet올릴때 좀 더 이쁘게 animation도 하고싶었지만 간단한 예제를 만드는 것이기에…마커를 눌렀을 때 프로바이더에 있는 콜백은 아래와 같습니다.

BottomSheet가 올라오면서 해당 가계에 대한 정보가 공유됩니다! 아래 동영상으로 어떻게 작동되는지 궁금하면 확인하세요 :)

--

--

Flutter & Node.js Full-Stack Developer

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store