React-Native

[React-Native] 리액트 네이티브 지도 사용하기 / expo에서 지도 구현 / google map API key 추가하는 방법 / 빌드 후 구글 지도가 안보이는 문제

solfa 2024. 7. 11. 03:26

빌드 후 구글 지도가 안보이는 문제

이 문제는 구글 맵 api 키를 환경 설정에 등록을 안했기 때문입니다!!!

api 키 발급받아서 app.json에 추가해주면 빌드 후에도 정상적으로 지도가 뜹니다!! 밑에서 확인하세요


구현하고 싶은 것

서버에서 위도와 경도를 받아와서 해당 지역을 지도로 보여주는 기능을 구현하고 싶었다.

 

이런 느낌으로! 

지도표시 + 해당 위치(1위) 마커 + 간단한 설명 + 1, 2, 3 순위 클릭 시 하단 지도에 위치 보여주기

요 정도를 구현 할 예정이다.


구현 할 것

1. 지도 라이브러리 선택하기

2. 서버로 위도 경도 받아오기

3. 해당 위치 지도에 마커로 띄우기

 

사실 할 건 별로 없다! 다만 지도를 쓰기 위해 api키를 발급받고 설정하고 그런 귀찮은것 들이 존재할 뿐!!!


구현 방법

1. 지도 라이브러리 선택하기

리액트 네이티브에서 사용할 수 있는 지도들은 꽤 한정적이다.

대표적으로 구글 맵과 네이버 지도 두 가지가 있다.

 

Q. 선생님 카카오 맵은 못 쓰나요?

A. 음... 쓸 순 있는데...

 

1. 공식적인 지원 부족 : 카카오맵은 리액트 네이티브에 대한 공식적인 라이브러리나 지원이 현재 없다. 따라서 사용하려면 직접 웹뷰(WebView)를 사용하거나, 네이티브 브릿지를 작성해야 한다. expo 쓰고 있는 입장에서는 네이티브? 어림도 없는 소리... 핳


2. 문서와 예제 부족 : 카카오맵을 리액트 네이티브에서 사용하는 방법에 대한 자료가 거의 없다.(따흑) 따라서 개발 과정에서 문제가 발생했을 때 해결 방법을 찾기 어려울 수 있다.

그래서 난 구글 맵을 사용하기로 했다! 네이버 지도는... 레퍼런스가 많이 없어서 안 썼다 ㅎㅎ

근데 웹뷰로 지도 띄우는 것도 나름 좋은 경험이니 나중에 한 번 해봐야겠다는 생각이 든다. (다 끝나고 이제서야)

 


리액트 네이티브에서 사용할 수 있는 지도 라이브러리 중 가장 많이 사용되는 두 가지는

`react-native-maps`와 `react-native-maps-google`가 있다.

 

  • react-native-maps
    • 구글 맵뿐만 아니라 애플 맵도 지원한다. 가장 대중적임.
    • NPM 다운로드 수: 800,000+ (월간 기준)
    • GitHub Repository
  • react-native-maps-google
    • 얘는 구글 맵 전용이다. 구글 맵의 고급 기능을 사용할 수 있도록 최적화되어 있다.
    • NPM 다운로드 수: 100,000+ (월간 기준)
    • GitHub Repository
  • => 지원 안 함

많이 쓰는 게 좋은 거니까 ㅎㅎㅎ 나는 `react-native-maps`를 사용했다.

 

2. 라이브러리 설치하기

npm install react-native-maps


3. 구글 지도 API 키 받아오기


구글 지도를 쓰려면 지도를 사용하겠다는 의미로 API키를 발급받아야 한다!

물론 라이브러리 설치 후 바로 사용은 가능하다! 로컬에서 바로 써보면 지도가 잘 나타나는 걸 확인할 수 있다. 하지만! API키를 써주지 않으면 개발을 모두 끝내고 빌드하고 난 후 지도가 사라지는... 안보이는 문제가 발생한다! 해당 문제는 API키를 발급받아서 app.json에 써주면 해결된다. 아무튼 추후를 위해 API키를 발급받고 파일에 추가까지 해보자.


구글 지도 API 키 발급받기
1. [Google Maps Platform](https://mapsplatform.google.com/)에 접속하여 로그인한다.

결제 하라고 뭐라뭐라 하는데 결제 안되니 겁먹지 말고 카드 등록 + 프로필 설정까지 전부 마치면 됨!

 

https://velog.io/@sukqbe/API-%EA%B5%AC%EA%B8%80-%EC%A7%80%EB%8F%84Google-Map-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0-API-Key-%EB%B0%9C%EA%B8%89%EB%B0%9B%EA%B8%B0-qumur49u

 

[API] 구글 지도(Google Map) 추가하기 (+ API Key 발급받기)

구글 지도(Google Map) API Key 발급 및 사용법

velog.io

 

나는 이 글 참고했다! 로그인 후 첫 api 키 발급까지 마쳤다면 Google Cloud Platform 관리 페이지로 넘어오게 된다.

여기에서 앞으로 API 키 관리나 각종 설정등이 가능하다. 평소에는 여기 링크로 들어가서 관리하는 식!

https://console.cloud.google.com/apis/

 

Google 클라우드 플랫폼

로그인 Google 클라우드 플랫폼으로 이동

accounts.google.com


2. 새 프로젝트를 생성한다.

콘솔 클라우드에 들어가서 새 프로젝트를 만들어준다. My First Project를 누르면 밑에처럼 새 프로젝트 생성하는 창이 뜬다.

오른쪽 상단에 새 프로젝트 클릭!

 

3. 좌측 메뉴에서 'API 및 서비스' -> '라이브러리'로 이동한다.

Google Maps Platform > 사용자 인증 정보

https://console.cloud.google.com/project/_/google/maps-apis/credentials?utm_source=Docs_CreateAPIKey&utm_content=Docs_maps-android-backend&hl=ko

사용자 인증 정보 페이지에서 사용자 인증 정보 만들기 > API 키를 클릭하면 API 키 생성 완료!

대화상자에 새로 만든 API 키가 표시된다. 이 생성된 API 키를 `app.json` 파일에 추가해주면 된다.

 

나는 expo라 app.json에서 ios와 안드로이드 각각 밑에 넣어줬다.

android/ios 아래에 config 하위에 googleMaps를 써주고 그 하위에 apiKey를 입력해준다!

    ...
    "android": {
      "package": "com.hobak.happinessql",
      "config": {
        "googleMaps": {
          "apiKey": "발급받은 API 키"
        }
      }
    },
    ...

 

이런 식으로 해주면 설정 끝!

 

4. 코드 작성하기

4-1. 서버로부터 위도와 경도 받아오기
나는 api 코드로 받아왔다. 밑에 전체 코드 첨부 참고하세용

4-2. 해당 위치를 지도에 마커로 띄우기

`MapView` 컴포넌트와 `Marker` 컴포넌트를 사용하여 지도 위에 마커를 표시할 수 있다.

 

MapView와 Marker를 사용한 예제 코드

import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import MapView, { Marker } from 'react-native-maps';

const Map = () => {
  const [coordinates, setCoordinates] = useState({ latitude: 37.78825, longitude: -122.4324 });

  useEffect(() => {
    const getCoordinates = async () => {
      const coords = await fetchCoordinates();
      if (coords) {
        setCoordinates(coords);
      }
    };
    getCoordinates();
  }, []);

  return (
    <View style={height: 450;}>
      <MapView
        initialRegion={{
          latitude: coordinates.latitude,
          longitude: coordinates.longitude,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        }}
      >
        <Marker coordinate={coordinates} />
      </MapView>
    </View>
  );
};


export default Map;


여기서 가장 중요한 점이 있다!

바로 MapView를 감싸는 View 태그를 반드시 만들어주고,

해당 View 태그에는 꼭!!! height를 지정해줘야한다!

안하면 지도가 안 보임 ㅎ 꼭 높이를 지정하라는 이런 소리는 아니고 부모 view 태그를 만들고 부모에 꼭 스타일 적용해줘야 안에 있는 mapview가 보인다. 왜인지는... 몰라... 

관련 이슈 첨부합니다

https://github.com/react-native-maps/react-native-maps/issues/684

 

코드 및 설명

import React, { useEffect, useState } from "react";
import { View, StyleSheet } from "react-native";
import MapView, { Marker } from "react-native-maps";
import { getLocation } from "./assets/apis/getTrends"; // 서버에서 위치 데이터를 받아오는 API

 

다음과 같이 필요한 모듈들 import 후

const [selectedLocation, setSelectedLocation] = useState({
  latitude: 37.5665,
  longitude: 126.978,
  latitudeDelta: 0.0922,
  longitudeDelta: 0.0421,
});

 

아무것도 없을 때를 대비해서 아무 위도/경도를 하나 기본 값으로 설정해주었다.

 

useEffect(() => {
  fetchData();
}, []);

const fetchData = async () => {
  try {
    const locationsData = await getLocation();
    setData(locationsData.data);
    if (locationsData.data && locationsData.data.length > 0) {
      const topLocation = locationsData.data[0];
      setSelectedLocation({
        latitude: topLocation.latitude || 37.5665,
        longitude: topLocation.longitude || 126.978,
        latitudeDelta: 0.0922,
        longitudeDelta: 0.0421,
      });
    }
  } catch (error) {
    console.error("Error fetching data:", error);
  }
};

 

fetchData 안에서 getLocation 함수를 통해 서버에서 위도와 경도를 받아오는 구조이다.

가져온 데이터가 있으면 첫 번째 위치를 selectedLocation(바로 보이는 지도의 위치) 상태로 설정해서 첫 번째 위치(1위)가 지도에 표시되도록 설정했다.

 

const handleLocationSelect = (location) => {
  if (location.latitude && location.longitude) {
    setSelectedLocation({
      latitude: location.latitude,
      longitude: location.longitude,
      latitudeDelta: 0.0922,
      longitudeDelta: 0.0421,
    });
  }
};

 

2위와 3위를 클릭했을 때도 해당 위치들이 지도에 표시되어야 하니까 위치를 handle하는 함수를 만들어서 클릭됐을 때 해당 위치가 const [selectedLocation, setSelectedLocation] = useState()에 저장되도록 설정하였다.

 

return (
  <View style={styles.container}>
    <View style={styles.mapContainer}>
      <MapView style={styles.map} region={selectedLocation}>
        {data.map(
          (location, index) =>
            location.latitude &&
            location.longitude && (
              <Marker
                key={index}
                coordinate={{
                  latitude: location.latitude,
                  longitude: location.longitude,
                }}
                title={location.location}
                description={location.happiestActivity}
              />
            )
        )}
      </MapView>
    </View>
  </View>
);

 

이런 식으로 최종 렌더링을 해주면 된다. MapViewregion 옵션을 사용해서 위도와 경도를 넣어준다.

참고로 region에는 위도, 경도, 지도의 확대/축소 수준을 결정하는 델타 값이 있다.

initialRegion={{
          latitude: 위도,
          longitude: 경도,
          latitudeDelta:  지도의 세로 방향에서 보이는 영역의 크기,
          longitudeDelta: 지도의 가로 방향에서 보이는 영역의 크기,
        }}

 

이 외에도 

  • showsUserLocation : 현재 사용자 위치를 지도에 표시할지 여부를 설정
  • zoomEnabled : 지도를 확대/축소할 수 있는지 여부를 설정
  • mapType : 지도의 유형을 설정, standard, satellite, hybrid, terrain (Android only) 중 하나

 

Marker에는

  • coordinate : 마커의 위치를 설정한다. 위도와 경도를 필요로 함
  • title : 마커를 탭할 때 표시되는 제목
  • description : 마커를 탭할 때 표시되는 설명
  • image : 마커에 사용할 커스텀 이미지를 지정
  • pinColor : 마커의 색상을 지정한다. 기본 색상은 빨간색
  • draggable : 마커를 드래그할 수 있는지 여부를 지정
  • onPress : 마커를 탭할 때 호출되는 콜백 함수

암튼 개많다 ;; 적절하게 잘 사용하면 좋을 듯! 라이브러리 깃허브 참고해서 사용해보자

 

https://github.com/react-native-maps/react-native-maps

 

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

 


 

완성된 화면

 

처음에 부모 태그 안 감싸주고 지도가 안 떠서 당황했고

빌드 후에 지도가 홀랑 사라져서 ㅜㅜ 너무 슬펐다

 

부딪히면서 배우는게 제일 기억에 잘 남는 것 같다....... 흑흑 

728x90