Support Table
React Native Naver Map | React Native | Note |
---|---|---|
≥2.1.0 |
≥ 0.74 |
Drop Bridge Support & 0.74 required |
≥2.x |
New Architecture Only | Drop Old Architecture Support, You should turn off bridgeless if want to render http web image marker |
<2.x |
Old Architecture + New Architecture |
[!IMPORTANT]
2.x
λ²μ λΆν΄ New Architectureμμλ§ λμν©λλ€. Fabricμ νμ±ννμ§ μμ νλ‘μ νΈμμλ1.x
λ²μ μ μ¬μ©νμλ©΄ λ©λλ€. μμν κΈ°λ₯ λ§κ³ μ°¨μ΄λλ λΆλΆμ μκ³1.x
λ²μ μμλ μΆ©λΆν νμν κΈ°λ₯λ€λ‘ μ§λμ±μ ꡬμΆν μ μμ΅λλ€.
κ±°μ λͺ¨λ νμ μ΄ μ€λͺ λμ΄ μλ API Docsλ₯Ό ꡬμ±νμ΅λλ€.
μ΅λν κ°λ
μ±μ μ΄λ ΈμΌλ©° component
μͺ½μμ μνλ μ»΄ν¬λνΈμ νμ
κ³Ό Prop
λ° Ref
λ‘ μ¬μ©λ²μ νμΈ κ°λ₯ν©λλ€.
expo config pluginμ μ¬μ©ν΄ Expoνκ²½μμλ μμ½κ² μν€ν μ³μ μκ΄μμ΄ λΉλν μ μμ΅λλ€.
Expo Go, Snackμμ μ¬μ©νμ§ λͺ»νμ§λ§ development build, production νκ²½μμ μμ½κ² μ¬μ©ν μ μμ΅λλ€.
[!IMPORTANT]
[iOS, Android] x [new arch, old arch] x [debug, release]
μ΄ 8κ°μ§ 쑰건μμ λͺ¨λ μ μμ μΌλ‘ λ λλ§ λλ κ²μ ν μ€νΈνμ΅λλ€.
symbol
)children
μΌλ‘ μ λ¬νλ React Native Custom Viewμ΅μ λ²μ μ SDKλ₯Ό μ§μνλ©° Propsμ Commandλ€λ‘ Naver Mapμ μ΅μ κΈ°λ₯μ μ‘°μν μ μμ΅λλ€.
# npm
npm install --save @mj-studio/react-native-naver-map
# yarn
yarn add @mj-studio/react-native-naver-map
# expo
npx expo install @mj-studio/react-native-naver-map
For ios, you should install pods
λ μμΈν μ€μ μ 곡μ λ¬Έμλ₯Ό μ°Έκ³ ν΄μ£ΌμΈμ.
Import Naver SDK Maven Repository to android/build.gradle
.
allprojects {
repositories {
maven {
url "https://repository.map.naver.com/archive/maven"
}
}
}
AndroidManifest.xml
<manifest>
<application>
<meta-data
android:name="com.naver.maps.map.CLIENT_ID"
android:value="YOUR_CLIENT_ID_HERE" />
</application>
</manifest>
AndroidManifest.xml
Currently, this package will request location permission for showing user's current location.
<manifest>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
# optional for background location
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>
μμΈν κΆνμ κ΄λ ¨λ λ΄μ©μ μλμ κΈ°μ¬λμ΄μμ΅λλ€.
λ μμΈν μ€μ μ 곡μ λ¬Έμλ₯Ό μ°Έκ³ ν΄μ£ΌμΈμ.
info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NMFClientId</key>
<string>YOUR_CLIENT_ID_HERE</string>
<dict>
<plist>
info.plist
Currently, this package will request location permission for showing user's current location.
<plist version="1.0">
<dict>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>{{usage description}}</string>
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>{{your purpose key}}</key>
<string>{{usage description}}</string>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>{{usage description}}</string>
</dict>
</plist>
μμΈν κΆνμ κ΄λ ¨λ λ΄μ©μ μλμ κΈ°μ¬λμ΄μμ΅λλ€.
expo-build-properties
packageThis is for inject naver maven repository.
npx expo install expo-build-properties
app.json
{
...
"plugins": [
[
"@mj-studio/react-native-naver-map",
{
"client_id": "{{Naver Map Client Key}}",
// (optional, you can set with expo-location instead of this package)
"android": {
"ACCESS_FINE_LOCATION": true,
"ACCESS_COARSE_LOCATION": true,
"ACCESS_BACKGROUND_LOCATION": true
},
// (optional, you can set with expo-location instead of this package)
"ios": {
"NSLocationAlwaysAndWhenInUseUsageDescription": "{{ your location usage description }}",
"NSLocationWhenInUseUsageDescription": "{{ your location usage description }}",
"NSLocationTemporaryUsageDescriptionDictionary": {
"purposeKey": "{{ your purpose key }}",
"usageDescription": "{{ your location usage description }}"
}
}
}
],
[
"expo-build-properties",
{
"android": {
"extraMavenRepos": ["https://repository.map.naver.com/archive/maven"]
}
}
],
...
]
}
Expoλ μμμ μ€λͺ λ Android, iOSμ μ€μ λ²μ΄ νμνμ§ μμ΅λλ€.
μμΈν κΆνμ κ΄λ ¨λ λ΄μ©μ μλμ κΈ°μ¬λμ΄μμ΅λλ€.
const jejuRegion: Region = {
latitude: 33.20530773,
longitude: 126.14656715029,
latitudeDelta: 0.38,
longitudeDelta: 0.8,
};
...
<NaverMapView
ref={ref}
style={{ flex: 1 }}
mapType={mapType}
layerGroups={{
BUILDING: true,
BICYCLE: false,
CADASTRAL: false,
MOUNTAIN: false,
TRAFFIC: false,
TRANSIT: false,
}}
initialRegion={jejuRegion}
isIndoorEnabled={indoor}
symbolScale={symbolScale}
lightness={lightness}
isNightModeEnabled={nightMode}
isShowCompass={compass}
isShowIndoorLevelPicker={indoorLevelPicker}
isShowScaleBar={scaleBar}
isShowZoomControls={zoomControls}
isShowLocationButton={myLocation}
isExtentBoundedInKorea
logoAlign={'TopRight'}
locale={'ja'}
onInitialized={() => console.log('initialized!')}
onOptionChanged={() => console.log('Option Changed!')}
onCameraChanged={(args) => console.log(`Camera Changed: ${formatJson(args)}`)}
onTapMap={(args) => console.log(`Map Tapped: ${formatJson(args)}`)}
>
<NaverMapMarkerOverlay
latitude={33.3565607356}
longitude={126.48599018}
onTap={() => console.log(1)}
anchor={{ x: 0.5, y: 1 }}
caption={{
key: '1',
text: 'hello',
}}
subCaption={{
key: '1234',
text: '123',
}}
width={100}
height={100}
/>
{/* Not Working in iOS Old Architecture Yet */}
<NaverMapMarkerOverlay*
latitude={33.4165607356}
longitude={126.48599018}
onTap={() => console.log(1)}
anchor={{ x: 0.5, y: 1 }}
caption={{
key: '1',
text: 'hello',
}}
subCaption={{
key: '1234',
text: '123',
}}
width={100}
height={100}
>
<View style={{ width: 100, height: 100, backgroundColor: 'red' }} />
</NaverMapMarkerOverlay>
<NaverMapMarkerOverlay
latitude={33.2565607356}
longitude={127.8599018}
onTap={() => console.log(1)}
anchor={{ x: 0.5, y: 1 }}
caption={{
key: '1',
text: 'hello',
}}
subCaption={{
key: '1234',
text: '123',
}}
width={100}
height={100}
image={{ uri: 'https://picsum.photos/100/100' }}
/>
<NaverMapCircleOverlay
latitude={33.17827398}
longitude={126.349895729}
radius={50000}
color={'#f2f1'}
outlineColor={'#aaa'}
outlineWidth={2}
onTap={() => console.log('hi')}
/>
<NaverMapPolygonOverlay
outlineWidth={5}
outlineColor={'#f2f2'}
color={'#0068'}
coords={[
{ latitude: 33.2249594, longitude: 126.54180047 },
{ latitude: 33.25683311547, longitude: 126.18193 },
{ latitude: 33.3332807, longitude: 126.838389399 },
]}
/>
<NaverMapPathOverlay
coords={[
{ latitude: 33.5249594, longitude: 126.24180047 },
{ latitude: 33.25683311547, longitude: 126.18193 },
{ latitude: 33.3332807, longitude: 126.838389399 },
]}
width={8}
color={'red'}
progress={-0.6}
passedColor={'green'}
/>
</NaverMapView>
λͺ¨λ μ½λμ JSDocμΌλ‘ μ£Όμμ΄ μ½μ λμ΄μμΌλ―λ‘ Documentationμμ΄λ κ°λ°μ μμν μ μμ΅λλ€.
νμ§λ§ μ νν μ΄λ€ νμ λ€μ΄ μκ³ μ΄λ€ μμ±μ μλ―Ένλμ§ μΉμ¬μ΄νΈμμ νμΈνμλ €λ©΄ Documentationλ₯Ό μ°Έκ³ ν΄μ£ΌμΈμ.
κΈ°λ³Έμ μΌλ‘ μ±μμ κΆνμ μ§μ κ΄λ¦¬κ° λμ΄μΌ ν©λλ€.
μ΄λ₯Ό κ΄λ¦¬νκΈ° μν΄ react-native-permissionsλΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νλ μμλ₯Ό μμλ³΄κ² μ΅λλ€.
[!TIP] Expo μ¬μ©μλΌλ©΄ expo-locationλ₯Ό μ°Έκ³ ν΄μ κΆνμ μ¬μ©ν μμ μ΄λ€ λΌκ³ λͺ μν μ μμ΅λλ€. λ°λΌμ μλ λ΄μ©λ€ μ€ λλΆλΆμ νμνμ§ μκ³ , νμν κΆνμ΄ λ¬΄μμΈμ§, μ΄λ»κ² λͺ μν΄μΌ νλμ§λ₯Ό μ΄ν΄λ³΄μ λ€μ expo-locationμμμ μ¬μ©λ²μ λ°λ₯΄μ μΌ ν©λλ€.
μ°μ ν¨ν€μ§λ₯Ό μ€μΉνκ³ μ€μ ν©λλ€.
yarn add react-native-permissions
react-native-permission
μ κ° νλ«νΌλ³ μ€μ λ°©λ²μ μ¬μ©λ²μ μ§μ μ°Έκ³ ν΄
Podfile(iOS)
, AndroidManifest.xml(Android)
λ₯Ό μ μ ν λ³κ²½ν΄μ£ΌμκΈΈ λ°λλλ€.
iOSλ λ€μκ³Ό κ°μ μΈ κ°μ§μ κΆνμ΄ μ°κ΄λμ΄μμ΅λλ€.
NSLocationAlwaysAndWhenInUseUsageDescription(>= iOS 11)
NSLocationWhenInUseUsageDescription
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λ₯Ό μ§μνλ μ½λμμλ§ νμΈν΄λ μ¬μ©μ λ¬΄λ¦¬κ° μμ κ²μ λλ€.
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μμλ μ λλ‘ λμ΅λλ€.
image={{symbol: 'green'}}
require
react native image file) (caching β
)image={require('./marker.png')}
image={{assetName: 'asset_image'}}
image={{httpUri: 'https://example.com/image.png'}}
[!WARNING] νμ¬ headerκ°μ μμ±μ μ§μλμ§ μμ΅λλ€.
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
κ°μ μμ±μΌλ‘ μ§μμ΄ κ°λ₯ν κ²μΌλ‘ 보μ
λλ€), λ§μ»€ νλλΉ λ§μ 리μμ€λ₯Ό μ°¨μ§νκ² λ©λλ€.
NaverMapView
Prop | iOS | Android |
---|---|---|
isLogoInteractionEnabled | β | β |
gestureFrictions | π¦ | π¦ |
Event | iOS | Android |
---|---|---|
onTapSymbol | π¦ | π¦ |
onAuthFailed | β | β |
onLocationChange | π¦ | π¦ |
iOS | Android | |
---|---|---|
onLongTap | β | π¦ |
NaverMapMarkerOverlay
Prop | iOS | Android |
---|---|---|
caption-fontFamily | β | β |
subcaption-fontFamily | β | β |
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT