리액트 네이트브로 네이버 지도 구현하기 #2 — 카메라, 위치 이동하기

리액트 네이티브를 이용해 네이버 지도 구현하기 가이드 #2

MJ Studio
MJ Studio
10 min readApr 14, 2024

--

이전 가이드에선 React Native Naver Map 패키지를 이용해 설치 및 키 발급에 대해 알아보았습니다.

카메라 및 위치 조절

일단 자신의 위치를 이런 사이트같은 곳에서 얻어와봅시다.

제가 위치한 선릉역은 위도가 37.50497126, 경도가 127.04905021정도이니 이 값을 이용해보겠습니다.

initialCamera 속성은 맵이 생성된 후 첫 카메라 설정입니다. camera를 사용하지 않을 때만 사용해야합니다. 컴포넌트가 mount되고 변경해도 동작하지 않습니다.

즉, 유저의 위치를 useState 같은 것을 이용한 상태로 관리하지 않으려고 할 때 유용합니다.

initialCamra, camera, initialRegion, region 네 속성은 무조건 한 가지만 사용되어야 합니다.

function App(): React.JSX.Element {
return (
<View style={{flex: 1}}>
<NaverMapView
style={{flex: 1}}
initialCamera={{
latitude: 37.50497126,
longitude: 127.04905021,
}}
/>
</View>
);
}

만약 camera 를 이용해 상태를 관리하려면 다음과 같이 할 수 있습니다.

function App(): React.JSX.Element {
const [camera, setCamera] = useState<Camera>({
latitude: 37.50497126,
longitude: 127.04905021,
});
return (
<View style={{flex: 1}}>
<NaverMapView style={{flex: 1}} camera={camera} />
</View>
);
}

이제 맵을 컨트롤을 직접 상태를 바꿔서 해보겠습니다.

강남역의 좌표인 위도 37.498040483, 경도 127.02758183로 이동해보겠습니다.

다음과 같이 UI를 변경해보겠습니다.

const Cameras = {
Seolleung: {
latitude: 37.50497126,
longitude: 127.04905021,
},
Gangnam: {
latitude: 37.498040483,
longitude: 127.02758183,
},
} satisfies Record<string, Camera>;

function App(): React.JSX.Element {
const [camera, setCamera] = useState<Camera>(Cameras.Seolleung);
return (
<View style={{flex: 1}}>
<NaverMapView style={{flex: 1}} camera={camera} />
<View
style={{
position: 'absolute',
bottom: 48,
left: 20,
right: 20,
height: 200,
backgroundColor: 'white',
borderRadius: 12,
borderWidth: 1,
borderColor: '#0002',
flexDirection: 'row',
alignItems: 'center',
flexWrap: 'wrap',
gap: 4,
}}>
<Button title={'Gangnam'} onPress={() => setCamera(Cameras.Gangnam)} />
<Button
title={'Seolleung'}
onPress={() => setCamera(Cameras.Seolleung)}
/>
</View>
</View>
);
}

이제 버튼을 누를때마다 선릉역과 강남역을 이동함을 알 수 있습니다.

Zoom, Tilt, Bearing(Heading)

그런데 이동할 때 역이 안보이는 정도로 이동합니다. 여기서 사용할 수 있는 속성이 zoom 입니다.

zoom은 기본으로 10이고, 15정도로 변경되도록 해보겠습니다.

const Cameras = {
Seolleung: {
latitude: 37.50497126,
longitude: 127.04905021,
zoom: 15,
},
Gangnam: {
latitude: 37.498040483,
longitude: 127.02758183,
zoom: 15,
},
} satisfies Record<string, Camera>;

이제 완벽히 역이 보이도록 잘 이동합니다!

Camera 객체엔 두 가지 속성이 더있는데, tilt와 bearing입니다.

Tilt

카메라의 기울임 각도를 나타내는 속성입니다. 카메라는 기울임 각도만큼 지면을 비스듬하게 내려다봅니다. 기울임 각도가 0도이면 카메라가 지면을 수직으로 내려다보며, 각도가 증가하면 카메라의 시선도 점점 수평에 가깝게 기울어집니다. 따라서 기울임 각도가 클수록 더 먼 곳을 볼 수 있게 됩니다. 카메라가 기울어지면 화면에 보이는 지도에 원근감이 적용됩니다. 즉, 화면의 중심을 기준으로 먼 곳은 더 작게 보이고 가까운 곳은 더 크게 보입니다.

