[React Native] 리액트 네이티브에서 구글 지도 + 장소 검색 구현하기

부기·2023년 4월 24일
1
post-thumbnail

서비스에서 지도를 띄워두고 장소를 검색하는 기능을 개발하게 됐다. 여러가지를 고려하느라 시간이 조금 걸렸는데, 고민한 내용들을 타임라인처럼 적어보려 한다.

1. 어떤 지도 API를 써야할까?

첫 단계에서 고민을 많이 했다. 내가 후보군에 올려놓은 지도 API는 다음 3가지였다.

  • 네이버 지도 API
  • 카카오 지도 API
  • 구글 지도 API

일단 기획된 서비스 대상이 국내에 한정되어 있어서, 국내 기업이 지원하는 API가 장소 정보에 대한 신뢰성이 더 높을 것 같았다. 이래놓고 구글 API 썼다.

1-1. 카카오 지도 API를 쓸 수 없었던 이유

처음엔 카카오 지도 API를 쓰려고 했다. 과거에 리액트 프로젝트로 웹 서비스를 구현하면서 지도 기능이 필요하여 JavaScript API를 가져다 써본 경험이 있었기 때문이다.
하지만 리액트 네이티브 프로젝트에서 API를 가져다 쓰려면 웹뷰가 필요했다. 나는 되도록 어플리케이션 내부에서 동작하는 것을 원했기 때문에, 잠시 보류하고 일단 다른 API 중에 내 요구사항에 맞는 것이 있는지 먼저 살펴보기로 했다.

1-2. 구글 지도 API를 쓰기로 한 이유

지도 기능을 처음 요청받자마자 당연히 쓰려고 했던 카카오 지도 API를 포기하게 되니, 네이버 지도 API와 구글 지도 API 중에 고민해야했다. 찾아보니 둘다 리액트 네이티브 프로젝트에 API를 적용할 수 있도록 일종의 브릿지 역할을 하는 npm 모듈이 있었다.
네이버 지도 API는 아무래도 결과의 신뢰성 측면에서 써볼만했지만, 개발을 하면서 오류가 나거나 했을 때 참고할 수 있는 레퍼런스는 구글 지도 API 쪽이 압도적이었다.

2. 어떻게 세팅할까?

2-1. npm 패키지 설치하기

1) react-native-maps

> yarn add react-native-maps

2) react-native-google-places-autocomplete

> yarn add react-native-google-places-autocomplete

Podfile을 업데이트해준다.

> cd ios
> pod install

2-2. GCP 콘솔에서 API 등록하기

가입된 구글 계정으로 Google Cloud Platform(GCP) 콘솔에 접속하면 API 등록을 할 수 있다. 나는 다음 3개의 API 키가 필요하다. 참고로 Places API 키는 iOS, Android 용이 따로 구분되어 있지 않은 것 같다.

  • Android 에서 사용하는 Maps API 키
  • iOS 에서 사용하는 Maps API 키
  • Places API 키

따라서, 다음 순서대로 진행하며 3개를 등록해주었다. iOS 용 키 등록과 Android 용 키 등록이 약간 다르니 주의해서 진행한다.

1) 프로젝트 생성하기

API 키를 올릴 새 프로젝트를 생성해준다.

2) API 키 생성하기

사용자 인증 정보 탭에 들어간다.

API 키를 생성해준다.

나는 3개의 API 키를 사용할 것이기 때문에 일단 이렇게 3개를 등록했고, 이후에 각각을 용도에 맞게 수정했다.

3) iOS API 키 수정하기

iOS 에서 사용할 API 키를 수정하기 전에, 확인해놓아야 하는 것이 있다. Xcode로 리액트 네이티브 프로젝트의 .xcodeproj 파일을 열어서 TARGET을 선택하고 General 탭을 클릭하여 Bundle Identifier를 복사해두어야 한다.

API 키 수정 화면에서, iOS 제한사항에 속성을 추가한 뒤 복사한 Bundle Identifier를 붙여넣었다. 우측의 API Key는 따로 복사해둔 후 수정사항을 저장한다.

4) Android API 키 수정하기

Android 도 API 설정을 수정하기 전에 확인해야 하는 것이 2가지 있다. 리액트 네이티브 프로젝트의 android 경로에서 다음 명령어를 입력한다.

> .gradlew signingReport

터미널에서 SHA-1 키를 복사한다.

다시 Android API 키 수정 화면으로 이동해서, Android 제한사항을 추가한 후 복사해둔 디지털 지문을 붙여넣고 저장한다. 패키지 이름android/src/main/java/com/프로젝트명/MainActivity.java 파일에서 최상단에 있는 패키지명을 기입하면 된다. 마찬가지로 우측의 API 키를 복사해두자.

5) Places API 키 수정하기

Places API 키 수정 화면에서는 우측의 API 키만 복사해두면 된다.

6) API 사용 활성화하기

다음 3개의 라이브러리를 등록해준다. 처음 사용할 때는 카드 등록 과정을 거쳐야 한다.

2-3. 프로젝트에서 API 설정하기

1) iOS 설정하기

리액트 네이티브 프로젝트의 ios/프로젝트명/AppDelegate.mm 파일을 열어서 내용을 확인하고 다음과 같이 추가한다. iOS API 키 수정하기에서 복사해 둔 키를 넣는다.

// AppDelegate.mm
#import "AppDelegate.h"
...
#import <GoogleMaps/GoogleMaps.h>
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [GMSServices provideAPIKey:@"API 키"];
  self.moduleName = @"프로젝트명";
  // You can add your custom initial props in the dictionary below.
  // They will be passed down to the ViewController used by React Native.
  self.initialProps = @{};

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

ios/Podfile 파일을 열어서 다음과 같이 추가한다.

# Podfile
...
target '프로젝트명' do
  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
  config = use_native_modules!
...

ios/프로젝트명/Info.plist 파일을 열어서 다음과 같이 추가한다. <string> 부분은 동의 팝업이 뜰 때 나타나는 문구이므로 원하는 대로 적는다.

<!-- Info.plist -->
...
<dict>
	...
	<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
	<string>서비스 이용을 위해 위치 정보 접근 권한이 필요합니다.</string>
	<key>NSLocationAlwaysUsageDescription</key>
	<string>서비스 이용을 위해 위치 정보 접근 권한이 필요합니다.</string>
    ...
</dict>
...

2) Android 설정하기

android/app/src/res/AndroidManifest.xml 파일에 다음과 같이 추가한다. Android 키 수정하기에서 복사해둔 키를 넣는다.

<!-- AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
	...
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
	...
    <application ...>
    	<meta-data
	      android:name="com.google.android.geo.API_KEY"
	      android:value="API 키"/>
      	<uses-library android:name="org.apache.http.legacy" android:required="false"/>
       	...
   	</application>
</manifest>

3. 어떻게 실행할까?

세팅이 끝났으니 실행을 해서 확인해볼 차례이다. 지도를 표시해줄 MapView 컴포넌트와 장소 검색창을 표시해줄 GooglePlacesAutoComplete 컴포넌트를 띄워보자.

3-1. 지도 띄우기

const MapSearch: React.FC = () {
  ...
  return (
    <View>
      <MapView
        provider={PROVIDER_GOOGLE}
        initialRegion={{
          latitude: 37.541,
          longitude: 126.986,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        }}
        style={styles.map}
      />
      ...
   	</View>
  )
}

export default MapSearch;

3-2. 장소 검색창 띄우기

GooglePlacesAutoComplete 컴포넌트의 스타일링은 react-native-google-places-autocomplete 문서에 자세히 나와있다.

const MapSearch: React.FC = () {
  ...
  return (
    <View>
      ...
      <GooglePlacesAutocomplete
        minLength={2}
        placeholder="장소를 검색해보세요!"
        query={{
          key: 'API 키',
          language: "ko",
          components: "country:kr",
        }}
        keyboardShouldPersistTaps={"handled"}
        fetchDetails={true}
        onPress={(data, details) => {console.log(data, details);}}
        onFail={(error) => console.log(error)}
        onNotFound={() => console.log("no results")}
        keepResultsAfterBlur={true}
        enablePoweredByContainer={false}
        styles={styles.search}
      />
   	</View>
  )
}

export default MapSearch;

4. 결과물

스타일링까지 완료한 최종 결과물은 이렇다.

회고

사실 구현하는 데는 그렇게 오래 걸리지 않았는데, 내가 무엇을 했는지 하나하나 글로 정리하는 게 쉽지 않았다. 여유 없이 되는 대로 개발하면 나중에 정리하기가 훨씬 어려운 것 같다 ^^; 여유있게 생각하는 습관을 들여야겠다.
그리고 API 키를 지금 상태로 코드에 넣어두는 것은 바람직하지 않다. 나중에 따로 빼서 프라이빗하게 관리할 수 있게 적용할 예정이다.(TO-DO!)

참고 자료

profile
도파민 중독 프론트엔드 개발자

0개의 댓글