Skip to content

기능추가 소셜로그인 구글 로그인#19

Open
thswogh wants to merge 2 commits intomainfrom
기능추가_소셜로그인_구글_로그인

Hidden character warning

The head ref may contain hidden characters: "\uae30\ub2a5\ucd94\uac00_\uc18c\uc15c\ub85c\uadf8\uc778_\uad6c\uae00_\ub85c\uadf8\uc778"
Open

기능추가 소셜로그인 구글 로그인#19
thswogh wants to merge 2 commits intomainfrom
기능추가_소셜로그인_구글_로그인

Conversation

@thswogh
Copy link
Contributor

@thswogh thswogh commented Jul 16, 2025

#8

Summary by CodeRabbit

  • 신규 기능

    • Google 및 Naver 소셜 로그인을 지원하는 버튼과 인증 플로우가 추가되었습니다.
    • Naver 로그인은 WebView를 통한 인증 및 사용자 정보 조회를 지원합니다.
    • Google 로그인을 위한 인증 세션 및 사용자 정보 연동 기능이 도입되었습니다.
  • 버그 수정

    • Google, Naver 인증 시 오류 발생 시 사용자에게 알림이 표시되고 적절한 예외 처리가 추가되었습니다.
  • 스타일

    • 소셜 로그인 버튼들의 디자인과 레이아웃이 개선되었습니다.
  • 환경설정

    • Google, Naver 인증을 위한 환경 변수와 관련 설정이 추가되었습니다.
  • 기타

    • Google 인증을 위한 외부 라이브러리(expo-web-browser)가 추가되었습니다.

@coderabbitai
Copy link

coderabbitai bot commented Jul 16, 2025

Walkthrough

이번 변경에서는 구글 및 네이버 소셜 로그인 기능이 추가되었습니다. 이를 위해 환경 변수, 인증 관련 API 모듈, UI 컴포넌트, WebView 기반 인증 플로우, 그리고 관련 의존성(expo-web-browser)이 도입 및 수정되었습니다. 기존 카카오 로그인 버튼의 상태 변수 네이밍도 일관성 있게 변경되었습니다.

Changes

파일/경로 변경 요약
.env 구글·네이버 OAuth용 클라이언트 ID, 시크릿, 리디렉션 URI 환경 변수 추가
package.json expo-web-browser 패키지(~14.0.2) 추가
app/index.tsx 인증 상태 기반 라우팅 로직 제거, 무조건 홈으로 100ms 후 이동하도록 변경
features/auth/api/googleAuth.ts 구글 OAuth 인증 및 사용자 정보 교환 API 신규 추가
features/auth/ui/GoogleLoginButton.tsx 구글 로그인 버튼에 비동기 인증, 로딩/에러 처리, UI 개선 반영
features/auth/ui/KakaoLoginButton.tsx WebView 모달 상태 변수명 showWebViewisShowWebView로 변경
features/auth/ui/NaverLoginButton.tsx 네이버 로그인 버튼에 WebView 모달, 인증 성공/실패 핸들러, 스타일 추가
features/auth/ui/NaverLoginWebView.tsx 네이버 OAuth 인증 WebView 컴포넌트 신규 추가, 토큰 교환 및 사용자 정보 조회, 에러 처리 구현

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant WebView/Browser
    participant Naver/Google OAuth
    participant Backend

    User->>App: 소셜 로그인 버튼 클릭
    App->>WebView/Browser: OAuth 인증 페이지 오픈
    User->>Naver/Google OAuth: 로그인 및 동의
    Naver/Google OAuth->>WebView/Browser: Redirect URI로 코드 전달
    WebView/Browser->>App: 인증 코드 전달
    App->>Backend: 인증 코드 전송 (POST)
    Backend->>Naver/Google OAuth: 토큰/유저정보 요청
    Naver/Google OAuth->>Backend: 토큰/유저정보 응답
    Backend->>App: 유저 정보 응답
    App->>User: 로그인 성공 처리
Loading

Poem

🥕
소셜 로그인, 토끼 춤을 춰요
구글·네이버 문 활짝 열렸죠
버튼 누르면 WebView가 반짝
인증 코드, 토큰 받아
토끼도 로그인 걱정 없네
오늘도 깡총, 로그인 OK!
🐇

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-07-16T12_49_38_373Z-debug-0.log

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (5)
features/auth/ui/NaverLoginButton.tsx (1)

7-7: 네이밍 일관성 개선 제안

KakaoLoginButton에서는 isShowWebView를 사용하는데, 여기서는 showWebView를 사용하고 있습니다. 일관성을 위해 동일한 네이밍 컨벤션을 사용하는 것이 좋습니다.

다음과 같이 수정하여 일관성을 맞추세요:

-  const [showWebView, setShowWebView] = useState(false);
+  const [isShowWebView, setIsShowWebView] = useState(false);

그리고 모든 참조를 업데이트하세요:

-    setShowWebView(true);
+    setIsShowWebView(true);
-    setShowWebView(false);
+    setIsShowWebView(false);
-  <Modal visible={showWebView} animationType="slide" presentationStyle="pageSheet">
+  <Modal visible={isShowWebView} animationType="slide" presentationStyle="pageSheet">
features/auth/ui/GoogleLoginButton.tsx (1)

18-25: 에러 처리 중복 개선 고려

현재 에러 발생 시 onLoginError 콜백 호출과 Alert.alert 표시를 모두 수행하고 있습니다. 이는 사용자에게 중복된 에러 메시지를 보여줄 수 있습니다.

다음과 같이 개선할 수 있습니다:

      } else {
        onLoginError(result.error || "구글 로그인 중 오류가 발생했습니다.");
-        Alert.alert("로그인 실패", result.error || "구글 로그인 중 오류가 발생했습니다.");
      }
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다.";
      onLoginError(errorMessage);
-      Alert.alert("로그인 실패", errorMessage);
    }

또는 에러 처리를 부모 컴포넌트에서 일관되게 처리하도록 구성할 수 있습니다.

features/auth/api/googleAuth.ts (2)

22-28: OAuth 스코프 하드코딩 개선 고려

OAuth 스코프가 하드코딩되어 있습니다. 향후 확장성을 고려하면 설정 가능하도록 개선할 수 있습니다.

+const DEFAULT_SCOPES = "profile email";
+
// OAuth URL
const authUrl =
  `https://accounts.google.com/o/oauth2/v2/auth?` +
  `client_id=${GOOGLE_CLIENT_ID}` +
  `&redirect_uri=${encodeURIComponent(GOOGLE_REDIRECT_URI)}` +
  `&response_type=code` +
- `&scope=${encodeURIComponent("profile email")}` +
+ `&scope=${encodeURIComponent(DEFAULT_SCOPES)}` +
  `&prompt=select_account`;

31-31: WebBrowser 세션 타임아웃 설정 고려

WebBrowser 세션에 타임아웃이 설정되어 있지 않아 사용자가 무한정 대기할 수 있습니다.

Expo WebBrowser는 기본적으로 타임아웃을 지원하지 않지만, Promise.race를 사용하여 구현할 수 있습니다:

+// 타임아웃 설정 (30초)
+const timeoutPromise = new Promise((_, reject) => {
+  setTimeout(() => reject(new Error("로그인 타임아웃")), 30000);
+});
+
// 기본 브라우저로 구글 로그인 페이지 열기
-const result = await WebBrowser.openAuthSessionAsync(authUrl, GOOGLE_REDIRECT_URI);
+const result = await Promise.race([
+  WebBrowser.openAuthSessionAsync(authUrl, GOOGLE_REDIRECT_URI),
+  timeoutPromise
+]);
features/auth/ui/NaverLoginWebView.tsx (1)

108-134: WebView 설정 최적화 고려

WebView에 많은 설정이 적용되어 있는데, 일부는 불필요할 수 있습니다.

OAuth 플로우에 필요한 최소한의 설정만 유지하는 것을 권장합니다:

      <WebView
        source={{ uri: authUrl }}
        onNavigationStateChange={handleNavigationChangeState}
        javaScriptEnabled={true}
        domStorageEnabled={true}
-        injectedJavaScript="window.ReactNativeWebView.postMessage('')"
-        startInLoadingState={false}
-        allowsBackForwardNavigationGestures={true}
-        allowsInlineMediaPlayback={true}
-        mediaPlaybackRequiresUserAction={false}
-        bounces={true}
-        scrollEnabled={true}
-        showsHorizontalScrollIndicator={false}
-        showsVerticalScrollIndicator={false}
-        decelerationRate="normal"
-        allowsFullscreenVideo={false}
-        allowsProtectedMedia={false}
-        dataDetectorTypes="none"
        {...(Platform.OS === "ios" && {
          allowsLinkPreview: false,
-          automaticallyAdjustContentInsets: false,
        })}
      />
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f8eaea and dd46b7e.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • .env (1 hunks)
  • app/index.tsx (1 hunks)
  • features/auth/api/googleAuth.ts (1 hunks)
  • features/auth/ui/GoogleLoginButton.tsx (1 hunks)
  • features/auth/ui/KakaoLoginButton.tsx (2 hunks)
  • features/auth/ui/NaverLoginButton.tsx (1 hunks)
  • features/auth/ui/NaverLoginWebView.tsx (1 hunks)
  • package.json (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
features/auth/ui/GoogleLoginButton.tsx (2)
features/auth/model/types.ts (1)
  • SocialLoginProps (9-12)
features/auth/api/googleAuth.ts (1)
  • handleGoogleSignIn (70-92)
🔇 Additional comments (6)
package.json (1)

35-35: 의존성 추가 승인

OAuth 인증 플로우를 지원하기 위한 expo-web-browser 의존성 추가가 적절합니다.

.env (1)

3-7: 보안 설정 검증 완료

.env 파일이 .gitignore에 포함되어 있어 커밋되지 않음을 확인했습니다.
민감한 OAuth 인증 정보는 계속해서 .env에 보관하시고, 배포 환경에서도 안전한 관리 정책을 유지해주세요.

features/auth/ui/KakaoLoginButton.tsx (1)

7-7: 네이밍 개선 승인

상태 변수명을 isShowWebView로 변경하여 boolean 값임을 명확히 하는 것이 좋은 개선입니다.

features/auth/ui/NaverLoginButton.tsx (1)

29-46: 네이버 로그인 구현 승인

모달 WebView를 사용한 네이버 로그인 구현이 잘 되어 있습니다. 적절한 에러 처리와 콜백 구조를 갖추고 있습니다.

features/auth/ui/GoogleLoginButton.tsx (2)

1-4: 임포트 및 의존성 확인 완료

필요한 React Native 컴포넌트들과 타입, API 함수를 적절히 임포트하고 있습니다.


32-42: UI 구현 및 로딩 상태 관리 우수

버튼의 로딩 상태에 따른 UI 변경 및 비활성화 처리가 잘 구현되어 있습니다. 사용자 경험을 고려한 좋은 구현입니다.

EXPO_PUBLIC_NAVER_CLIENT_ID=tCdEIPDTDBnfdVRdRgoO
EXPO_PUBLIC_NAVER_CLIENT_SECRET=IX3znje6Hl
EXPO_PUBLIC_NAVER_REDIRECT_URI=https://dailysnap.xyz/api/auth/naver
EXPO_PUBLIC_GOOGLE_CLIENT_ID=735338487068-kh9kfnrrus8fdmucfek7996ml15jiell.apps.googleusercontent.com.apps.googleusercontent.com
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Google 클라이언트 ID 수정 필요

Google 클라이언트 ID에 .apps.googleusercontent.com이 중복으로 포함되어 있습니다. 올바른 형식으로 수정해야 합니다.

다음과 같이 수정하세요:

-EXPO_PUBLIC_GOOGLE_CLIENT_ID=735338487068-kh9kfnrrus8fdmucfek7996ml15jiell.apps.googleusercontent.com.apps.googleusercontent.com
+EXPO_PUBLIC_GOOGLE_CLIENT_ID=735338487068-kh9kfnrrus8fdmucfek7996ml15jiell.apps.googleusercontent.com
📝 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
EXPO_PUBLIC_GOOGLE_CLIENT_ID=735338487068-kh9kfnrrus8fdmucfek7996ml15jiell.apps.googleusercontent.com.apps.googleusercontent.com
EXPO_PUBLIC_GOOGLE_CLIENT_ID=735338487068-kh9kfnrrus8fdmucfek7996ml15jiell.apps.googleusercontent.com
🤖 Prompt for AI Agents
In the .env file at line 6, the Google client ID contains a duplicated suffix
'.apps.googleusercontent.com'. Remove the extra '.apps.googleusercontent.com' so
that the client ID ends with a single '.apps.googleusercontent.com' to correct
the format.

Comment on lines +9 to +24
// const { userInfo } = useAuth();

useEffect(() => {
const timer = setTimeout(() => {
if (userInfo) {
// 로그인된 사용자면, 홈 네비게이션으로 이동
router.replace("/(tabs)/home");
} else {
// 로그인되지 않았으면 로그인 페이지로 이동
router.replace("/login");
}
router.replace("/(tabs)/home");
// if (userInfo) {
// // 로그인된 사용자면, 홈 네비게이션으로 이동
// router.replace("/(tabs)/home");
// } else {
// // 로그인되지 않았으면 로그인 페이지로 이동
// router.replace("/login");
// }
}, 100);

return () => clearTimeout(timer);
}, [userInfo, router]);
}, [router]);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

인증 우회에 대한 우려사항

사용자 인증 로직이 주석 처리되어 모든 사용자가 로그인 없이 홈으로 이동합니다. 이는 의도된 변경인지 확인이 필요합니다.

만약 개발 중 임시 변경이라면, 배포 전 반드시 인증 로직을 복원해야 합니다.

인증이 필요한 앱이라면 다음과 같이 복원하세요:

-  // const { userInfo } = useAuth();
+  const { userInfo } = useAuth();

-      router.replace("/(tabs)/home");
-      // if (userInfo) {
-      //   // 로그인된 사용자면, 홈 네비게이션으로 이동
-      //   router.replace("/(tabs)/home");
-      // } else {
-      //   // 로그인되지 않았으면 로그인 페이지로 이동
-      //   router.replace("/login");
-      // }
+      if (userInfo) {
+        // 로그인된 사용자면, 홈 네비게이션으로 이동
+        router.replace("/(tabs)/home");
+      } else {
+        // 로그인되지 않았으면 로그인 페이지로 이동
+        router.replace("/login");
+      }

-  }, [router]);
+  }, [router, userInfo]);
📝 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
// const { userInfo } = useAuth();
useEffect(() => {
const timer = setTimeout(() => {
if (userInfo) {
// 로그인된 사용자면, 홈 네비게이션으로 이동
router.replace("/(tabs)/home");
} else {
// 로그인되지 않았으면 로그인 페이지로 이동
router.replace("/login");
}
router.replace("/(tabs)/home");
// if (userInfo) {
// // 로그인된 사용자면, 홈 네비게이션으로 이동
// router.replace("/(tabs)/home");
// } else {
// // 로그인되지 않았으면 로그인 페이지로 이동
// router.replace("/login");
// }
}, 100);
return () => clearTimeout(timer);
}, [userInfo, router]);
}, [router]);
const { userInfo } = useAuth();
useEffect(() => {
const timer = setTimeout(() => {
if (userInfo) {
// 로그인된 사용자면, 홈 네비게이션으로 이동
router.replace("/(tabs)/home");
} else {
// 로그인되지 않았으면 로그인 페이지로 이동
router.replace("/login");
}
}, 100);
return () => clearTimeout(timer);
}, [router, userInfo]);
🤖 Prompt for AI Agents
In app/index.tsx between lines 9 and 24, the user authentication logic is
commented out, causing all users to be redirected to the home page without
login. To fix this, restore the authentication check by uncommenting the
userInfo usage and conditionally redirect users to the home page if logged in or
to the login page if not. Ensure this logic is active before deployment to
enforce proper authentication flow.

Comment on lines +4 to +6
const GOOGLE_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID ?? "";
const GOOGLE_REDIRECT_URI = process.env.EXPO_PUBLIC_GOOGLE_REDIRECT_URI ?? "";
const SERVER_BASE_URL = process.env.EXPO_PUBLIC_SERVER_BASE_URL ?? "";
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

환경변수 검증 추가 필요

환경변수들이 빈 문자열로 초기화되어 있지만, 실제 런타임에서 이 값들이 유효한지 검증하는 로직이 없습니다.

다음과 같이 환경변수 검증을 추가하는 것을 권장합니다:

const GOOGLE_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID ?? "";
const GOOGLE_REDIRECT_URI = process.env.EXPO_PUBLIC_GOOGLE_REDIRECT_URI ?? "";
const SERVER_BASE_URL = process.env.EXPO_PUBLIC_SERVER_BASE_URL ?? "";

+// 환경변수 검증
+if (!GOOGLE_CLIENT_ID || !GOOGLE_REDIRECT_URI || !SERVER_BASE_URL) {
+  throw new Error("구글 로그인에 필요한 환경변수가 설정되지 않았습니다.");
+}
📝 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
const GOOGLE_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID ?? "";
const GOOGLE_REDIRECT_URI = process.env.EXPO_PUBLIC_GOOGLE_REDIRECT_URI ?? "";
const SERVER_BASE_URL = process.env.EXPO_PUBLIC_SERVER_BASE_URL ?? "";
const GOOGLE_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID ?? "";
const GOOGLE_REDIRECT_URI = process.env.EXPO_PUBLIC_GOOGLE_REDIRECT_URI ?? "";
const SERVER_BASE_URL = process.env.EXPO_PUBLIC_SERVER_BASE_URL ?? "";
// 환경변수 검증
if (!GOOGLE_CLIENT_ID || !GOOGLE_REDIRECT_URI || !SERVER_BASE_URL) {
throw new Error("구글 로그인에 필요한 환경변수가 설정되지 않았습니다.");
}
🤖 Prompt for AI Agents
In features/auth/api/googleAuth.ts around lines 4 to 6, the environment
variables are assigned default empty strings without runtime validation. Add
validation logic after these assignments to check if any of the variables are
empty or invalid, and throw an error or handle the case appropriately to ensure
the app does not proceed with missing critical configuration.

Comment on lines +59 to +67
export async function exchangeGoogleCodeForUserInfo(code: string) {
try {
const response = await axios.post(`${SERVER_BASE_URL}/api/auth/google`, { code });
return response.data;
} catch (error) {
console.error("Google Token Exchange Error:", error);
throw error;
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

백엔드 API 에러 처리 개선 필요

현재 백엔드 API 호출에서 HTTP 상태 코드별 에러 처리가 부족합니다.

export async function exchangeGoogleCodeForUserInfo(code: string) {
  try {
    const response = await axios.post(`${SERVER_BASE_URL}/api/auth/google`, { code });
+    
+    if (response.status !== 200) {
+      throw new Error(`서버 응답 오류: ${response.status}`);
+    }
+    
    return response.data;
  } catch (error) {
    console.error("Google Token Exchange Error:", error);
+    
+    if (axios.isAxiosError(error)) {
+      if (error.response?.status === 401) {
+        throw new Error("인증에 실패했습니다.");
+      } else if (error.response?.status === 500) {
+        throw new Error("서버 오류가 발생했습니다.");
+      }
+    }
+    
    throw error;
  }
}
📝 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
export async function exchangeGoogleCodeForUserInfo(code: string) {
try {
const response = await axios.post(`${SERVER_BASE_URL}/api/auth/google`, { code });
return response.data;
} catch (error) {
console.error("Google Token Exchange Error:", error);
throw error;
}
}
export async function exchangeGoogleCodeForUserInfo(code: string) {
try {
const response = await axios.post(`${SERVER_BASE_URL}/api/auth/google`, { code });
if (response.status !== 200) {
throw new Error(`서버 응답 오류: ${response.status}`);
}
return response.data;
} catch (error) {
console.error("Google Token Exchange Error:", error);
if (axios.isAxiosError(error)) {
if (error.response?.status === 401) {
throw new Error("인증에 실패했습니다.");
} else if (error.response?.status === 500) {
throw new Error("서버 오류가 발생했습니다.");
}
}
throw error;
}
}
🤖 Prompt for AI Agents
In features/auth/api/googleAuth.ts around lines 59 to 67, the current error
handling for the backend API call does not differentiate based on HTTP status
codes. Improve error handling by checking the HTTP status code in the catch
block and handle different cases accordingly, such as logging specific messages
or throwing custom errors for different status codes to provide clearer feedback
on the failure reason.

Comment on lines +9 to +11
const NAVER_CLIENT_ID = process.env.EXPO_PUBLIC_NAVER_CLIENT_ID;
const NAVER_CLIENT_SECRET = process.env.EXPO_PUBLIC_NAVER_CLIENT_SECRET;
const NAVER_REDIRECT_URI = process.env.EXPO_PUBLIC_NAVER_REDIRECT_URI;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

환경변수 검증 및 타입 안전성 개선 필요

환경변수들이 undefined일 수 있지만 검증하지 않고 있으며, 이후 non-null assertion을 사용하고 있습니다.

const NAVER_CLIENT_ID = process.env.EXPO_PUBLIC_NAVER_CLIENT_ID;
const NAVER_CLIENT_SECRET = process.env.EXPO_PUBLIC_NAVER_CLIENT_SECRET;
const NAVER_REDIRECT_URI = process.env.EXPO_PUBLIC_NAVER_REDIRECT_URI;

+// 환경변수 검증
+if (!NAVER_CLIENT_ID || !NAVER_CLIENT_SECRET || !NAVER_REDIRECT_URI) {
+  throw new Error("네이버 로그인에 필요한 환경변수가 설정되지 않았습니다.");
+}
📝 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
const NAVER_CLIENT_ID = process.env.EXPO_PUBLIC_NAVER_CLIENT_ID;
const NAVER_CLIENT_SECRET = process.env.EXPO_PUBLIC_NAVER_CLIENT_SECRET;
const NAVER_REDIRECT_URI = process.env.EXPO_PUBLIC_NAVER_REDIRECT_URI;
const NAVER_CLIENT_ID = process.env.EXPO_PUBLIC_NAVER_CLIENT_ID;
const NAVER_CLIENT_SECRET = process.env.EXPO_PUBLIC_NAVER_CLIENT_SECRET;
const NAVER_REDIRECT_URI = process.env.EXPO_PUBLIC_NAVER_REDIRECT_URI;
// 환경변수 검증
if (!NAVER_CLIENT_ID || !NAVER_CLIENT_SECRET || !NAVER_REDIRECT_URI) {
throw new Error("네이버 로그인에 필요한 환경변수가 설정되지 않았습니다.");
}
🤖 Prompt for AI Agents
In features/auth/ui/NaverLoginWebView.tsx around lines 9 to 11, the environment
variables NAVER_CLIENT_ID, NAVER_CLIENT_SECRET, and NAVER_REDIRECT_URI are
assigned without validation and later used with non-null assertions, risking
runtime errors if they are undefined. Add explicit checks to verify these
variables are defined before use, and handle the case where they are missing by
throwing an error or providing fallback logic. This ensures type safety and
prevents runtime crashes due to undefined environment variables.

Comment on lines +13 to +17
interface NaverLoginWebViewProps {
onLoginSuccess: (userInfo: any) => void;
onLoginError: (error: any) => void;
onClose: () => void;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

타입 안전성 개선 필요

props의 타입 정의에서 any 타입을 사용하고 있어 타입 안전성이 부족합니다.

+interface NaverUserInfo {
+  id: string;
+  email: string;
+  name: string;
+  nickname: string;
+  profileImage: string;
+  accessToken: string;
+}

interface NaverLoginWebViewProps {
-  onLoginSuccess: (userInfo: any) => void;
-  onLoginError: (error: any) => void;
+  onLoginSuccess: (userInfo: NaverUserInfo) => void;
+  onLoginError: (error: Error) => void;
  onClose: () => void;
}
📝 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
interface NaverLoginWebViewProps {
onLoginSuccess: (userInfo: any) => void;
onLoginError: (error: any) => void;
onClose: () => void;
}
interface NaverUserInfo {
id: string;
email: string;
name: string;
nickname: string;
profileImage: string;
accessToken: string;
}
interface NaverLoginWebViewProps {
onLoginSuccess: (userInfo: NaverUserInfo) => void;
onLoginError: (error: Error) => void;
onClose: () => void;
}
🤖 Prompt for AI Agents
In features/auth/ui/NaverLoginWebView.tsx around lines 13 to 17, the props
interface uses 'any' types for onLoginSuccess and onLoginError parameters, which
reduces type safety. Replace 'any' with more specific types that accurately
represent the expected userInfo and error objects to improve type safety and
catch potential issues at compile time.

const [isChangeNavigate, setIsChangeNavigate] = useState(true);

// CSRF 방지를 위한 state 값 생성 (랜덤 문자열)
const STATE = Math.random().toString(36).substring(2, 15);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

보안 취약점: 약한 STATE 생성

CSRF 보호를 위한 STATE 값이 Math.random()으로 생성되어 보안상 취약합니다.

+import { randomBytes } from 'expo-crypto';

// CSRF 방지를 위한 state 값 생성 (랜덤 문자열)
-const STATE = Math.random().toString(36).substring(2, 15);
+const STATE = randomBytes(16).toString('hex');

또는 crypto가 없는 환경에서는:

-const STATE = Math.random().toString(36).substring(2, 15);
+const STATE = Date.now().toString(36) + Math.random().toString(36).substring(2);
📝 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
const STATE = Math.random().toString(36).substring(2, 15);
import { randomBytes } from 'expo-crypto';
// CSRF 방지를 위한 state 값 생성 (랜덤 문자열)
const STATE = randomBytes(16).toString('hex');
🤖 Prompt for AI Agents
In features/auth/ui/NaverLoginWebView.tsx at line 28, the STATE value for CSRF
protection is generated using Math.random(), which is insecure. Replace this
with a cryptographically secure random string generator, such as using the Web
Crypto API's crypto.getRandomValues() method, to create a strong, unpredictable
STATE value for better security.

},
data: new URLSearchParams({
grant_type: "authorization_code",
client_id: NAVER_CLIENT_ID!,
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Non-null assertion 제거 필요

환경변수가 검증되지 않은 상태에서 non-null assertion을 사용하고 있습니다.

환경변수 검증을 추가한 후:

          client_id: NAVER_CLIENT_ID!,
          client_secret: NAVER_CLIENT_SECRET!,

이를 다음과 같이 변경:

          client_id: NAVER_CLIENT_ID,
          client_secret: NAVER_CLIENT_SECRET,

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In features/auth/ui/NaverLoginWebView.tsx at line 44, remove the non-null
assertion operator (!) from NAVER_CLIENT_ID to avoid assuming the environment
variable is always defined. Instead, add validation logic before this line to
check if NAVER_CLIENT_ID is present and handle the case when it is missing, such
as throwing an error or providing a fallback, ensuring the code safely uses the
environment variable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant