빌드 후 구글 지도가 안보이는 문제
이 문제는 구글 맵 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/)에 접속하여 로그인한다.
결제 하라고 뭐라뭐라 하는데 결제 안되니 겁먹지 말고 카드 등록 + 프로필 설정까지 전부 마치면 됨!
[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 > 사용자 인증 정보
사용자 인증 정보 페이지에서 사용자 인증 정보 만들기 > 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>
);
이런 식으로 최종 렌더링을 해주면 된다. MapView의 region 옵션을 사용해서 위도와 경도를 넣어준다.
참고로 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
완성된 화면
처음에 부모 태그 안 감싸주고 지도가 안 떠서 당황했고
빌드 후에 지도가 홀랑 사라져서 ㅜㅜ 너무 슬펐다
부딪히면서 배우는게 제일 기억에 잘 남는 것 같다....... 흑흑
'React-Native' 카테고리의 다른 글
[React-Native] 현재 위치 불러오기 / Expo Location 사용하기 (0) | 2024.07.09 |
---|---|
[Raact-Native] 조건부 렌더링, 리액트처럼 라우터 기능 구현하기 (0) | 2024.04.11 |