Bearing

카메라의 헤딩 각도를 나타내는 속성입니다. 헤딩은 카메라가 바라보는 방위를 의미합니다. 카메라가 정북 방향을 바라볼 때 헤딩 각도는 0도이며, 시계 방향으로 값이 증가합니다. 즉, 동쪽을 바라볼 때 90도, 남쪽을 바라볼 때 180도가 됩니다

자유롭게 변경하면서 조절해보겠습니다. 지도의 보이는 모습이 달라집니다.

Region 속성

camera 와 다르게 regioninitialRegion 은 직접 보이는 지역을 표시하는 방법이고 tilt, bearing 이 0으로 설정된 상태에서 딱 원하는 위치만 보여주기에 적합합니다.

latitude, longitude

한반도의 위치상 지도에서 왼쪽 아래의 위도, 경도는 위가 북쪽이라고 할 때 더 작습니다.

latitude, longitude는 이 위치를 의미합니다.

latitudeDelta, longitudeDelta

두 델타값은 지도에서 각각 세로 길이와 가로 길이를 의미하게 된다고 생각하시면 됩니다.

지도에서 보여줄 사각형 영역을 정의해 그걸 최대의 Zoom으로 보여줄 수 있는 정도의 위치와 zoom이 자동으로 설정됩니다.

다음과 같이 Region을 이용하는 코드로 바꿔보겠습니다.

const Regions = {
Seolleung: {
latitude: 37.50497126,
longitude: 127.04905021,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
},
Gangnam: {
latitude: 37.498040483,
longitude: 127.02758183,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
},
} satisfies Record<string, Region>;

function App(): React.JSX.Element {
const [region, setRegion] = useState<Region>(Regions.Seolleung);
return (
<View style={{flex: 1}}>
<NaverMapView style={{flex: 1}} region={region} />
<View
style={{
position: 'absolute',
bottom: 48,
left: 20,
right: 20,
height: 200,
backgroundColor: 'white',
borderRadius: 12,
borderWidth: 1,
borderColor: '#0002',
flexDirection: 'row',
alignItems: 'center',
flexWrap: 'wrap',
gap: 4,
}}>
<Button title={'Gangnam'} onPress={() => setRegion(Regions.Gangnam)} />
<Button
title={'Seolleung'}
onPress={() => setRegion(Regions.Seolleung)}
/>
</View>
</View>
);
}

그런데 이제 이동해보면 강남역과 선릉역이 정확히 지도의 중앙에 위치하지 않습니다.

왜냐면 Region에서 latitude, longitude는 지도의 왼쪽 아래를 의미하는 값이기 때문입니다.

애니메이션으로 지도 움직이기

state로 관리하면 지도가 바로 움직이지만 애니메이션으로 Camera나 Region을 변경할 수 있습니다.

function App(): React.JSX.Element {
const [region, setRegion] = useState<Region>(Regions.Seolleung);
const ref = useRef<NaverMapViewRef>(null);
const map = () => ref.current;
return (
<View style={{flex: 1}}>
<NaverMapView ref={ref} style={{flex: 1}} region={region} />
<View
...
<Button
title={'Gangnam'}
onPress={() =>
map()?.animateCameraTo({
...Cameras.Gangnam,
duration: 3000,
easing: 'Fly',
})
}
/>
</View>
</View>
);
}
  • animateCameraTo

카메라를 애니메이션과 함께 이동시킵니다.

  • animateCameraBy

카메라를 특정 위치만큼 델타값으로 애니메이션과 함께 이동시킵니다.

  • animateRegionTo

카메라를 특정 Region으로 애니메이션과 함께 이동시킵니다.

  • animateCameraWithTwoCoords

카메라를 두 좌표가 모두 보이는 최대 줌 레벨로 애니메이션과 함께 이동시킵니다.
카메라의 중심은 두 좌표의 중심이며 pivot으로 조절할 수 있습니다. pivot은 기본 0.5(중앙)이며 0 ~ 1 값으로 설정할 수 있습니다.

마무리

camera, region객체가 무엇인지 알아보고 그것을 이용해 지도의 위치를 관리하는 방법을 배웠습니다.

다음 가이드에선 여러가지 오버레이들을 이용해 지도에 마커를 띄우거나 쉐이프들을 그려보겠습니다.

--

--