๋ณธ ๋ฌธ์๋ ํ์ฌ ํ๋ก์ ํธ ์ฝ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์ต ํฌ์ธํธ๋ฅผ ์ ๋ฆฌํ ๋ฉ๋ชจ์ ๋๋ค. ํนํ ์์ ๋ก๊ทธ์ธ(Kakao SDK) ํ๋ฆ๊ณผ ์ค๋ฌด์์ ์ค์ํ๊ฒ ๋ณด๋ ๊ตฌํ/์ด์ ํฌ์ธํธ์ ์ง์คํ์ต๋๋ค.
- ์ฑ ์ฑ๊ฒฉ: ๋ฌ๋ ํธ๋ํน + ํผ๋/์ ๋ธ๋ผ/์ฌ์ ๊ธฐ๋ฅ์ด ์๋ ๋ชจ๋ฐ์ผ ์ฑ(Expo/React Native).
- ๋ค์ดํฐ๋ธ/ํ๋ซํผ: Expo Dev/Build + iOS/Android, Hermes, EAS ์ฌ์ฉ.
- ์ฃผ์ ๊ธฐ์ ์คํ: React Navigation, Expo Location, Axios, NativeModules(Kakao), AsyncStorage.
- ๋ฒ ์ด์ค URL:
utils/api/client.tsโhttps://api.waytoearth.cloud. - ๋ฅ๋งํฌ ์คํด:
waytoearth://(app.config.jsโscheme: "waytoearth").
- ํ๋ฉด:
Pages/(์:Login.tsx,LiveRunningScreen.tsx,Onboading.tsx๋ฑ) - ์ฌ์ฌ์ฉ ์ปดํฌ๋ํธ:
components/(์:KakaoLoginButton.tsx,Running/โฆ) - ํ
:
hooks/(์:useKakaoLogin.ts,useLiveRunTracker.ts) - API ๋ชจ๋:
utils/api/*.ts(client.ts,auth.ts,running.ts,users.ts,feeds.ts) - ์ ํธ:
utils/geo.ts,utils/run.ts(๊ฑฐ๋ฆฌ, ํ์ด์ค ๊ณ์ฐ ๋ฑ) - ํ์
:
types/types.ts,utils/api/types.ts - ์ค์ :
app.config.js,app.plugin.js,eas.json,tsconfig.json
- ์ฌ์ฉ์๊ฐ
Pages/Login.tsx์์ ์นด์นด์ค ๋ฒํผ ํญ โuseKakaoLogin()ํธ์ถ hooks/useKakaoLogin.tsNativeModules.RNKakaoLogins๋ก๋/๊ฒ์ฌ (๋ค์ดํฐ๋ธ ๋ชจ๋ ๊ฐ์ฉ์ฑ ํ์ธ)- ์นด์นด์คํก ๋ก๊ทธ์ธ ๊ฐ๋ฅ ์ฌ๋ถ ์ฒดํฌ โ ๊ฐ๋ฅ ์
login(), ๋ถ๊ฐ ์loginWithKakaoAccount()๋ก ์ก์ธ์ค ํ ํฐ ํ๋ - ์๋ฒ ๋ก๊ทธ์ธ:
utils/api/auth.ts์kakaoLoginWithSDK(accessToken)ํธ์ถ
kakaoLoginWithSDK- Kakao API
GET https://kapi.kakao.com/v2/user/me๋กkakaoIdํ๋ณด - ๋ฐฑ์๋
POST /v1/auth/kakao๋กkakaoId,accessToken์ ๋ฌ(๋ชจ๋ฐ์ผ ํ๋๊ทธ ํฌํจ) - ์๋ต์์
jwtToken์ถ์ถ(์๋ฒ ๋ํ ์ ๋ฌด๋ฅผ ๋ชจ๋ ์ปค๋ฒ)
- Kakao API
- JWT ์ ์ฅ ๋ฐ ๋ผ์ฐํ
AsyncStorage.setItem("jwtToken", โฆ)์ ์ฅisOnboardingCompleted์ ๋ฐ๋ผRegister๋๋LiveRunningScreen์ผ๋ก ์ด๋
- ํ
:
hooks/useKakaoLogin.ts- ๋ค์ดํฐ๋ธ ๋ชจ๋ ๊ฐ๋: RNKakao ์กด์ฌ/๋ฉ์๋ ์ฒดํฌ โ ์๋ฏธ์๋ ์ค๋ฅ ๋ฉ์์ง ์ ๊ณต(๊ฐ๋ฐ ๋น๋/APK ์ฌ์ค์น ์๋ด ํฌํจ)
getKeyHash()(Android) ์ง์ ์ ํคํด์ ํ์(๊ฐ๋ฐ ํธ์)- ์นด์นด์คํก ์ค์น/๊ฐ์ฉ์ฑ ๋ถ๊ธฐ โ
login()vsloginWithKakaoAccount()ํด๋ฐฑ - ์คํจ ์
Alert+ ์์ ํlogout()์๋
- API:
utils/api/auth.ts- Kakao
user/me์ฌ์กฐํ๋กkakaoId์ ๋ขฐ์ฑ ํ๋ณด ํ ์๋ฒ ๋ก๊ทธ์ธ ์์ฒญ - ์๋ฒ ์๋ต์ ๋ํผ({ success, data }) ๋๋ ์ง์ ํ์ด๋ก๋๋ฅผ ๋ชจ๋ ์์ฉํ๋ ์ธ๋ํ ๋ก์ง
- Kakao
- ํด๋ผ์ด์ธํธ:
utils/api/client.ts- ์์ฒญ ์ธํฐ์
ํฐ:
AsyncStorage์ JWT๋ฅผAuthorization: Bearer๋ก ์๋ ์ฃผ์ - ์๋ต ์ธํฐ์
ํฐ:
{ success, data, message }๋ํผ๋ฅผ ์๋ ์ธ๋ํ โ ๋ชจ๋๋ณ ์ฝ๋ ๋จ์ํ
- ์์ฒญ ์ธํฐ์
ํฐ:
- ์ค์ :
app.config.js+app.plugin.js@react-native-seoul/kakao-loginํ๋ฌ๊ทธ์ธ ์ฌ์ฉ, Android ๋น๋ ์ Kakao Maven,queries(Android 11+) ๋ฐkakao_app_key์๋ ์ฃผ์- EAS์์
KAKAO_NATIVE_APP_KEYํ๊ฒฝ๋ณ์ ์ฃผ์
- ํ์ฌ๋ SDK ์ง์ ๋ก๊ทธ์ธ ๋ฐฉ์(๋ค์ดํฐ๋ธ KakaoTalk ์ฑ ๋๋ ๊ณ์ ๋ก๊ทธ์ธ)์ ์ฌ์ฉ
- ์ฅ์ : ์ฌ์ฉ์ ๊ฒฝํ(์ํญ), ์์ ์ ์ธ ์ก์ธ์ค ํ ํฐ ํ๋ณด, ๋ฅ๋งํฌ/๋ฆฌ๋๋ ํธ ๋ณต์ก๋โ
- ๋์์ผ๋ก
kakaoLogin(code, redirectUri)ํจ์๋ ์ค๋น๋์ด ์์ผ๋ ํ์ฌ ๊ฒฝ๋ก๋kakaoLoginWithSDK๊ฐ ์ฃผ ๊ฒฝ๋ก
- ๊ฐ๋ฐ ๋น๋ ํ์: Kakao SDK๋ Expo Go๊ฐ ์๋ Dev/Production ๋น๋์์ ๋์
- ํคํด์ ๋ฑ๋ก: Android๋ ์ฝ์์ ์ฌ๋ฐ๋ฅธ KeyHash ๋ฑ๋ก ํ์(
useKakaoLogin,Login.tsx์์ ๋ก๊ทธ ํ์ธ) - Kakao App Key:
app.config.js/eas.json์์ ํ๊ฒฝ๋ณ์ ์ฐ๊ฒฐ ํ์ธ(EAS Secrets ๊ถ์ฅ) - Android Manifest
queries:com.kakao.talk์กฐํ ์ค์ (ํ๋ฌ๊ทธ์ธ์ด ์ฒ๋ฆฌ) - ๋ฅ๋งํฌ ์คํด:
scheme: "waytoearth"์ ์ง, iOS URL Types/Android Intent Filter ๋น๋ ํ์ธ - ์๋ฒ ์๋ต ํฌ๋งท: ์ธํฐ์
ํฐ ์ธ๋ํ/
auth.ts์ ๋คํ์ ํค(jwtToken|accessToken|token) ์ปค๋ฒ ์ฌ๋ถ ์ ๊ฒ
- ํ ํฐ ๋ณด๊ด:
AsyncStorageโ ํ์ ์expo-secure-store/Keychain ์ ํ ๊ฒํ (์ํ ๋ชจ๋ธ์ ๋ฐ๋ผ) - ํ ํฐ ๊ฐฑ์ : 401 ์ธํฐ์ ํฐ์์ Refresh ํ๋ฆ ์ถ๊ฐ(์ง๊ธ์ ์์)
- ๋ชจ๋ ๋ถ๋ฆฌ: Kakao SDK ์๋ฌ์ฝ๋ ๋งคํ/์ฌ์ฉ์ ์นํ ๋ฉ์์ง ํ ์ด๋ธํ
- ์ฌ์๋/๋ฐฑ์คํ: ์ผ์ ๋คํธ์ํฌ ์ด์์ ๋ํ ์์ ์ฑ(ํนํ ๋ก๊ทธ์ธ ์ฒซ ์ง์ )
- ๋ก๊น /ํธ๋ํน: ์คํจ์จ, ์๋ฌ์ฌ์ ๋์๋ณด๋ํ(Sentry/Ampli ๋ฑ)
- ํ
:
hooks/useLiveRunTracker.ts- ๊ถํ ์์ฒญ/์ค๋น(
getForegroundPermissionsAsync, ์ด๊ธฐ ์์น ์บ์) - ์์น ์คํธ๋ฆผ ๊ตฌ๋
(
watchPositionAsync) + ๋ ธ์ด์ฆ ํํฐ๋ง - ๊ฑฐ๋ฆฌ/์๋/ํ์ด์ค/์นผ๋ก๋ฆฌ ๊ณ์ฐ(
utils/geo.ts,utils/run.ts) - ์ฃผ๊ธฐ ์
๋ฐ์ดํธ(์ต์ 5์ด ๋๋ 50m ๋ณํ) ์ ์๋ฒ๋ก ์ ์ก(
utils/api/running.ts) - ์ธ์
์์ฑ: ์๋ฒ ๋ฏธ๊ตฌํ ์ ๋ก์ปฌ ์ธ์
(
local_โฆ)๋ก ๋์, ์ด์ ์ ์ ๊ฑฐ ์ฃผ์ ์์
- ๊ถํ ์์ฒญ/์ค๋น(
- ํ๋ฉด:
Pages/LiveRunningScreen.tsxuseLiveRunTracker์ํ/์ ์ด(start/pause/resume/stop) ๋ฐ์ธ๋ฉ
- ์ ํ๋ ์๊ณ์น:
accuracy > 60m์ํ ์ ์ธ - ์ต์ ์ด๋: ์ ํ๋ ๊ธฐ๋ฐ ํํ(์:
max(acc*0.5, 5m)) ๋ฏธ๋ง ์ด๋ ์ ์ธ - ์ ์(์ ์ง ๊ทผ์ฒ) ํ๋ค๋ฆผ:
speed < 0.6 m/s์์ ๋ ๊ฐํ ์ต์ ์ด๋ - ์๋ ์คํ์ดํฌ:
> 6.5 m/s๊ตฌ๊ฐ์ ๊ฑฐ๋ฆฌ ๋ฐ์ ์ ์ธ(๋ฌ๋ฆฌ๊ธฐ ํฉ๋ฆฌ ๋ฒ์) - ๊ฑฐ๋ฆฌ ๋ณด์ : ์ด์ /ํ์ฌ ์ ํ๋์ ํ๊ท 50%๋ฅผ ๋ ธ์ด์ฆ ํ์ฉ์น๋ก ์ฐจ๊ฐ ํ ๋ฐ์
- ์ฐ๋กํ:
UPDATE_MIN_MS=5000,UPDATE_MIN_KM=0.05๋ง์กฑ ์apiUpdate - ์ ์ก ํ์ด๋ก๋: ๋์ ๊ฑฐ๋ฆฌ(m), ๊ฒฝ๊ณผ(sec), ํ๊ท ํ์ด์ค(sec/km), ์นผ๋ก๋ฆฌ,
currentPoint{lat,lng,sequence,t} - ์๋ฃ ์ ์ก:
apiComplete์์routePoints์ํ์ฑ/ํ์์คํฌํ ๋ณด์ ,endedAtISO ํ์คํ
- ๋ฐฐํฐ๋ฆฌ: ์ ํ๋/์ฃผ๊ธฐ ์กฐ์ ์ผ๋ก ์๋ชจ ๊ด๋ฆฌ(์ ํ๋ High โ Balanced, distanceInterval/timeInterval)
- ๋ฐฑ๊ทธ๋ผ์ด๋: iOS
setActivityTypeAsync(Fitness)์ฌ์ฉ ์ ํํธ ์ ๊ณต, ์ค์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ์ฑ ์ ํ๋ก์ ํธ ์๊ตฌ์ ๋ง์ถฐ ํ ์คํธ ํ์ - ๊ถํ UX: ์ฌ์ ์๋ด/๊ฑฐ๋ถ ์ ๋์ฒด UX, ์ค์ ์ด๋ ์๋ด
- ๋ฐ์ดํฐ ์ผ๊ด์ฑ: ์ ๋ก๋ ์คํจ ์ ๋ก์ปฌ ํ/์ฌ์๋(ํ์ฌ๋ ์กฐ์ฉํ ๋ฌด์, ๊ฐ์ ์ฌ์ง)
- ์ธํฐ์ ํฐ ์ธ๋ํ: ๋ค์ํ ์๋ฒ ์๋ต ๋ํผ๋ฅผ ํก์ โ ๋ชจ๋ ์ฝ๋ ๋จ์, ํ ์คํธ ์ฉ์ด
- ์๋ฌ ๋ก๊น
:
[API ERR]์ํ/๋ฐ๋ ๋ก๊น , ํ์ ์ ์ฌ์ฉ์ ๋ฉ์์ง์ ๋ถ๋ฆฌ๋ ๋ด๋ถ ๋ก๊น ์ฒด๊ณ ๊ถ์ฅ - ํ์
๋คํ์ฑ ํก์:
auth.ts,running.ts๊ฐ ์ฌ๋ฌ ํค ํ๋ณด๋ฅผ ์์ ํ ๋งคํ(๋ง์ด๊ทธ๋ ์ด์ /์ค์จ๊ฑฐ ๋ถ์ผ์น ๋์) - ์ด๋ฏธ์ง ์
๋ก๋:
utils/api/feeds.ts- presign โ S3 PUT โ
download/public url์ฌ์ฉ(์ด์ ํ์ค ํจํด) FileSystem.uploadAsync๋ก Content-Type/Length ์ค์
- presign โ S3 PUT โ
- .env ๋น๊ณต๊ฐ: ํ์ฌ
.env์ ํค ๋ ธ์ถ๋จ โ ์ฆ์ ๋ ํฌ ์ ์ธ(.gitignore), ํค ๋กํ ์ด์ , EAS Secrets๋ก ์ด๊ด ๊ถ์ฅ - HTTPS ๊ณ ์ :
baseURL์ https, OK - ๊ถํ ์ ์ธ: ์์น ๊ถํ์ Expo๊ฐ ๊ด๋ฆฌํ์ง๋ง, ์ฑ์คํ ์ด ์ ์ถ ์ ํ๋ซํผ๋ณ ์ค๋ช ๋ฌธ๊ตฌ/๊ถํ ํญ๋ชฉ ์ฌ๊ฒ์ฆ ํ์
- ๋ฅ๋งํฌ/์คํด:
scheme: waytoearth์ ์ง, ์นด์นด์ค ์ค์ ๊ณผ ์ถฉ๋ ์๋์ง ํ์ธ
- ์ธ์ฆ
- Refresh ํ ํฐ ํ๋ฆ + 401 ์๋ ์ฌ๋ฐ๊ธ/์ฌ์๋
- ํ ํฐ ์ ์ฅ์ ๋ณด์ ๋ ๋ฒจ ์ํฅ(ํ์ ์ SecureStore)
- ํธ๋ํน ์์ ํ
- ์ ๋ก๋ ์คํจ ํ์/์ฌ์๋(๋ฐฑ์คํ), ์คํ๋ผ์ธ ์ผ๊ด ๋๊ธฐํ
- ๋ฐฐํฐ๋ฆฌ/์ ํ๋ ํ๋กํ์ผ ํ๋ฆฌ์ (์ ์ฝ/๊ท ํ/์ ๋ฐ)
- DX/๊ด์ธก์ฑ
- ์๋ฌ/์ด๋ฒคํธ ๋ก๊น ํ์คํ(Sentry), ์ฃผ์ ํผ๋(๋ก๊ทธ์ธ/์ธ์ ์์/์๋ฃ) ์งํํ
- Jest + RNTL ๊ธฐ๋ณธ ํ
์คํธ ์ถ๊ฐ(ํ
๋จ์:
useKakaoLogin,useLiveRunTracker)
- ์ฝ๋ ์ ๋
utils/api/weather.ts์callOrMock๋ฑ ๋ฏธ์ ์ ์ ํธ ๊ฒํ /์ ๋ฆฌ- NativeWind ๋์
๋ฒ์ ํ๋ ์
className์ผ๊ด ์ ์ฉ
- Kakao ๋ก๊ทธ์ธ ํ
:
hooks/useKakaoLogin.ts - ๋ก๊ทธ์ธ ํ๋ฉด:
Pages/Login.tsx - ์ธ์ฆ API:
utils/api/auth.ts, ํด๋ผ์ด์ธํธutils/api/client.ts - ๋ฌ๋ ํ
:
hooks/useLiveRunTracker.ts - ๋ฌ๋ API:
utils/api/running.ts - ๊ฑฐ๋ฆฌ/ํ์ด์ค ์ ํธ:
utils/geo.ts,utils/run.ts - Kakao ์ค์ :
app.config.js,app.plugin.js,eas.json
ํ์ ์ ์ ํญ๋ชฉ ์ค ์ํ๋ ๋ถ๋ถ์ ๋ ๊น๊ฒ ํ์ฅํด ๋๋ฆฌ๊ฒ ์ต๋๋ค.
์ข์ ์ง๋ฌธ์ด์์. โ์ธ์ธํ๊ฒโ๋ ๋ง์ง๋ง, ํ์ผ ๋จ์๊ฐ ์๋๋ผ โ์๋ ๋จ์(ํ๋์ ๋ ผ๋ฆฌ ๋ณํ)โ๋ก ์ชผ๊ฐ๋ ๊ฒ ๋ฒ ์คํธ์ ๋๋ค. ๊ฐ ์ปค๋ฐ์ ๋ค์์ ๋ง์กฑํ๋ฉด ์ข์์:
- ๋น๋/ํ ์คํธ๊ฐ ํต๊ณผํ๋ค.
- ํ๋์ ๋ชฉ์ ๋ง ๋ด๋๋ค(๊ธฐ๋ฅ ์ถ๊ฐ, ๋ฒ๊ทธ ์์ , ๋ฆฌํฉํฐ ๋ฑ).
- ์ปค๋ฐ ๋ฉ์์ง๋ง ์ฝ์ด๋ ์๋๊ฐ ๋ช ํํ๋ค.
- PR์์๋ ํ์์ ์ค์ฟผ์ ๊ฐ๋ฅํ์ง๋ง, ๋ก์ปฌ ํ์คํ ๋ฆฌ๋ ์๋ฏธ ์๊ฒ ๋จ๋๋ค.