Skip to content

feat: 앱 네이티브 SDK 소셜 로그인 기능 구현 (구글/카카오)#153

Merged
soyeong0115 merged 8 commits into
devfrom
feat/132-app-social-login
Jun 6, 2026
Merged

feat: 앱 네이티브 SDK 소셜 로그인 기능 구현 (구글/카카오)#153
soyeong0115 merged 8 commits into
devfrom
feat/132-app-social-login

Conversation

@soyeong0115

@soyeong0115 soyeong0115 commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

작업 요약

  • 앱(React Native)에서 카카오/구글 네이티브 SDK를 통한 소셜 로그인을 구현합니다

작업 세부 내용

@piki/core

  • REQUEST_SOCIAL_LOGIN, SOCIAL_LOGIN_SUCCESS, SOCIAL_LOGIN_ERROR WebBridge 메시지 타입 추가
  • SocialProviderT, 로그인 관련 payload 타입 정의 (types/login.ts)

apps/app

  • EAS Build 세팅 (eas.json — development/preview/production 프로파일)
  • app.json@react-native-kakao/core, @react-native-google-signin/google-signin 플러그인 설정
  • _layout.tsx — 앱 시작 시 카카오 SDK 초기화(initializeKakaoSDK), Google Sign-In 설정(GoogleSignin.configure)
  • hooks/useSocialLogin.ts — 네이티브 SDK 로그인 → JWT 발급 → 앱 저장 + 웹 전달
  • utils/tokenStorage.tsexpo-secure-store 기반 JWT 저장 (iOS Keychain / Android Keystore)
  • apis/postSocialLogin.ts — 백엔드 POST /auth/login/{provider} 호출
  • app/index.tsxREQUEST_SOCIAL_LOGIN 메시지 수신 시 useSocialLogin 실행
  • metro.config.js — pnpm 워크스페이스 심링크 해석 설정 추가
  • app.json — 번들 ID를 기존 팀 빌드와 동일한 day.no30s.piki로 통일
    (기존 com.piki.app은 다른 팀 계정에 등록되어 있어 개발 빌드에 사용 불가)

apps/web

  • LoginButtons.tsx — WebView 환경 감지 시 OAuth 리다이렉트 대신 WebBridge.postMessage(REQUEST_SOCIAL_LOGIN) 발송
  • hooks/useNativeLoginResult.ts — 앱으로부터 SOCIAL_LOGIN_SUCCESS 수신 → 쿠키 저장 → /home 이동
  • next.config.js — 실기기 테스트용 allowedDevOrigins 환경변수화 (NEXT_PUBLIC_DEV_ORIGIN)

로그인 플로우

웹 로그인 버튼 클릭 (WebView)
→ WebBridge: REQUEST_SOCIAL_LOGIN
→ 앱: 네이티브 SDK 로그인 (카카오앱 / 구글 팝업)
→ 앱: POST /auth/login/{provider} { accessToken }
→ 앱: expo-secure-store에 JWT 저장
→ WebBridge: SOCIAL_LOGIN_SUCCESS { accessToken, refreshToken }
→ 웹: 쿠키 저장 → /home 이동

이슈 및 해결

① pnpm 워크스페이스에서 Metro가 네이티브 모듈을 못 찾는 문제

  • pnpm은 심링크 기반으로 패키지를 관리하는데, Metro가 기본적으로 심링크를 따라가지 않아 @react-native-kakao/user 모듈을 찾지 못하는 오류 발생
  • metro.config.jsunstable_enableSymlinks: truenodeModulesPaths 명시로 해결

② Next.js 실기기 접속 시 JS 번들 차단 문제

  • 실기기가 LAN IP(192.168.219.120)로 웹 서버에 접근하면 Next.js 16이 cross-origin으로 판단해 /_next/webpack-hmr 리소스를 차단 → 버튼 클릭 불가
  • next.config.jsallowedDevOrigins에 LAN IP 허용으로 해결 (환경변수로 관리)

③ 카카오 SDK 초기화 누락

  • Expo 플러그인이 네이티브 초기화를 처리하지 못해 "The SDK is not initialized" 오류 발생
  • _layout.tsx에서 initializeKakaoSDK(appKey) 명시적 호출로 해결

④ 구글 accessToken 발급 방식

  • GoogleSignin.signIn()idToken을 그대로 전달했으나 백엔드가 거부
  • GoogleSignin.getTokens()accessToken을 별도 발급하여 전달하는 방식으로 해결

실기기 테스트 방법

  1. eas build --profile development --platform ios로 Custom Dev Client 빌드 및 기기 설치
  2. pnpm --filter piki-web dev로 웹 서버 실행 (NEXT_PUBLIC_DEV_ORIGIN={LAN IP} 설정 필요)
  3. apps/app/.envEXPO_PUBLIC_WEB_URL=http://{LAN IP}:3000, EXPO_PUBLIC_API_URL 설정
  4. npx expo start --dev-client로 앱 서버 실행 후 기기에서 접속
  5. 로그인 화면에서 카카오/구글 버튼으로 동작 확인

기능 작동 확인 영상

d1ddd7c8b05f4bdcb644ca8250037f20.mov

연관 이슈

closes #132

Summary by CodeRabbit

  • New Features

    • 카카오·구글 소셜 로그인 통합 및 앱↔웹 소셜 로그인 플로우 추가
    • 네이티브↔웹 간 토큰 동기화 및 WebView 연동 개선
    • 인증 토큰 안전 저장/관리 기능 추가
  • Chores

    • 앱 설정(iOS/Android) 및 빌드/배포 설정 추가·갱신
    • 소셜 로그인·쿠키 관련 의존성 및 번들 구성 개선
  • Refactor

    • 웹브리지 메시지 타입 확장 (소셜 로그인 이벤트 포함)

@vercel

vercel Bot commented Jun 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
depromeet Ready Ready Preview, Comment Jun 6, 2026 4:01pm

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

No description provided.

@github-actions
github-actions Bot requested review from iOdiO89 and ychany June 5, 2026 05:32
@github-actions github-actions Bot added APP Good for newcomers feature New feature or request WEB labels Jun 5, 2026
@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

앱과 웹 사이에 WebBridge 메시지 계약을 추가하고, Kakao/Google 네이티브 SDK로 로그인하여 백엔드에서 JWT를 교환·저장한 뒤 WebView에 쿠키를 동기화하고 웹에서 결과를 처리하는 전체 흐름을 구현합니다.

Changes

네이티브 소셜 로그인 통합 (WebBridge 기반)

Layer / File(s) Summary
WebBridge 소셜 로그인 메시지 계약
packages/core/src/consts/webBridge.ts, packages/core/src/types/login.ts, packages/core/src/types/webBridge.ts, packages/core/src/index.ts
REQUEST_SOCIAL_LOGIN, SOCIAL_LOGIN_SUCCESS, SOCIAL_LOGIN_ERROR 메시지 타입과 각 메시지의 payload 스키마(SocialProviderT, 토큰 구조)를 정의하고, WebBridgeMessageT 유니온에 통합합니다.
Kakao/Google 네이티브 SDK 설정 및 의존성
apps/app/app.json, apps/app/app/_layout.tsx, apps/app/package.json
Android/iOS 플러그인 및 권한을 app.json에 추가하고, _layout.tsx에서 initializeKakaoSDKGoogleSignin.configure를 호출하며 네이티브 패키지 의존성을 추가합니다.
앱 측 인증 인프라
apps/app/utils/tokenStorage.ts, apps/app/apis/postSocialLogin.ts
TokenStorage 유틸로 secure storage를 통해 access/refresh 토큰을 관리하고, postSocialLogin으로 백엔드와 소셜 액세스 토큰 교환을 수행합니다.
앱 측 로그인 흐름 및 WebView 통합
apps/app/hooks/useSocialLogin.ts, apps/app/hooks/useWebviewCookieSync.ts, apps/app/app/index.tsx
useSocialLogin 훅에서 네이티브 SDK로 access token을 획득하고 postSocialLogin을 호출해 JWT를 받아 저장한 뒤 WebBridge로 성공/오류 메시지를 전송합니다. useWebviewCookieSync는 WebView 대상에 쿠키를 사전 동기화하고, Page는 REQUEST_SOCIAL_LOGIN 메시지를 처리합니다.
웹 측 네이티브 로그인 감지 및 결과 처리
apps/web/src/app/login/_components/LoginButtons.tsx, apps/web/src/hooks/useNativeLoginResult.ts
웹에서 WebView 환경을 감지하면 REQUEST_SOCIAL_LOGIN을 전송하고, useNativeLoginResult는 앱에서 전송된 SOCIAL_LOGIN_SUCCESS/SOCIAL_LOGIN_ERROR를 받아 토큰을 쿠키에 저장하고 라우팅으로 이동합니다.
빌드 및 개발 환경 설정
apps/app/eas.json, apps/app/metro.config.js, apps/web/next.config.js
EAS 빌드 프로필을 추가하고 Metro 설정에서 워크스페이스 심링크를 지원하도록 하며, Next.js dev origin을 환경변수로 구성합니다.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • iOdiO89
  • ychany
  • kanghaeun

Poem

🐰 네이티브도 웹도 손잡고 뛰네
WebBridge로 속삭이며 토큰을 주네
Kakao·Google 한 번에 안아주고
쿠키 심어 WebView에 꿈을 주네
로그인 성공, 모두 함께 춤추네 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 주요 변경사항(네이티브 SDK 기반 소셜 로그인 구현)을 명확하게 요약하고 있습니다.
Linked Issues check ✅ Passed 모든 연관 이슈 #132의 체크리스트 항목들이 구현되었습니다. EAS 설정, 카카오/구글 SDK 설정, WebBridge 메시지 타입 추가, 앱/웹 측 로그인 흐름 구현이 완료되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 #132의 소셜 로그인 구현 범위 내에 있으며, Metro 심링크 설정과 allowedDevOrigins 환경변수 관리는 이 기능 구현에 필수적인 변경입니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/132-app-social-login

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (1)
apps/app/app/_layout.tsx (1)

6-15: 💤 Low value

SDK 초기화 실패에 대한 에러 핸들링을 추가하는 것을 고려해주세요.

현재 SDK 초기화가 실패하더라도 에러가 무시됩니다. 초기화 실패 시 사용자에게 명확한 피드백을 제공하거나 로깅하는 것이 좋습니다.

에러 핸들링 추가 예시
 // 카카오 네이티브 앱 키로 SDK 초기화 (앱 실행 시 1회)
-initializeKakaoSDK('326734abdf8de5c7e090a2fc72e1dce6');
+try {
+  initializeKakaoSDK('326734abdf8de5c7e090a2fc72e1dce6');
+} catch (error) {
+  console.error('Kakao SDK 초기화 실패:', error);
+}

 // Google Sign-In 설정
-GoogleSignin.configure({
-  iosClientId: '978975594396-mo5b39fe8fqfuukqkf42p63tlqkc4785.apps.googleusercontent.com',
-  webClientId: '978975594396-kgl5nei9occteirhlsk9mep9r65t83bn.apps.googleusercontent.com',
-});
+try {
+  GoogleSignin.configure({
+    iosClientId: '978975594396-mo5b39fe8fqfuukqkf42p63tlqkc4785.apps.googleusercontent.com',
+    webClientId: '978975594396-kgl5nei9occteirhlsk9mep9r65t83bn.apps.googleusercontent.com',
+  });
+} catch (error) {
+  console.error('Google Sign-In 설정 실패:', error);
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/app/app/_layout.tsx` around lines 6 - 15, Wrap the SDK initialization
calls in error handling: call initializeKakaoSDK(...) and
GoogleSignin.configure(...) inside try/catch blocks (or a single try/catch) and
on failure log the error (e.g., console.error or your app logger) and surface
user feedback (e.g., Alert.alert or a toast) so failures aren't silently
ignored; update the initialization location that currently calls
initializeKakaoSDK and GoogleSignin.configure to catch exceptions and handle
them accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/app/apis/postSocialLogin.ts`:
- Around line 7-10: Replace the locally redefined PostSocialLoginResponseT with
the shared type from `@piki/core`: import type { SocialLoginSuccessPayloadT } from
'`@piki/core`' and change the postSocialLogin function return type to
Promise<SocialLoginSuccessPayloadT>; remove the duplicate type declaration for
PostSocialLoginResponseT so only the imported SocialLoginSuccessPayloadT is used
across the file (update any references to PostSocialLoginResponseT accordingly).

In `@apps/app/app.json`:
- Around line 13-19: The iOS and Android bundle identifiers are inconsistent:
the iOS "bundleIdentifier" is "day.no30s.piki" while the Android "package" is
"com.piki.app"; confirm intended canonical identifier and update the Android
"package" or the iOS "bundleIdentifier" so both use the same reverse-domain
string (e.g., change "package" to "day.no30s.piki" or change "bundleIdentifier"
to match "com.piki.app"), and ensure any other config or native manifests use
the same identifier (search for "bundleIdentifier" and "package" to apply the
change).
- Around line 38-49: Replace the hardcoded keys by loading them from
environment/EAS secrets: remove the literal strings assigned to nativeAppKey and
iosUrlScheme in app.json and reference environment variables instead (e.g., via
expo config or app.config.js that reads process.env), then store the real values
as EAS secrets and map them in eas.json (KAKAO_NATIVE_APP_KEY,
GOOGLE_IOS_URL_SCHEME). Update the config that sets nativeAppKey and
iosUrlScheme to read process.env.KAKAO_NATIVE_APP_KEY and
process.env.GOOGLE_IOS_URL_SCHEME so the code uses the secrets at build/runtime
instead of the hardcoded values.

In `@apps/app/app/_layout.tsx`:
- Around line 6-15: The SDK keys are hardcoded in initializeKakaoSDK(...) and
GoogleSignin.configure(...); change these calls to read values from
environment/config (e.g., Expo app.json extra or a Constants module) instead of
literals: retrieve kakaoAppKey, googleIosClientId and googleWebClientId from
process.env or Constants.expoConfig.extra and pass those variables into
initializeKakaoSDK and GoogleSignin.configure so the secrets are not embedded in
the source and align with app.json extra.

In `@apps/app/app/index.tsx`:
- Line 48: The JSX currently passes source={isSynced ? { uri:
process.env.EXPO_PUBLIC_WEB_URL ?? 'http://localhost:3000' } : undefined}, which
violates the no-undefined rule; change it to use a conditional spread so the
source prop is only provided when isSynced is true (e.g. spread an object when
isSynced, otherwise spread nothing). Update the JSX around the source prop
(referencing the source prop, the isSynced variable, and
process.env.EXPO_PUBLIC_WEB_URL) to remove the undefined literal and
conditionally supply the prop via spread.

In `@apps/web/src/hooks/useNativeLoginResult.ts`:
- Line 23: The empty catch block in useNativeLoginResult (inside the try/catch
in the useNativeLoginResult hook) should include a brief explanatory comment
stating why errors are intentionally ignored (e.g., non-fatal race condition,
best-effort behavior, or fallback handled elsewhere); update the catch {} to
catch (err) { /* reason: ... */ } so the intent is clear and future maintainers
know this is deliberate rather than accidental.
- Around line 11-22: The handler for MessageEvent currently parses event.data
and accesses message.payload directly, risking saving "undefined" tokens; update
the handler to validate the parsed object with isWebBridgeMessageT (from
`@piki/core`) and confirm message.type ===
WEBBRIDGE_MESSAGE_TYPE.SOCIAL_LOGIN_SUCCESS and that payload.accessToken and
payload.refreshToken are present before calling setCookie('access_token', ...)
and setCookie('refresh_token', ...); if validation fails, treat it like
SOCIAL_LOGIN_ERROR (router.replace('/login')) or ignore the event to avoid
storing invalid tokens.

---

Nitpick comments:
In `@apps/app/app/_layout.tsx`:
- Around line 6-15: Wrap the SDK initialization calls in error handling: call
initializeKakaoSDK(...) and GoogleSignin.configure(...) inside try/catch blocks
(or a single try/catch) and on failure log the error (e.g., console.error or
your app logger) and surface user feedback (e.g., Alert.alert or a toast) so
failures aren't silently ignored; update the initialization location that
currently calls initializeKakaoSDK and GoogleSignin.configure to catch
exceptions and handle them accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bb12f968-0249-4619-a91a-40f7627354c1

📥 Commits

Reviewing files that changed from the base of the PR and between f1a0d6d and 36d8e68.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (17)
  • apps/app/apis/postSocialLogin.ts
  • apps/app/app.json
  • apps/app/app/_layout.tsx
  • apps/app/app/index.tsx
  • apps/app/eas.json
  • apps/app/hooks/useSocialLogin.ts
  • apps/app/hooks/useWebviewCookieSync.ts
  • apps/app/metro.config.js
  • apps/app/package.json
  • apps/app/utils/tokenStorage.ts
  • apps/web/next.config.js
  • apps/web/src/app/login/_components/LoginButtons.tsx
  • apps/web/src/hooks/useNativeLoginResult.ts
  • packages/core/src/consts/webBridge.ts
  • packages/core/src/index.ts
  • packages/core/src/types/login.ts
  • packages/core/src/types/webBridge.ts

Comment thread apps/app/apis/postSocialLogin.ts Outdated
Comment thread apps/app/app.json Outdated
Comment thread apps/app/app.json
Comment on lines +38 to +49
[
"@react-native-kakao/core",
{
"nativeAppKey": "326734abdf8de5c7e090a2fc72e1dce6"
}
],
[
"@react-native-google-signin/google-signin",
{
"iosUrlScheme": "com.googleusercontent.apps.978975594396-mo5b39fe8fqfuukqkf42p63tlqkc4785"
}
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

하드코딩된 API 키를 환경 변수 또는 EAS Secret으로 분리해주세요.

nativeAppKey(Line 41)와 iosUrlScheme(Line 47)가 하드코딩되어 있어 보안 위험이 있습니다. 이러한 값들은 Git 저장소에 노출되며, 공개 저장소일 경우 악용될 수 있습니다.

EAS Secret을 사용하거나 환경 변수로 주입하는 방식으로 변경해주세요.

🔐 EAS Secret을 사용한 수정 제안

eas.json에 secret 설정:

{
  "build": {
    "development": {
      "env": {
        "KAKAO_NATIVE_APP_KEY": "eas-secret:kakao-app-key",
        "GOOGLE_IOS_URL_SCHEME": "eas-secret:google-ios-url-scheme"
      }
    }
  }
}

app.json에서 환경 변수 참조:

 [
   "`@react-native-kakao/core`",
   {
-    "nativeAppKey": "326734abdf8de5c7e090a2fc72e1dce6"
+    "nativeAppKey": process.env.KAKAO_NATIVE_APP_KEY
   }
 ],
 [
   "`@react-native-google-signin/google-signin`",
   {
-    "iosUrlScheme": "com.googleusercontent.apps.978975594396-mo5b39fe8fqfuukqkf42p63tlqkc4785"
+    "iosUrlScheme": process.env.GOOGLE_IOS_URL_SCHEME
   }
 ]

Secret 등록:

eas secret:create --scope project --name kakao-app-key --value YOUR_KEY
eas secret:create --scope project --name google-ios-url-scheme --value YOUR_SCHEME
🧰 Tools
🪛 Betterleaks (1.3.1)

[high] 41-41: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/app/app.json` around lines 38 - 49, Replace the hardcoded keys by
loading them from environment/EAS secrets: remove the literal strings assigned
to nativeAppKey and iosUrlScheme in app.json and reference environment variables
instead (e.g., via expo config or app.config.js that reads process.env), then
store the real values as EAS secrets and map them in eas.json
(KAKAO_NATIVE_APP_KEY, GOOGLE_IOS_URL_SCHEME). Update the config that sets
nativeAppKey and iosUrlScheme to read process.env.KAKAO_NATIVE_APP_KEY and
process.env.GOOGLE_IOS_URL_SCHEME so the code uses the secrets at build/runtime
instead of the hardcoded values.

Comment thread apps/app/app/_layout.tsx Outdated
Comment thread apps/app/app/index.tsx Outdated
Comment thread apps/web/src/hooks/useNativeLoginResult.ts
Comment thread apps/web/src/hooks/useNativeLoginResult.ts Outdated
# Conflicts:
#	apps/app/app.json
#	apps/app/app/_layout.tsx
#	apps/app/app/index.tsx
#	apps/app/eas.json
#	apps/app/metro.config.js
#	apps/app/package.json
#	apps/web/next.config.js
#	packages/core/src/consts/webBridge.ts
#	packages/core/src/index.ts
#	packages/core/src/types/webBridge.ts
#	pnpm-lock.yaml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/app/apis/postSocialLogin.ts (1)

23-27: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

성공 응답의 토큰 payload를 검증하지 않아 undefined가 전파될 수 있습니다.

현재는 data.data를 그대로 반환하므로 응답 구조가 어긋나면 이후 저장/동기화 단계에서 잘못된 인증 상태를 만들 수 있습니다.

수정 제안
   const data = await response.json();
   if (!response.ok) throw new Error(data.detail ?? '로그인에 실패했습니다.');
 
-  return data.data;
+  const payload = data?.data;
+  if (!payload?.accessToken || !payload?.refreshToken) {
+    throw new Error('로그인 응답 형식이 올바르지 않습니다.');
+  }
+
+  return payload;
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/app/apis/postSocialLogin.ts` around lines 23 - 27, The function
postSocialLogin returns data.data without validating the token payload, which
can let undefined propagate; update postSocialLogin to validate the response
shape after parsing response.json() by checking that data.data exists and
contains required fields (e.g., accessToken, refreshToken, and any expiry/userId
fields your app expects), and throw a descriptive Error if those properties are
missing or malformed so callers never receive an undefined token object;
reference the response, data, and the current return data.data locations when
making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/app/apis/postSocialLogin.ts`:
- Around line 12-13: The code builds the social-login URL using
process.env.EXPO_PUBLIC_API_URL without validating it, causing immediate
failures when the env var is empty; update the logic in postSocialLogin (where
`${process.env.EXPO_PUBLIC_API_URL}/api/v1/auth/login/${provider}` is
constructed) to explicitly validate that process.env.EXPO_PUBLIC_API_URL is set
and non-empty before making the fetch—if missing, throw a clear error (or return
a rejected Promise) with a descriptive message like "EXPO_PUBLIC_API_URL is not
configured" so the failure is surfaced early and no network request is
attempted.

In `@apps/app/eas.json`:
- Around line 26-27: The production profile in eas.json is missing required
environment variables (EXPO_PUBLIC_API_URL, EXPO_PUBLIC_KAKAO_NATIVE_APP_KEY,
EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID, EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID) which are
used by the SDK init in apps/app/app/_layout.tsx and the login call in
apps/app/apis/postSocialLogin.ts; fix by adding those four keys with the same
values as your other profiles into the "production" object (or move them into a
common/shared profile that all three build profiles inherit from) so production
builds receive non-empty values for social login.

---

Outside diff comments:
In `@apps/app/apis/postSocialLogin.ts`:
- Around line 23-27: The function postSocialLogin returns data.data without
validating the token payload, which can let undefined propagate; update
postSocialLogin to validate the response shape after parsing response.json() by
checking that data.data exists and contains required fields (e.g., accessToken,
refreshToken, and any expiry/userId fields your app expects), and throw a
descriptive Error if those properties are missing or malformed so callers never
receive an undefined token object; reference the response, data, and the current
return data.data locations when making this change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 55856c19-0e93-4f69-a16c-21ad1e1757d7

📥 Commits

Reviewing files that changed from the base of the PR and between 36d8e68 and d7232e2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • apps/app/apis/postSocialLogin.ts
  • apps/app/app.json
  • apps/app/app/_layout.tsx
  • apps/app/app/index.tsx
  • apps/app/eas.json
  • apps/app/metro.config.js
  • apps/app/package.json
  • apps/web/next.config.js
  • apps/web/src/hooks/useNativeLoginResult.ts
  • packages/core/src/consts/webBridge.ts
  • packages/core/src/index.ts
  • packages/core/src/types/webBridge.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/core/src/index.ts
  • apps/app/package.json
  • packages/core/src/consts/webBridge.ts
  • packages/core/src/types/webBridge.ts
  • apps/app/app/_layout.tsx
  • apps/web/next.config.js
  • apps/app/metro.config.js
  • apps/app/app/index.tsx

Comment on lines +12 to +13
`${process.env.EXPO_PUBLIC_API_URL}/api/v1/auth/login/${provider}`,
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

API base URL 미설정 시 로그인 요청이 즉시 깨집니다.

환경 변수가 비어 있으면 잘못된 URL로 요청되어 소셜 로그인 경로 전체가 실패합니다. 요청 전에 명시적으로 검증해 설정 오류를 조기에 드러내는 게 안전합니다.

수정 제안
 export const postSocialLogin = async (
   provider: SocialProviderT,
   body: PostSocialLoginRequestT
 ): Promise<SocialLoginSuccessPayloadT> => {
+  const apiBaseUrl = process.env.EXPO_PUBLIC_API_URL;
+  if (!apiBaseUrl) {
+    throw new Error('EXPO_PUBLIC_API_URL이 설정되지 않았습니다.');
+  }
+
   const response = await fetch(
-    `${process.env.EXPO_PUBLIC_API_URL}/api/v1/auth/login/${provider}`,
+    `${apiBaseUrl}/api/v1/auth/login/${provider}`,
     {
       method: 'POST',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
`${process.env.EXPO_PUBLIC_API_URL}/api/v1/auth/login/${provider}`,
{
export const postSocialLogin = async (
provider: SocialProviderT,
body: PostSocialLoginRequestT
): Promise<SocialLoginSuccessPayloadT> => {
const apiBaseUrl = process.env.EXPO_PUBLIC_API_URL;
if (!apiBaseUrl) {
throw new Error('EXPO_PUBLIC_API_URL이 설정되지 않았습니다.');
}
const response = await fetch(
`${apiBaseUrl}/api/v1/auth/login/${provider}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
}
);
if (!response.ok) {
throw new Error('Failed to login');
}
return response.json();
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/app/apis/postSocialLogin.ts` around lines 12 - 13, The code builds the
social-login URL using process.env.EXPO_PUBLIC_API_URL without validating it,
causing immediate failures when the env var is empty; update the logic in
postSocialLogin (where
`${process.env.EXPO_PUBLIC_API_URL}/api/v1/auth/login/${provider}` is
constructed) to explicitly validate that process.env.EXPO_PUBLIC_API_URL is set
and non-empty before making the fetch—if missing, throw a clear error (or return
a rejected Promise) with a descriptive message like "EXPO_PUBLIC_API_URL is not
configured" so the failure is surfaced early and no network request is
attempted.

Comment thread apps/app/eas.json
Comment on lines 26 to 27
"production": {
"autoIncrement": true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

프로덕션 프로필에도 로그인 필수 env를 넣어 주세요.

Line 26의 production에는 EXPO_PUBLIC_API_URL,
EXPO_PUBLIC_KAKAO_NATIVE_APP_KEY, EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID,
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID가 빠져 있습니다. 이 값들은
apps/app/app/_layout.tsx:1-13의 SDK 초기화와
apps/app/apis/postSocialLogin.ts:3-27의 로그인 API 호출에 직접 쓰이므로,
현재 설정대로면 프로덕션 빌드에서 소셜 로그인이 빈 값/undefined로 깨집니다.
production.env를 추가하거나 공통 프로필로 승격해서 세 프로필이 같은 값을
상속받도록 맞춰 주세요.

수정 예시
   "production": {
+    "env": {
+      "EXPO_PUBLIC_API_URL": "https://api.depromeet18team3.cloud",
+      "EXPO_PUBLIC_KAKAO_NATIVE_APP_KEY": "326734abdf8de5c7e090a2fc72e1dce6",
+      "EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID": "978975594396-mo5b39fe8fqfuukqkf42p63tlqkc4785.apps.googleusercontent.com",
+      "EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID": "978975594396-kgl5nei9occteirhlsk9mep9r65t83bn.apps.googleusercontent.com"
+    },
     "autoIncrement": true
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"production": {
"autoIncrement": true
"production": {
"env": {
"EXPO_PUBLIC_API_URL": "https://api.depromeet18team3.cloud",
"EXPO_PUBLIC_KAKAO_NATIVE_APP_KEY": "326734abdf8de5c7e090a2fc72e1dce6",
"EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID": "978975594396-mo5b39fe8fqfuukqkf42p63tlqkc4785.apps.googleusercontent.com",
"EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID": "978975594396-kgl5nei9occteirhlsk9mep9r65t83bn.apps.googleusercontent.com"
},
"autoIncrement": true
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/app/eas.json` around lines 26 - 27, The production profile in eas.json
is missing required environment variables (EXPO_PUBLIC_API_URL,
EXPO_PUBLIC_KAKAO_NATIVE_APP_KEY, EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID,
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID) which are used by the SDK init in
apps/app/app/_layout.tsx and the login call in apps/app/apis/postSocialLogin.ts;
fix by adding those four keys with the same values as your other profiles into
the "production" object (or move them into a common/shared profile that all
three build profiles inherit from) so production builds receive non-empty values
for social login.

@soyeong0115
soyeong0115 merged commit d36ef34 into dev Jun 6, 2026
6 checks passed
@soyeong0115
soyeong0115 deleted the feat/132-app-social-login branch June 6, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

APP Good for newcomers feature New feature or request WEB

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 앱 네이티브 SDK 소셜 로그인 기능 구현

2 participants