본문 바로가기
프로그래밍 개발/React Native

React Native - 구글 맵(Google Map) SDK 환경세팅과 위치 기반 서비스 적용기

by Jinseok Kim 2023. 8. 22.
반응형

구글 맵(Google Map) SDK 환경 세팅과 지도 운영 서비스 적용기

제가 운영 중인 서비스 특성상 위치 기반 서비스가 필요했습니다. 유저 고객들이 Map을 활용하여 가까운 방문 가게나 병원을 더 수월하게 찾도록 하는 것이 목표였습니다.

 

현재도 많은 플랫폼 서비스들이 지도 기능을 이용한 서비스 운영을 하고 있습니다. 예를 들어 카카오 택시, 배달의 민족, 등등 위치 기반 서비스는 흔하면서도 플랫폼 서비스 운영의 활성화를 위한 필수 기능이라고 생각합니다.

 

 

 


국내용이 아닌 글로벌 서비스라는 특성으로 인하여 구글 Map을 사용해야 한다는 결정을 하게 되었습니다.

React Native 프레임워크를 쓰고 있는 프로젝트여서 구글 Map SDK를 React Native 프로젝트에 얹을 수 있는 적당한 라이브러리를 찾아 개발 및 서비스 배포를 하게 되었습니다.

 




 

React Native 구글 맵(Google Map) SDK 환경 세팅

 

기술 조사/서칭을 통하여 구글 Map SDK 라이브러리 중에 가장 많은 Stars와 활성화가 되어있는 라이브러리를 찾았습니다.

 

GitHub - react-native-maps/react-native-maps: React Native Mapview component for iOS + Android

React Native Mapview component for iOS + Android. Contribute to react-native-maps/react-native-maps development by creating an account on GitHub.

github.com

 

 

 

 

처음에는 라이브러리 패키지를 인스톨해 줍니다

npm install react-native-maps

 

 

 

이제부터는 OS별 Native 단 설정이 필요합니다.

 

 

iOS


 

패키지를 설치한 후에는 Pod를 설치해야 합니다.

cd ios && pod install

 

 

 

 

iOS에서 Google 지도를 활성화하려면 Google API 키를 얻고 AppDelegate.m(m)에서 다음과 같이 편집해야 합니다.

 

Google 콘솔에서 얻은 API 키가 필요합니다.

[GMSServices ProvideAPIKey]는 메서드의 첫 번째 호출이어야 합니다.

 

AppDelegate.m(m)

+ #import <GoogleMaps/GoogleMaps.h>

@implementation AppDelegate
...

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
+  [GMSServices provideAPIKey:@"_YOUR_API_KEY_"]; // Google 콘솔에서 얻은 API 키를 사용하여 이 줄을 추가해야합니다.

 

 

 

 

 


iOS용 Google Maps SDK에는 iOS 13이 필요하므로 iOS 프로젝트 설정에서 배포 대상이 13.0인지 확인해야 합니다.

Podfile 배포 대상이 Podfile 상단에서 = 13.0으로 설정되어 있는지 확인하세요. 

 

 

Podfile

platform :ios, '13.0'

 

 

 

 

 

 

이어서 Podfile에서 세팅이 더 필요합니다.

use_native_modules 위의 Podfile에 다음을 추가하시고 ios 폴더에서 pod install을 실행합니다.

 

Podfile

// Rosetta 없이 Apple Silicon Mac에서 빌드하는 경우에만 필요합니다.
pod 'Google-Maps-iOS-Utils', :git => 'https://github.com/Simon-TechForm/google-maps-ios-utils.git', :branch => 'feat/support-apple-silicon'

rn_maps_path = '../node_modules/react-native-maps'
pod 'react-native-google-maps', :path => rn_maps_path

 

 

 

마지막으로 권한 설정입니다.

App의 Info.plist 파일에는 앱에 위치가 필요한 이유를 명확하고 완전하게 설명하는 사용자 지향 목적 문자열과 함께 NSLocationWhenInUseUsageDescription이 포함되어야 합니다.

 

 

info.plist

	...
    
	<key>NSLocationWhenInUseUsageDescription</key>
	<string>현재 위치를 알 수 있도록 권한을 부여하여 위치별로 가까운 병원에 대한 정보를 제공합니까?</string>
    
	...

이 설정을 하지 않으면 Apple에서 앱 스토어 심사에서 반려당할 수 있으니 주의 바랍니다.

 


Google Maps iOS SDK에는 사용자 위치에 액세스 하는 데 필요한 코드가 포함되어 있으므로 사용자 위치에 액세스 하는지 여부에 관계없이 이는 필수입니다.

 

 

 

 

 

Android


 

 

AndroidManifest 파일에 API 키를 추가합니다.

 

android/app/src/main/AndroidManifest.xml

<application>
   <!-- 이 메타데이터 태그만 추가하면 되지만 application 하위 태그인지 확인하세요. -->
   <meta-data
     android:name="com.google.android.geo.API_KEY"
     android:value="Your Google maps API Key Here"/>
</application>

 




이제부터는 패키지 라이브러리, RN 버전에 따라 추가 설정이 필요할 수 있습니다.

만약 위의 세팅을 하고 나서도 이슈가 발생하거나 추가적인 설정이 필요하다면 아래 공식 Docs 환경세팅을 참고하시면 더 정확한 환경세팅이 가능합니다.

https://github.com/react-native-maps/react-native-maps/blob/master/docs/installation.md

 

 

 

 

 

 

위치 기반 서비스 적용하며 겪었던 고충과 배움

 

위치 기반 서비스 적용을 위해 사용했던 react-native-maps 패키지 라이브러리는 정말 훌륭했습니다. 기능을 구현하는데 필요한 메서드, fuction 기능들이 SDK 기능들을 잘 활용할 수 있도록 만들어 놓았다고 생각합니다.

 

처음에는 패키지 라이브러리가 너무 좋아 이 기능을 구현하는 데는 큰 어려움이 없었지만 이 당시 아직 개발자로서 부족한 역량 때문에 큰 이슈를 만나게 되었습니다.

 

 

 

지도의 상태값 변화에 따른 성능 랜더링 이슈


import MapView, { PROVIDER_GOOGLE } from 'react-native-maps'

// ...

<MapView
   onRegionChange={onRegionChange}
   customMapStyle={mapStyle}
   ...
>

위의 MapView 컴포넌트는 지도 뷰를 뿌려주는 컴포넌트입니다.

 

사용자가 지도를 제스처하여 서칭할때 onRegionChange 콜백 기능을 통해 들어오는 값을 활용하여 구현하려는 기능을 만들어 놓았습니다.

 

문제는 onRegionChange가 제스쳐 할 때마다 너무 많이 호출되어 onRegionChange에서 들어오는 값을 담는 state 값이 계속 바뀌면서 엄청난 랜더링을 발생시키는 것이 문제였습니다.

 

처음에는 큰 이슈라고 생각하지 않아 프로덕션 배포까지 하면서 신경을 쓰지 않기까지 했습니다. 하지만 어느 날 기능 검토를 하던 중에 Android 폰에서 지도를 사용하면 얼마 지나지 않아 앱을 사용할 수 없을 정도로 CPU를 과도하게 잡아먹어 작동하지 않는 치명적인 이슈를 발견하게 되었습니다. (iOS는 하드웨어가 좋아 이슈가 눈에 띄게 발현되지는 않았습니다)

 

 

 

 



지도 성능 랜더링 이슈를 해결하기


 

이때 이 성능 이슈를 해결하기 위해 Ref가 필요했습니다. onRegionChange에서 받아낸 지도 위치 값 수치들은 UI View에 실시간으로 표시할 필요가 없었고 이 수치를 통해 특정 이벤트 때 API에 담아 호출만 하면 되었기 때문에 굳이 useState을 이용하여 랜더링을 할 필요 없다는 것을 뒤늦게 깨닫게 되었습니다.

ReactJs의 내장 Hooks useRef을 사용하여 onRegionChange가 아무리 호출되어도 useRef을 사용하여 지도 위치 값을 저장하고 있어서 Ref값이 아무리 변동되어도 랜더링이 되지 않아 성능 이슈를 해결하게 되었습니다.

 

사실 개발에 능숙한 분들이 처음부터 Ref을 사용했겠지만 미숙했던 저는 처음부터 생각하지 못했던 것 같았습니다.

 

	const locationRef = useRef<{latitude: number; longitude: number}>({
            latitude: -6.217811692628187,
            longitude: 106.84085805632431,
  	});
  	const deltaRef = useRef<{latitudeDelta: number; longitudeDelta: number}>({
            latitudeDelta: 0.09180037480303938,
            longitudeDelta: 0.05152387131647629,
  	});


	...


	const onRegionChangeComplete = useCallback(
          (region, details) => {
              locationRef.current = {
                latitude: region?.latitude,
                longitude: region?.longitude,
              };
              deltaRef.current = {
                latitudeDelta: region?.latitudeDelta,
                longitudeDelta: region?.longitudeDelta,
              };
          },
          [],
    );

 

이 이슈 해결을 통해 위치 기반 서비스 기능을 구현해 보는 경험뿐만 아니라 ReactJS을 프로젝트의 성능 개선을 해보는 경험 또한 해보며 프론트엔드로서 한층 더 성장하는 느낌을 받았습니다.

성능 개선을 위하여 ReactJs에 대한 더 깊은 공부와 연구를 자연스럽게 더 하게 되었던 것 같았습니다.

반응형

댓글