Important
2.4.x
버전부터 AI NAVER API에서 제공되던 지도 API가 아닌 새롭게 출시된 Maps 단독 상품이 지원됩니다.
기본적으로 앱에서 권한은 직접 관리가 되어야 합니다.
이를 관리하기 위해 react-native-permissions라이브러리를 사용하는 예시를 알아보겠습니다.
Tip
Expo 사용자라면 expo-location를 참고해서 권한을 사용할 예정이다 라고 명시할 수 있습니다. 따라서 아래 내용들 중 대부분은 필요하지 않고, 필요한 권한이 무엇인지, 어떻게 명시해야 하는지를 살펴보신 다음 expo-location에서의 사용법을 따르셔야 합니다.
우선 패키지를 설치하고 설정합니다.
pnpm add react-native-permissions
react-native-permission
의 각 플랫폼별 설정 방법은 사용법을 직접 참고해
Podfile(iOS)
, AndroidManifest.xml(Android)
를 적절히 변경해주시길 바랍니다.
iOS는 다음과 같은 세 가지의 권한이 연관되어있습니다.
NSLocationAlwaysAndWhenInUseUsageDescription(>= iOS 11)
- 앱이 foreground와 background 모두에서 위치 정보에 액세스하는 것을 허용합니다.
- iOS 11 이상에서는 NSLocationAlwaysUsageDescription 대신 이 키를 사용해야 합니다.
NSLocationWhenInUseUsageDescription
- 앱이 foreground에 있을 때 (즉, 사용자가 actively하게 앱을 사용 중일 때) 위치 정보에 액세스하는 것을 허용합니다.
NSLocationTemporaryUsageDescriptionDictionary(>= iOS 14)
- 앱이 임시로 정확한 위치 정보에 액세스할 수 있도록 허용합니다. 이는 앱이 특정 작업을 수행하는 동안에만 정확한 위치가 필요한 경우 사용됩니다.
Tip
앱이 iOS 11미만의 기기를 지원하고 있지 않다면 NSLocationAlwaysUsageDescription
을 기재하지 않아도 됩니다.
만약 지원한다면 같이 설정해주셔야 합니다.
그럼 Podfile
에서 다음과 같은 세 가지의 권한을 허용해줍니다.
setup_permissions([
'LocationAccuracy',
'LocationAlways',
'LocationWhenInUse',
...
])
Xcode에서 앱 타겟의 Signing & Capabilities
탭에서 Background Modes
를 활성화하고 Location updates
옵션을 선택합니다.
이는 백그라운드에서 위치를 받아오기 위해 필요하므로 필요없다면 설정하지 않아도 됩니다.
Naver Map SDK에서 내부적으로 이용하는 FusedLocationSource
는 사용자가 isShowLocationButton prop을
true
로 설정하는 순간 자동으로 권한 요청을 시행합니다.
Android는 비교적 간단하게 권한을 구현할 수 있습니다.
아래 권한들만 AndroidManifest.xml
에 사용한다고 명시하면 됩니다.
android.permission.ACCESS_FINE_LOCATION
- 정확한 위치 정보 권한
android.permission.ACCESS_COARSE_LOCATION
- 대략적인 위치 정보 권한
android.permission.ACCESS_BACKGROUND_LOCATION
- 백그라운드 상태에서 위치 정보 권한
여기까지의 설정이 끝났다면 지도가 필요한 화면에서 다음과 같이 코드로 권한을 요청할 수 있습니다.
For Bare RN Project or ejected Expo (react-native-permissions
)
// useEffect는 단순히 컴포넌트가 mount될 때 호출해주기 위해서 사용되었습니다.
useEffect(() => {
if (Platform.OS === 'ios') {
request(PERMISSIONS.IOS.LOCATION_ALWAYS).then((status) => {
console.log(`Location request status: ${status}`);
if (status === 'granted') {
requestLocationAccuracy({
purposeKey: 'common-purpose', // replace your purposeKey of Info.plist
})
.then((accuracy) => {
console.log(`Location accuracy is: ${accuracy}`);
})
.catch((e) => {
console.error(`Location accuracy request has been failed: ${e}`);
});
}
});
}
if (Platform.OS === 'android') {
requestMultiple([
PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
PERMISSIONS.ANDROID.ACCESS_BACKGROUND_LOCATION,
])
.then((status) => {
console.log(`Location request status: ${status}`);
})
.catch((e) => {
console.error(`Location request has been failed: ${e}`);
});
}
}, []);
For Expo (expo-location
)
import * as Location from 'expo-location'
...
useEffect(() => {
(async () => {
try {
const {granted} = await Location.requestForegroundPermissionsAsync();
/**
* Note: Foreground permissions should be granted before asking for the background permissions
* (your app can't obtain background permission without foreground permission).
*/
if(granted) {
await Location.requestBackgroundPermissionsAsync();
}
} catch(e) {
console.error(`Location request has been failed: ${e}`);
}
})();
}, []);
Note
대부분의 Type들과 Prop들의 설명은 코드의 주석에도 적혀있고 이 프로젝트는 TypeScript를 지원하니 코드에서만 확인해도 사용에 무리가 없을 것입니다.
- ✅ Fully Supported
⚠️ Developing, lack of features yet- 📦 Planned
Component | iOS | Android | Description |
---|---|---|---|
NaverMapView | ✅ | ✅ | 지도 |
NaverMapMarkerOverlay | ✅ | ✅ | 마커 오버레이 |
Info Window | 📦 | 📦 | 오버레이의 콜오버, 툴팁 |
NaverMapCircleOverlay | ✅ | ✅ | 원 오버레이 |
NaverMapPolylineOverlay | ✅ | ✅ | 폴리라인 오버레이 |
NaverMapPolygonOverlay | ✅ | ✅ | 폴리곤 |
NaverMapGroundOverlay | ✅ | ✅ | 지상 오버레이 |
NaverMapPathOverlay | ✅ | ✅ | 경로 오버레이 |
NaverMapMultipartPathOverlay | 📦 | 📦 | 여러개의 경로 오버레이 |
NaverMapArrowPathOverlay | ✅ | ✅ | 화살표 경로 오버레이 |
마커의 종류는 총 5가지입니다.
Important
[iOS, Android] x [new arch, old arch] x [debug, release]
총 8가지 조건에서 모두 정상적으로 렌더링 되는 것을 테스트했습니다.
Tip
reuseIdentifier
는 전달하지 않아도 모두 자동으로 캐싱이 됩니다.
되도록이면 마커는 모두 width
, height
prop을 사용해야합니다. 2번 타입의 경우 현재 debug/release 빌드의 크기가 width
, height
없이 다르게 나오는 현상이 있습니다.
release에서는 제대로 나옵니다.
- Naver Map Basic Symbol (green, red, gray, ...) (caching ✅)
image={{symbol: 'green'}}
- Local Resource (
require
react native image file) (caching ✅)
image={require('./marker.png')}
- Local Native Resource
image={{assetName: 'asset_image'}}
- iOS: main bundle의 image asset 이름
- Android: resources의 drawable 이름
- Network Image (caching ✅)
image={{httpUri: 'https://example.com/image.png'}}
Warning
현재 header같은 속성은 지원되지 않습니다.
- Custom React View (caching ❌)
iOS(new arch)에선 현재 View들에 collapsable=false
를 설정해야 동작합니다.
Tip
마커의 생김새를 바꿔야 한다면 그것에 대한 의존성들을 제일 상위 자식의 key
로 전달해야합니다.
<NaverMapMarkerOverlay width={width} height={height} ...>
<View key={`${text}/${width}/${height}`} collapsable={false} style={{width, height}}>
<Text>{text}</Text>
</View>
</NaverMapMarkerOverlay>
Important
이 타입은 많이 생성될 시 성능에 굉장히 영향을 미칠 수 있습니다. 아직은 단순하게만 사용하시거나 되도록이면 이미지를 사용하는 것을 추천드립니다.
현재 이 타입은 Android에선 react-native-map
의 구현체를 비슷하게 가져와 React Native의 Shadow Node를 조금 커스텀해서 자식의 위치를
추적한다음 실제 Android의 View
를 삽입해줍니다.
iOS에선 단순히 UIView
를 UIImage
로 캔버스에 그려 표시해줍니다.
두 방법 모두가 이미지 캐싱이 아직 지원되지 않고(추후에 reuseableIdentifier
같은 속성으로 지원이 가능할 것으로 보입니다), 마커 하나당 많은 리소스를 차지하게 됩니다.
- ✅ Done
- 📦 Planned
- ❓ Maybe Planned
- ❌ Not Planned
Prop | iOS | Android |
---|---|---|
isLogoInteractionEnabled | ❌ | ❌ |
gestureFrictions | 📦 | 📦 |
Event | iOS | Android |
---|---|---|
onTapSymbol | 📦 | 📦 |
onAuthFailed | ❌ | ❌ |
onLocationChange | 📦 | 📦 |
iOS | Android | |
---|---|---|
onLongTap | ❌ | 📦 |
Prop | iOS | Android |
---|---|---|
caption-fontFamily | ❓ | ❓ |
subcaption-fontFamily | ❓ | ❓ |
- Project Started (23.04.01)
- Project Setup & Component Structure (23.04.03)
- General Props & Commands (23.04.05)
- Camera, Region, Commands, Events (23.04.07)
- Implement Basic Overlays (23.04.10)
- Location Service (23.04.10)
- Support Paper(Old Arch) (23.04.11)
- Release (23.04.11)
- Support Expo with config plugin (23.04.12)
- Docs
- Implement Clustering (23.04.24)
- Implement ArrowheadPath Overlay (23.05.01)
- Implement Ground Overlay (23.05.01)
- Implement MutlPath Overlay (25.08.25)
- Implement Location Overlay Commands <- 🔥
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT