지하철 타고 가다가 내려야 되는 역을 듣지 못하고 지나쳐버린 개인 경험에서 비롯하여 이를 해결해줄 앱을 만들기로 결심하였습니다.
이 앱은 사용자의 현재 위치를 실시간으로 파악하기 위해 모바일 디바이스의 geolocation 데이터를 추적합니다. 앱이 background 상태일 때도 내릴 역에 도착하면 푸쉬알림을 띄워줍니다.
앱이 작동하는 방식은 다음과 같습니다.
- 사용자는 앱을 실행하고 내릴 역을 설정합니다.
- 앱은 사용자의 현재 위치를 추적합니다.
- 사용자의 현재 위치가 내릴 역과 가까워지면 앱은 푸쉬알림을 띄웁니다
지하철역 검색 기능 | 최초 진입 시 위치 추적 퍼미션 | 지하철 역 근처에 도착하면 푸시 알림 기능 |
---|---|---|
Android Studio (emulator) 또는 XCode (simulator) 또는 실기기 연결 후 로컬환경에서 다음 명령어를 실행해주세요.
yarn start
yarn run android // or yarn run ios
-
프론트엔드: React Native, Styled-Components
-
상태관리: Recoil
-
푸시알림: notifee
-
지도: React-native-nmap, react-native-geolocation-service
-
테스트: jest
-
코드컨벤션: eslint, prettier
[문제] 기존 코드에는 한글자 타이핑 할 때 마다 지하철 데이터 API 함수를 호출하기 때문에 상당히 비효율적이었습니다.
[해결] lodash
라이브러리의 debounce
메서드를 이용하여 700ms 동안 호출을 지연시킵니다. 타이핑이 멈추고 (끝나고) 해당 시간이 지난 후에야 함수 호출을 하기 때문에 불필요한 호출 빈도를 줄일 수 있습니다.
[코드]
import {debounce} from 'lodash';
...
const debouncedGetMetroData = debounce(getMetroData, 700);
...
// jsx
<SearchBarInput
...
onChangeText={text => {
debouncedGetMetroData(text);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}}
/>
[출처] https://www.mrlatte.net/code/2020/12/15/lodash-debounce
- [커밋] https://github.com/saul-atomrigs/metro-location-app/commit/071a4dd0acd691baccdd73c14f2e8dc08683489f)
// 상대경로 예시:
import ImportHell from '../../../../../src/screens/ImportHell'
// 절대경로 예시:
import ImportHeaven from 'screens/ImportHeaven'
-
[커밋] https://github.com/saul-atomrigs/metro-location-app/commit/8826ecdfba7458bedfa17430ba7c1d7ac838b5d9)
-
[커밋] https://github.com/saul-atomrigs/metro-location-app/commit/bc7fa6972b1f0d3aae658c3477f7f8c48f777ea5)
-
- 리액트 네이티브 위치 퍼미션 이슈 해결 (https://stackoverflow.com/questions/59892302/location-permission-not-granted-in-react-native)
- 실기기에서 위치 실시간으로 반영되는지 백그라운드에서도 테스트
-
[참조] https://github.com/luggit/react-native-config - April 5, 2023
-
[iOS 에러]: iOS에서만 환경 변수 못 읽어오는 이슈. 버전 reverted해서 임시적으로 해결 (lugg/react-native-config#737 (comment)) April 16, 2023 -> 커밋: https://github.com/saul-atomrigs/metro-location-app/commit/94561207d995f2e8ae4b7c98cd535afd9f6202c3
-
[Babel 에러]:
.plugins 0 may only be a two-tuple or three-tuple
April 18, 2023 https://github.com/goatandsheep/react-native-dotenv 라이브러리로 대체 → Babel 설정 중 2개 이상의
plugins
설정 하는 법 배울 수 있었다(https://stackoverflow.com/questions/46937204/is-it-possible-to-use-more-than-one-babel-preset-in-a-project) → 바벨 설정 커밋 링크 (https://github.com/saul-atomrigs/metro-location-app/commit/ad8613d7e233f0af01c614e0421dfdee41f5110d)
-
-
- RNNaverMapMarker을 UIManager가 찾지 못하는 이슈 해결 → node_modules 폴더와 yarn.lock 파일 삭제하고, ios 폴더로 이동해 pod deintegrate 후 다시 pod install(https://www.inflearn.com/questions/611165/rnnavermapmarker을-uimanager가-찾지-못하는-에러)
- 리액트 네이티브에서 환경 변수 세팅하기 (react-native-config). iOS, Android 각각 설정 방식 다름. 2023.04.05
- iOS에서 네이버 지도 셋업
- Android에서 네이버 지도 셋업
- [안드로이드 에러]: 라이브러리 추가 시 에러 (Build was configured to prefer settings repositories..)는 이 곳 (https://angelplayer.tistory.com/263) 에서 방법 2로 해결, 2023.04.05
- [ios, Android 공통 타입 에러]: NaverMapViewProps에 children이 없어서 NaverMapView 컴포넌트의 자식 컴포넌트를 넣으면 타입 에러 (No overload matches this call…) 뜨는 이슈. QuadFlask/react-native-naver-map#149 ← PR올라와 있지만, 아직 반영이 안 되어, 직접 node_modules 소스코드에 반영하여 patch package 하여 이슈 해결 April 16, 2023 -> 커밋: https://github.com/saul-atomrigs/metro-location-app/commit/af0ea303b12397ec98e97668574192bea2138df8
-
- [Local notification vs Push (remote) notification]
- local: 앱 자체에서 띄움. 예) 시간, 장소, 스케쥴 등에 따라 알림 등 ← metro-location-app에 더 적합
- Notifee https://velog.io/@2ast/React-Native-local-push-notification-셋팅하기-feat-notifee April 27, 2023 안드로이드 알림이 오긴 하지만, 팝업 형식으로 하려면?
- push: 외부 서버에서 띄움. 예) 실시간 안내, abandoned cart 알림 등
- local: 앱 자체에서 띄움. 예) 시간, 장소, 스케쥴 등에 따라 알림 등 ← metro-location-app에 더 적합
Geolocation
패키지의watchPosition
메소드를notifee.registerForegroundService
안에 추가. May 19, 2023:
notifee.registerForegroundService(() => { let currentLatitude = ''; let currentLongitude = ''; Geolocation.watchPosition(position => { currentLatitude = position.coords.latitude; currentLongitude = position.coords.longitude; }); return new Promise(() => { if ( Math.abs(currentLatitude - P0.latitude) < 0.005 && Math.abs(currentLongitude - P0.longitude) < 0.005 ) { notifee.displayNotification({ title: 'Foreground Service', body: '이번 역에서 내리세요', android: { channelId: 'default', }, }); } }); });
- 좌표데이터는
number
타입인데, 습관적으로let 변수명 = ''
으로 초기화해서 (즉,string
타입으로) 오류 발생 May 25, 2023
- [Local notification vs Push (remote) notification]
-
def getPassword(String currentUser, String keyChain) { def stdout = new ByteArrayOutputStream() def stderr = new ByteArrayOutputStream() exec { commandLine 'security', '-q', 'find-generic-password', '-a', currentUser, '-s', keyChain, '-w' standardOutput = stdout errorOutput = stderr ignoreExitValue true } //noinspection GroovyAssignabilityCheck stdout.toString().trim() }
[참조] https://pilloxa.gitlab.io/posts/safer-passwords-in-gradle/
-
[iOS 빌드 에러] module map file '/Users/atomrigslab/Library/Developer/Xcode/DerivedData/metro-goccvfvslwkmkmedzwsqgmqkcmim/Build/Products/Debug-iphonesimulator/YogaKit/YogaKit.modulemap' not found
[해결] 여기서 xcdoeproj 가 아닌 xcworkspace 파일을 통해서 xcode를 열어야한다.
-
[Android앱 출시 에러] Android 13(API 33)에 광고 ID 변경사항 도입광고 ID를 사용하고 Android 13 이상을 타겟팅하는 앱은 앱 매니페스트에서 com.google.android.gms.permission.AD_ID 권한을 선언해야 합니다.
[해결] (1) 광고가 없을 시
AndroidManifest.xml
에 다음을 추가:<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove" /> <meta-data android:name="google_analytics_adid_collection_enabled" android:value="false" />
(2) 광고가 있다면 콘솔에서 광고 사용을 '예'로 하고 Analytics를 체크
-
[안드로이드 빌드 에러]
[원인] 미상
[해결] 터미널에
nano ~./zshrc
→ 환경변수 재설정:export ANDROID_HOME={복사한 안드로이드 sdk 위치} export PATH=$PATH:$ANDROID_HOME/emulator export PATH=$PATH:$ANDROID_HOME/tools export PATH=$PATH:$ANDROID_HOME/tools/bin export PATH=$PATH:$ANDROID_HOME/platform-tools
-
[iOS 빌드 에러] 스크린샷
[해결] XCode 빌드 폴더 클린 후 다음 커맨드 실행:
rm -rf ios/build rm -rf Pods pod install
[출처] software-mansion/react-native-reanimated#3823 (comment)