Skip to content

Conversation

@ImHyungsuk
Copy link
Contributor

@ImHyungsuk ImHyungsuk commented Nov 21, 2025

๐Ÿ“Œ PR ์š”์•ฝ

๐ŸŒฑ ์ž‘์—…ํ•œ ๋‚ด์šฉ

  • ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ํด๋ฆฌ์–ด

๐ŸŒฑ PR ํฌ์ธํŠธ

  • ํ•˜๋‹ค ์ปจํ”Œ๋ฆญํŠธ ๋‚ฌ๋Š”๋ฐ ํ•ด๊ฒฐ ๋œ๋“ฏ?

๐Ÿ“ธ ์Šคํฌ๋ฆฐ์ƒท

์Šคํฌ๋ฆฐ์ƒท
ํŒŒ์ผ์ฒจ๋ถ€๋ฐ”๋žŒ

๐Ÿ“ฎ ๊ด€๋ จ ์ด์Šˆ

Summary by CodeRabbit

  • ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ

    • Google ๋กœ๊ทธ์ธ์ด ๊ธฐ์กด ๋กœ๊ทธ์ธ ์˜ต์…˜์— ์ถ”๊ฐ€๋˜์–ด Google๋กœ ๊ฐ„ํŽธ ๋กœ๊ทธ์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐœ์„ 

    • ํ”„๋กœํ•„ ํŽธ์ง‘ ํ™”๋ฉด์˜ ๋ ˆ์ด์•„์›ƒ ๊ฐ„๊ฒฉ์„ ์กฐ์ •ํ•˜์—ฌ UI ์ •๋ ฌ์ด ๊ฐœ์„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
    • ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ๋ ˆ์ด๋ธ”(์ถ”๊ฐ€๋œ ๋ฌธ์ž์—ด ๋ฆฌ์†Œ์Šค) ๋“ฑ UI ๋ฌธ๊ตฌ๊ฐ€ ํ™•์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์ž‘์—…

    • ๋ฆด๋ฆฌ์Šค/๋นŒ๋“œ ์„ค์ •๊ณผ ๋‚œ๋…ํ™” ๊ทœ์น™์ด ์—…๋ฐ์ดํŠธ๋˜์–ด Google ๋กœ๊ทธ์ธ ๊ด€๋ จ ์„ค์ •์ด ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

โœ๏ธ Tip: You can customize this high-level summary in your review settings.

@ImHyungsuk ImHyungsuk requested a review from a team November 21, 2025 07:37
@ImHyungsuk ImHyungsuk self-assigned this Nov 21, 2025
@ImHyungsuk ImHyungsuk added the ํ˜•์„ ๐Ÿง๐Ÿ€ ๊ทธ๋‚  ์ธ๋ฅ˜๋Š” ๋– ์˜ฌ๋ ธ๋‹ค . ์ง„๊ฒฉ์˜ ํ˜•์„์„œ์„œ์„œ์„ label Nov 21, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 21, 2025

Walkthrough

๊ตฌ๊ธ€ ์›น ํด๋ผ์ด์–ธํŠธ ID๋ฅผ ๋นŒ๋“œ ์„ค์ •์— ์ถ”๊ฐ€ํ•˜๊ณ , AndroidX CredentialManager ๊ธฐ๋ฐ˜์˜ GoogleLoginHelper์™€ OAuth UI/๋ทฐ๋ชจ๋ธ ํ™•์žฅ์„ ํ†ตํ•ด ๊ธฐ์กด ์นด์นด์˜ค ๋กœ๊ทธ์ธ์— ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ์„ ํ†ตํ•ฉํ–ˆ์Šต๋‹ˆ๋‹ค. ProGuard ๊ทœ์น™๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ๋„ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Changes

์‘์ง‘๋„ / ํŒŒ์ผ(๋“ค) ๋ณ€๊ฒฝ ์š”์•ฝ
๋นŒ๋“œ ์„ค์ • ๋ฐ ProGuard
app/proguard-rules.pro, build-logic/convention/.../BuildConfig.kt, gradle/libs.versions.toml
ProGuard ๊ทœ์น™ ์ถ”๊ฐ€( com.google.gson.TypeAdapter ๋ณด์กด, com.google.googlesignin.** ๋ณด์กด) ๋ฐ GOOGLE_WEB_CLIENT_ID ๋นŒ๋“œํ•„๋“œ, Google Identity/Credentials ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ„์ „/์˜์กด์„ฑ ์ถ”๊ฐ€.
๋นŒ๋“œ ํ•„๋“œ ๊ณต๊ธ‰์ž
core/common/.../BuildConfigFields.kt, core/buildconfig/.../BuildConfigFieldsProviderImpl.kt
BuildConfigFields์— googleWebClientId: String ํ•„๋“œ ์ถ”๊ฐ€ ๋ฐ ๊ณต๊ธ‰์ž ๊ตฌํ˜„์—์„œ ํ•ด๋‹น ๊ฐ’ ์ „๋‹ฌํ•˜๋„๋ก ์—…๋ฐ์ดํŠธ. (๊ณต๊ฐœ API ํ™•์žฅ)
OAuth ๊ธฐ๋Šฅ โ€” ๊ตฌํ˜„ ๋ฐ ์˜์กด์„ฑ
feature/oauth/build.gradle.kts, feature/oauth/.../GoogleLoginHelper.kt
Google Identity / Credentials ์˜์กด์„ฑ ์ถ”๊ฐ€ ๋ฐ CredentialManager๋ฅผ ์‚ฌ์šฉํ•œ GoogleLoginHelper ํด๋ž˜์Šค ์ถ”๊ฐ€(๊ตฌ๊ธ€ ID ํ† ํฐ ํš๋“).
OAuth ๊ณ„์•ฝ ๋ฐ ๋ทฐ๋ชจ๋ธ
feature/oauth/.../OauthContract.kt, feature/oauth/.../OauthViewModel.kt
OauthIntent์— GoogleLoginClick, GoogleLoginSuccess, GoogleLoginFailure ์ถ”๊ฐ€ ๋ฐ StartGoogleLogin ์‚ฌ์ด๋“œ์ดํŽ™ํŠธ ์ฒ˜๋ฆฌ ๋กœ์ง/ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€. ๋ทฐ๋ชจ๋ธ์—์„œ ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ๋ถ„๊ธฐ ์ถ”๊ฐ€.
OAuth UI ๋ฐ ๋ ˆ์ด์•„์›ƒ
feature/oauth/.../OauthScreen.kt, feature/mypage/.../ProfileEditScreen.kt
OauthScreen ์‹œ๊ทธ๋‹ˆ์ฒ˜์— googleLoginClick ์ฝœ๋ฐฑ ์ถ”๊ฐ€ ๋ฐ UI์—์„œ ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ์—ฐ๊ฒฐ. ProfileEditScreen์˜ Spacer๋“ค weight โ†’ ๊ณ ์ • ๋†’์ด๋กœ ๋ณ€๊ฒฝ.
๋ฆฌ์†Œ์Šค
feature/oauth/.../strings.xml
apple_login ๋ฌธ์ž์—ด ๋ฆฌ์†Œ์Šค ์ถ”๊ฐ€.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant OauthScreen
    participant OauthViewModel
    participant GoogleLoginHelper
    participant CredentialManager
    participant Backend

    User->>OauthScreen: ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ํด๋ฆญ
    OauthScreen->>OauthViewModel: GoogleLoginClick ๋ฐœ์†ก
    OauthViewModel->>OauthScreen: StartGoogleLogin ์‚ฌ์ด๋“œ์ดํŽ™ํŠธ (๋˜๋Š” ์ด๋ฒคํŠธ)
    OauthScreen->>GoogleLoginHelper: requestGoogleLogin(onSuccess,onFailure)
    GoogleLoginHelper->>CredentialManager: GetCredentialRequest (webClientId ํฌํ•จ)
    CredentialManager->>User: ๊ตฌ๊ธ€ ๊ณ„์ • ์„ ํƒ UI ํ‘œ์‹œ
    User->>CredentialManager: ๊ณ„์ • ์„ ํƒ
    CredentialManager->>GoogleLoginHelper: GoogleIdTokenCredential ๋ฐ˜ํ™˜
    GoogleLoginHelper->>OauthScreen: onSuccess(idToken)
    OauthScreen->>OauthViewModel: GoogleLoginSuccess(provider="GOOGLE", accessToken=idToken)
    OauthViewModel->>Backend: postSocialLogin(provider, accessToken)
    Backend->>OauthViewModel: JWT ์‘๋‹ต
    OauthViewModel->>OauthViewModel: SaveJwtToken ์ฒ˜๋ฆฌ
Loading

Estimated code review effort

๐ŸŽฏ 3 (Moderate) | โฑ๏ธ ~20 ๋ถ„

Possibly related PRs

  • [Feature/#3] kakao login sdkย #4 โ€” BuildConfigFields ๋ฐ ๊ณต๊ธ‰์ž ๋ณ€๊ฒฝ๊ณผ ๊ฒน์น˜๋Š” ๋ณ€๊ฒฝ(๋นŒ๋“œ ํ•„๋“œ ์ถ”๊ฐ€/์กฐ์ •).

Suggested labels

์‹œํ˜„๐Ÿฅ๐ŸŸ

Suggested reviewers

  • leeseokchan00

์ „์ฒด ์„ค๋ช…

๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ๊ธ€ ์›น ํด๋ผ์ด์–ธํŠธ ID๋ฅผ ๋นŒ๋“œ ์„ค์ •์— ์ถ”๊ฐ€ํ•˜๊ณ , AndroidX CredentialManager๋ฅผ ํ™œ์šฉํ•œ GoogleLoginHelper ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ๊ตฌ๊ธ€ ์ธ์ฆ ํ† ํฐ์„ ํš๋“ํ•ฉ๋‹ˆ๋‹ค. OAuth ํ™”๋ฉด๊ณผ ๋ทฐ๋ชจ๋ธ์„ ํ™•์žฅํ•ด ๊ธฐ์กด ์นด์นด์˜ค ๋กœ๊ทธ์ธ๊ณผ ํ•จ๊ป˜ ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ํ๋ฆ„์„ ํ†ตํ•ฉํ•ฉ๋‹ˆ๋‹ค.

๋ณ€๊ฒฝ์‚ฌํ•ญ

์‘์ง‘๋„ / ํŒŒ์ผ(๋“ค) ๋ณ€๊ฒฝ ์š”์•ฝ
๋นŒ๋“œ ์„ค์ • ๋ฐ ProGuard
app/proguard-rules.pro, build-logic/convention/.../BuildConfig.kt, gradle/libs.versions.toml
GSON TypeAdapter์™€ Google Sign-In ๊ด€๋ จ ํด๋ž˜์Šค ์œ ์ง€๋ฅผ ์œ„ํ•œ ProGuard ๊ทœ์น™ ์ถ”๊ฐ€. Google Web Client ID๋ฅผ ๋นŒ๋“œ ์„ค์ •์— ์ถ”๊ฐ€. Google Identity ๋ฐ Credentials ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ„์ „ ๋ฐ ์˜์กด์„ฑ ์ •์˜.
๋นŒ๋“œ ์„ค์ • ํ•„๋“œ ํ™•์žฅ
core/common/.../BuildConfigFields.kt, core/buildconfig/.../BuildConfigFieldsProviderImpl.kt
BuildConfigFields ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค์— googleWebClientId ํ•„๋“œ ์ถ”๊ฐ€ ๋ฐ ๊ณต๊ธ‰์ž ๊ตฌํ˜„ ์—…๋ฐ์ดํŠธ.
๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ๊ตฌํ˜„
feature/oauth/build.gradle.kts, feature/oauth/.../GoogleLoginHelper.kt
Google Credentials ์˜์กด์„ฑ ์ถ”๊ฐ€. CredentialManager๋ฅผ ํ™œ์šฉํ•œ GoogleLoginHelper ํด๋ž˜์Šค ๊ตฌํ˜„์œผ๋กœ Google ID ํ† ํฐ ํš๋“ ๊ธฐ๋Šฅ ์ œ๊ณต.
OAuth ๊ณ„์•ฝ ๋ฐ ํ๋ฆ„
feature/oauth/.../OauthContract.kt, feature/oauth/.../OauthViewModel.kt
GoogleLoginClick, GoogleLoginSuccess, GoogleLoginFailure ์ธํ…ํŠธ์™€ StartGoogleLogin ์‚ฌ์ด๋“œ์ดํŽ™ํŠธ ์ถ”๊ฐ€. ๋ทฐ๋ชจ๋ธ์—์„œ ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ.
OAuth UI
feature/oauth/.../OauthScreen.kt, feature/mypage/.../ProfileEditScreen.kt
OauthScreen์— googleLoginClick ์ฝœ๋ฐฑ ์ถ”๊ฐ€ํ•˜๊ณ  ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ์—ฐ๊ฒฐ. ProfileEditScreen์˜ Spacer ๋ ˆ์ด์•„์›ƒ ์กฐ์ • (๊ณ ์ • ๋†’์ด๊ฐ’ ์ ์šฉ).
๋ฆฌ์†Œ์Šค
feature/oauth/.../strings.xml
apple_login ๋ฌธ์ž์—ด ๋ฆฌ์†Œ์Šค ์ถ”๊ฐ€.

์‹œํ€€์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

sequenceDiagram
    actor User
    participant OauthScreen
    participant OauthViewModel
    participant GoogleLoginHelper
    participant CredentialManager
    participant Backend
    
    User->>OauthScreen: ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ํด๋ฆญ
    OauthScreen->>OauthViewModel: GoogleLoginClick ๋ฐœ์†ก
    OauthViewModel->>OauthViewModel: StartGoogleLogin ์‚ฌ์ด๋“œ์ดํŽ™ํŠธ ์ƒ์„ฑ
    OauthScreen->>GoogleLoginHelper: requestGoogleLogin ํ˜ธ์ถœ
    GoogleLoginHelper->>CredentialManager: ์ž๊ฒฉ์ฆ๋ช… ์š”์ฒญ
    CredentialManager->>User: ๊ตฌ๊ธ€ ๊ณ„์ • ์„ ํƒ UI
    User->>CredentialManager: ๊ณ„์ • ์„ ํƒ
    CredentialManager->>GoogleLoginHelper: GoogleIdTokenCredential ๋ฐ˜ํ™˜
    GoogleLoginHelper->>OauthScreen: onSuccess (ID ํ† ํฐ)
    OauthScreen->>OauthViewModel: GoogleLoginSuccess ๋ฐœ์†ก
    OauthViewModel->>Backend: postSocialLogin (provider="GOOGLE", accessToken)
    Backend->>OauthViewModel: JWT ํ† ํฐ ๋ฐ˜ํ™˜
    OauthViewModel->>OauthViewModel: SaveJwtToken ๋ฐœ์†ก
Loading

์ฝ”๋“œ ๋ฆฌ๋ทฐ ์˜ˆ์ƒ ๋…ธ๋ ฅ

๐ŸŽฏ 3 (Moderate) | โฑ๏ธ ~20 ๋ถ„

  • ํŠน๋ณ„ ์ฃผ์˜ ์‚ฌํ•ญ:
    • GoogleLoginHelper.kt: CredentialManager API ์‚ฌ์šฉ๋ฒ• ๋ฐ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋กœ์ง ๊ฒ€์ฆ ํ•„์š”
    • OauthViewModel.kt: GoogleLoginSuccess์™€ ๊ธฐ์กด postSocialLogin ํ๋ฆ„์˜ ํ†ตํ•ฉ ์ผ๊ด€์„ฑ ํ™•์ธ
    • BuildConfigFields.kt ๋ฐ ๊ด€๋ จ ๊ณต๊ธ‰์ž: ์ƒˆ ํ•„๋“œ์˜ ๋ชจ๋“  ํ˜ธ์ถœ ์‚ฌ์ดํŠธ์—์„œ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”์ง€ ํ™•์ธ
    • ProGuard ๊ทœ์น™์˜ ์ ์ ˆ์„ฑ ๋ฐ ๋Ÿฐํƒ€์ž„ ๋ฐ˜์˜ ๊ฒ€์ฆ

๊ด€๋ จ PR ๊ฐ€๋Šฅ์„ฑ

  • [Feature/#3] kakao login sdkย #4: BuildConfigFields ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์™€ ๊ณต๊ธ‰์ž ์ˆ˜์ •์ด ๊ฒน์นœ๋‹ค (์ƒˆ๋กœ์šด ํ•„๋“œ ์ถ”๊ฐ€ ๋ฐ BuildConfigFieldsProviderImpl ์—…๋ฐ์ดํŠธ).

์ œ์•ˆ ๋ผ๋ฒจ

์‹œํ˜„๐Ÿฅ๐ŸŸ

์ œ์•ˆ ๊ฒ€ํ† ์ž

  • leeseokchan00

์‹œ

๐Ÿฐ ๊ตฌ๊ธ€ ํ† ํฐ ํ๋‹น, ์ž๊ฒฉ์ฆ๋ช…์— ๋›ฐ์–ด๋“ค๊ณ 
์ž‘์€ ๋ฐœ๋กœ ํด๋ฆญํ•˜๋ฉด ID๊ฐ€ ๋„์ฐฉํ•ด์š”
์นด์นด์˜ค์™€ ์†์žก๊ณ  OAuth ์ถค์„ ์ถ”๋‹ˆ
๋กœ๊ทธ์ธ ๊ธธ์ด ๋” ๋ฐ˜์ง๋ฐ˜์งํ•˜๋„ค โœจ

๐Ÿšฅ Pre-merge checks | โœ… 3 | โŒ 2
โŒ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check โš ๏ธ Warning ProfileEditScreen.kt์˜ ๋ ˆ์ด์•„์›ƒ ๊ฐ„๊ฒฉ ์ˆ˜์ •์€ Google ๋กœ๊ทธ์ธ ๊ตฌํ˜„๊ณผ ๋ฌด๊ด€ํ•œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ProfileEditScreen.kt์˜ Spacer ์ˆ˜์ •์‚ฌํ•ญ์„ ๋ณ„๋„์˜ PR๋กœ ๋ถ„๋ฆฌํ•˜๊ฑฐ๋‚˜ ํ•ด๋‹น ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ด PR์—์„œ ์ œ๊ฑฐํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
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 (3 passed)
Check name Status Explanation
Description Check โœ… Passed Check skipped - CodeRabbitโ€™s high-level summary is enabled.
Title check โœ… Passed PR ์ œ๋ชฉ์€ ํ’€ ๋ฆฌํ€˜์ŠคํŠธ์˜ ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ธ Google ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ์š”์•ฝํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
Linked Issues check โœ… Passed ์—ฐ๊ฒฐ๋œ ์ด์Šˆ #155๋Š” Google ๋กœ๊ทธ์ธ ๊ตฌํ˜„์— ๋Œ€ํ•œ ๊ธฐ๋Šฅ ์š”์ฒญ์ด๋ฉฐ, PR์˜ ๋ชจ๋“  ์ฝ”๋“œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ด๋ฅผ ์ถฉ์กฑํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

โœ๏ธ Tip: You can configure your own custom pre-merge checks in the settings.

โœจ 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

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

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: 9

โ™ป๏ธ Duplicate comments (2)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt (2)

140-140: ๋™์ผํ•œ ์ด์Šˆ: ๊ณ ์ • ๋†’์ด Spacer ๊ฒ€์ฆ ํ•„์š”

Line 129์™€ ๋™์ผํ•˜๊ฒŒ, ์ด Spacer๋„ weight ๊ธฐ๋ฐ˜์—์„œ ๊ณ ์ • ๋†’์ด(32.dp)๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


168-168: ๋™์ผํ•œ ์ด์Šˆ: ๊ณ ์ • ๋†’์ด Spacer ๊ฒ€์ฆ ํ•„์š”

Line 129, 140๊ณผ ๋™์ผํ•˜๊ฒŒ, ์ด Spacer๋„ weight ๊ธฐ๋ฐ˜์—์„œ ๊ณ ์ • ๋†’์ด(24.dp)๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿงน Nitpick comments (4)
feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthViewModel.kt (1)

56-76: ๋””๋ฒ„๊ทธ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ๊ฐœ์„ ํ•˜์„ธ์š”.

Line 73์˜ ๋กœ๊ทธ ํƒœ๊ทธ "asdasdasd"๋Š” ์˜๋ฏธ ์—†๋Š” ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. ๋””๋ฒ„๊น… ์‹œ ๋กœ๊ทธ๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐœ์„ ํ•˜์„ธ์š”:

         }.onFailure {
-            Log.d("asdasdasd", it.toString())
+            Log.e("OauthViewModel", "Social login failed: ${it.message}", it)
         }
feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt (1)

50-50: GoogleLoginHelper์˜ ์ƒ๋ช…์ฃผ๊ธฐ ๊ด€๋ฆฌ๋ฅผ ๊ณ ๋ คํ•ด๋ณด์„ธ์š”.

GoogleLoginHelper๊ฐ€ remember๋กœ ์ƒ์„ฑ๋˜์ง€๋งŒ ๋ช…์‹œ์ ์ธ ์ •๋ฆฌ ๋กœ์ง์ด ์—†์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ๋Š” ํฐ ๋ฌธ์ œ๊ฐ€ ์—†์–ด ๋ณด์ด์ง€๋งŒ, ํ–ฅํ›„ ๋ฆฌ์†Œ์Šค ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•˜์—ฌ DisposableEffect๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด๋ณด์„ธ์š”.

์˜ˆ์‹œ:

val googleLoginHelper = remember { GoogleLoginHelper(context = context) }
DisposableEffect(Unit) {
    onDispose {
        // Clean up if needed in the future
    }
}
feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt (2)

25-25: ์ฃผ์„ ์ฒ˜๋ฆฌ๋œ ์ฝ”๋“œ๋ฅผ ์ •๋ฆฌํ•˜์„ธ์š”.

์—ฌ๋Ÿฌ ๊ณณ์— ์ฃผ์„ ์ฒ˜๋ฆฌ๋œ ์ฝ”๋“œ(SERVER_URL, nonce, ๋กœ๊ทธ ๋“ฑ)๊ฐ€ ๋‚จ์•„์žˆ์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ์ฝ”๋“œ๋Š” ํ™œ์„ฑํ™”ํ•˜๊ณ , ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ๋Š” ์ œ๊ฑฐํ•˜์—ฌ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ด๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

  • Line 25: SERVER_URL์ด ํ•„์š”ํ•˜๋‹ค๋ฉด ํ™œ์„ฑํ™”ํ•˜๊ณ , ์•„๋‹ˆ๋ฉด ์ œ๊ฑฐ
  • Lines 69-71: ๋””๋ฒ„๊ทธ ๋กœ๊ทธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด BuildConfig.DEBUG๋กœ ์กฐ๊ฑด๋ถ€ ํ™œ์„ฑํ™”
  • Lines 74, 77, 83: ์—๋Ÿฌ ๋กœ๊ทธ๋Š” ํ™œ์„ฑํ™” ๊ถŒ์žฅ

Also applies to: 33-33, 69-71, 74-74, 77-77, 83-83


24-24: BuildConfig๋ฅผ ์ง์ ‘ ์ฐธ์กฐํ•˜๋Š” ๋Œ€์‹  ์ฃผ์ž…๋ฐ›๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด๋ณด์„ธ์š”.

ํ˜„์žฌ WEB_CLIENT_ID๋ฅผ companion object์—์„œ BuildConfig๋ฅผ ์ง์ ‘ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ๊ณผ ์˜์กด์„ฑ ๋ช…์‹œ๋ฅผ ์œ„ํ•ด ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ฃผ์ž…๋ฐ›๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด๋ณด์„ธ์š”.

์˜ˆ์‹œ:

class GoogleLoginHelper(
    private val context: Context,
    private val webClientId: String = com.teamsolply.solply.buildconfig.BuildConfig.GOOGLE_WEB_CLIENT_ID
) {
    // ...
    private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
        .setServerClientId(webClientId)
        // ...
}
๐Ÿ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between db6473b and a3a96c3.

๐Ÿ“’ Files selected for processing (12)
  • app/proguard-rules.pro (1 hunks)
  • build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt (1 hunks)
  • core/buildconfig/src/main/java/com/teamsolply/solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt (2 hunks)
  • core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt (1 hunks)
  • feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt (3 hunks)
  • feature/oauth/build.gradle.kts (2 hunks)
  • feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt (1 hunks)
  • feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthContract.kt (2 hunks)
  • feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt (4 hunks)
  • feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthViewModel.kt (1 hunks)
  • feature/oauth/src/main/res/values/strings.xml (1 hunks)
  • gradle/libs.versions.toml (2 hunks)
๐Ÿงฐ Additional context used
๐Ÿงฌ Code graph analysis (1)
feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthViewModel.kt (4)
core/ui/src/main/java/com/teamsolply/solply/ui/base/BaseViewModel.kt (1)
  • postSideEffect (48-52)
remote/oauth/src/main/java/com/teamsolply/solply/oauth/service/OauthService.kt (2)
  • postSocialLogin (10-16)
  • postSocialLogin (11-15)
data/oauth/src/main/java/com/teamsolply/solply/oauth/repository/OauthRepositoryImpl.kt (1)
  • postSocialLogin (13-27)
domain/oauth/src/main/java/com/teamsolply/solply/oauth/repository/OauthRepository.kt (2)
  • postSocialLogin (5-8)
  • postSocialLogin (6-6)
๐Ÿช› detekt (1.23.8)
feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt

[warning] 73-73: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

๐Ÿ”‡ Additional comments (8)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt (1)

129-130: ๊ณ ์ • ๋†’์ด๋กœ ๋ณ€๊ฒฝ๋œ Spacer์˜ ๋ฐ˜์‘ํ˜• ๋™์ž‘์„ ํ™•์ธํ•˜์„ธ์š”.

์ด Spacer๊ฐ€ weight ๊ธฐ๋ฐ˜์—์„œ ๊ณ ์ • ๋†’์ด(16.dp)๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ณ ์ • ๋†’์ด๋Š” ๋‹ค์–‘ํ•œ ํ™”๋ฉด ํฌ๊ธฐ์—์„œ ์œ ์—ฐํ•˜๊ฒŒ ๋Œ€์‘ํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ์ž‘์€ ํ™”๋ฉด์—์„œ๋Š” ๋ ˆ์ด์•„์›ƒ์ด ์ž˜๋ฆฌ๊ฑฐ๋‚˜ ์˜๋„ํ•˜์ง€ ์•Š์€ ์Šคํฌ๋กค์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์–‘ํ•œ ํ™”๋ฉด ํฌ๊ธฐ(ํŠนํžˆ ์ž‘์€ ๊ธฐ๊ธฐ)์—์„œ UI๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ‘œ์‹œ๋˜๋Š”์ง€ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

feature/oauth/build.gradle.kts (1)

1-17: LGTM! Google Sign-In ์˜์กด์„ฑ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Google Sign-In ํ†ตํ•ฉ์— ํ•„์š”ํ•œ Credential Manager API ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค(google.id, credentials, credentials.play.auth)๊ณผ BuildConfig ์ ‘๊ทผ์„ ์œ„ํ•œ ์˜์กด์„ฑ์ด ์ ์ ˆํ•˜๊ฒŒ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

feature/oauth/src/main/res/values/strings.xml (1)

5-5: PR ๋ชฉํ‘œ์™€์˜ ๋ถˆ์ผ์น˜ ํ™•์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ด PR์˜ ๋ชฉํ‘œ๋Š” ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ๊ตฌํ˜„์ธ๋ฐ, apple_login ๋ฌธ์ž์—ด ๋ฆฌ์†Œ์Šค๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Apple ๋กœ๊ทธ์ธ์ด ์ด๋ฒˆ PR์˜ ๋ฒ”์œ„์— ํฌํ•จ๋˜๋Š” ๊ฒƒ์ด ๋งž๋Š”์ง€ ํ™•์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthContract.kt (2)

15-17: LGTM! Google ๋กœ๊ทธ์ธ Intent๊ฐ€ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด Kakao ๋กœ๊ทธ์ธ ํŒจํ„ด์„ ๋”ฐ๋ผ Google ๋กœ๊ทธ์ธ Intent๋“ค์ด ์ ์ ˆํ•˜๊ฒŒ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Click -> Success/Failure ํ๋ฆ„์ด ๋ช…ํ™•ํ•ฉ๋‹ˆ๋‹ค.


27-27: LGTM! Google ๋กœ๊ทธ์ธ SideEffect๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Kakao ๋กœ๊ทธ์ธ๊ณผ ๋™์ผํ•œ ํŒจํ„ด์œผ๋กœ StartGoogleLogin SideEffect๊ฐ€ ์ถ”๊ฐ€๋˜์–ด ์ผ๊ด€์„ฑ์ด ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.

core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt (1)

6-6: LGTM! BuildConfig ํ•„๋“œ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

googleWebClientId ํ•„๋“œ๊ฐ€ data class์— ์ ์ ˆํ•˜๊ฒŒ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt (1)

37-41: ํ•„๋“œ ์ด๋ฆ„์˜ ์˜คํƒ€๋ฅผ ์ˆ˜์ •ํ•˜์„ธ์š”.

BuildConfig ํ•„๋“œ ์ด๋ฆ„์— ์˜คํƒ€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค: GOOGLe_WEB_CLIENT_ID์˜ e๊ฐ€ ์†Œ๋ฌธ์ž์ž…๋‹ˆ๋‹ค. GOOGLE_WEB_CLIENT_ID๋กœ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ diff๋ฅผ ์ ์šฉํ•˜์„ธ์š”:

         buildConfigField(
             "String",
-            "GOOGLE_WEB_CLIENT_ID",
+            "GOOGLE_WEB_CLIENT_ID",
             gradleLocalProperties(rootDir, providers).getProperty("google.web.client.id")
         )

Likely an incorrect or invalid review comment.

core/buildconfig/src/main/java/com/teamsolply/solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt (1)

4-4: LGTM! Google Web Client ID๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

BuildConfig์—์„œ GOOGLE_WEB_CLIENT_ID๋ฅผ ๊ฐ€์ ธ์™€ BuildConfigFields์— ์ •์ƒ์ ์œผ๋กœ ์ „๋‹ฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Also applies to: 18-18

Comment on lines +23 to +24
-keep class * extends com.google.gson.TypeAdapter
-keep class com.google.googlesignin.** { *; }
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸก Minor

๐Ÿงฉ Analysis chain

ProGuard ๊ทœ์น™์ด ์ง€๋‚˜์น˜๊ฒŒ ๊ด‘๋ฒ”์œ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ ๊ทœ์น™์ด ๋งค์šฐ ๋„“์€ ๋ฒ”์œ„๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค:

  • * extends TypeAdapter: ๋ชจ๋“  TypeAdapter ์„œ๋ธŒํด๋ž˜์Šค ์œ ์ง€
  • com.google.googlesignin.** { *; }: ๋ชจ๋“  Google Sign-In ํด๋ž˜์Šค์™€ ๋ฉค๋ฒ„ ์œ ์ง€

์ด๋Š” ๋‚œ๋…ํ™”๋ฅผ ๋ฐฉํ•ดํ•˜๊ณ  APK ํฌ๊ธฐ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Google Sign-In Credential Manager API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๋” ๊ตฌ์ฒด์ ์ธ ๊ทœ์น™์œผ๋กœ ์ถฉ๋ถ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์Šคํฌ๋ฆฝํŠธ๋กœ ์‹ค์ œ ์‚ฌ์šฉ๋˜๋Š” Google Sign-In ํด๋ž˜์Šค๋ฅผ ํ™•์ธํ•˜์„ธ์š”:


๐Ÿ Script executed:

#!/bin/bash
# Google Sign-In ๊ด€๋ จ import ๋ฐ ์‚ฌ์šฉ ํ™•์ธ
rg -nP --type=kotlin -C3 'import.*google\.android\.gms\.auth|import.*googleid' feature/oauth/

Length of output: 1223


๐Ÿ Script executed:

#!/bin/bash
# Search for actual usage of com.google.googlesignin package
rg -nP --type=kotlin --type=java 'com\.google\.googlesignin' .

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Search for Gson TypeAdapter usage
rg -nP --type=kotlin --type=java 'TypeAdapter' .

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check if Credential Manager classes appear in ProGuard rules already
cat app/proguard-rules.pro

Length of output: 847



๐Ÿ Script executed:

#!/bin/bash
# Check build.gradle for dependencies
fd -e gradle | head -20

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Search build files for google-signin or gson dependencies
rg -nP 'google.*signin|gson' build.gradle

Length of output: 52


๐Ÿ Script executed:

#!/bin/bash
# Search for any Credential Manager ProGuard rules or missing rules
rg -nP 'credentials|credential' app/proguard-rules.pro

Length of output: 0


์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ProGuard ๊ทœ์น™์„ ์ œ๊ฑฐํ•˜์„ธ์š”.

๊ฒ€์ฆ ๊ฒฐ๊ณผ, ์ฝ”๋“œ๋ฒ ์ด์Šค ์–ด๋””์—์„œ๋„ ๋‹ค์Œ์ด ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค:

  • com.google.googlesignin ํŒจํ‚ค์ง€ (๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ: 0๊ฑด)
  • TypeAdapter ํด๋ž˜์Šค (๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ: 0๊ฑด)

ํ˜„์žฌ ๊ตฌํ˜„์€ com.google.android.libraries.identity.googleid (Credential Manager API)๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ผ์ธ 23-24์˜ ๊ทœ์น™์€ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ ˆ๊ฑฐ์‹œ Google Sign-In SDK ๊ด€๋ จ ๊ทœ์น™์ž…๋‹ˆ๋‹ค.

์ด ๊ทœ์น™๋“ค์„ ์ œ๊ฑฐํ•˜๋ฉด APK ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ณ  ์ ์ ˆํ•œ ๋‚œ๋…ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค:

-keep class * extends com.google.gson.TypeAdapter
-keep class com.google.googlesignin.** { *; }
๐Ÿค– Prompt for AI Agents
In app/proguard-rules.pro around lines 23 to 24, remove the two unused legacy
ProGuard rules for Google Sign-In and Gson TypeAdapter (the lines keeping
com.google.googlesignin.** and classes extending com.google.gson.TypeAdapter);
delete those two lines, run a clean build to confirm no missing symbol or
runtime obfuscation issues, and if build/tests pass, commit the updated proguard
file.

Comment on lines +29 to +34
private val nonce = UUID.randomUUID().toString()
private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setServerClientId(WEB_CLIENT_ID) // ์›น ํด๋ผ์ด์–ธํŠธ ID
.setFilterByAuthorizedAccounts(false)
// .setNonce(nonce)
.build()
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major

๐Ÿงฉ Analysis chain

Nonce ์‚ฌ์šฉ์ด ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค.

Line 33์—์„œ setNonce(nonce)๊ฐ€ ์ฃผ์„ ์ฒ˜๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. Nonce๋Š” ์žฌ์ƒ ๊ณต๊ฒฉ(replay attack)์„ ๋ฐฉ์ง€ํ•˜๋Š” ์ค‘์š”ํ•œ ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค. ํŠน๋ณ„ํ•œ ์ด์œ ๊ฐ€ ์—†๋‹ค๋ฉด ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

Nonce๋ฅผ ํ™œ์„ฑํ™”ํ•˜์„ธ์š”:

     private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
         .setServerClientId(WEB_CLIENT_ID) // ์›น ํด๋ผ์ด์–ธํŠธ ID
         .setFilterByAuthorizedAccounts(false)
-//        .setNonce(nonce)
+        .setNonce(nonce)
         .build()

์„œ๋ฒ„ ์ธก์—์„œ๋„ ์ด nonce๋ฅผ ๊ฒ€์ฆํ•˜๋„๋ก ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


์ด ๋ฆฌ๋ทฐ ์ฝ”๋ฉ˜ํŠธ๋ฅผ ๊ฒ€์ฆํ•˜๊ธฐ ์œ„ํ•ด ์ €์žฅ์†Œ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค.


๐Ÿ Script executed:

#!/bin/bash
# Search for the GoogleLoginHelper file and examine its content
find . -name "GoogleLoginHelper.kt" -type f 2>/dev/null | head -5

Length of output: 78


๐Ÿ Script executed:

#!/bin/bash
# Search for GetGoogleIdOption imports and usage patterns
rg -n "GetGoogleIdOption" --type kotlin -B3 -A3

Length of output: 1907


๐Ÿ Script executed:

#!/bin/bash
# Search for nonce-related code and comments in the OAuth module
rg -n "nonce" --type kotlin -i -B2 -A2

Length of output: 1167


๐Ÿ Script executed:

#!/bin/bash
# Search for server-side validation of nonce
rg -n "nonce" --type java --type kotlin -B2 -A2

Length of output: 1167


๐Ÿ Script executed:

#!/bin/bash
# Check for build.gradle or pom.xml to identify Google Sign-In library version
find . -name "build.gradle*" -o -name "pom.xml" | xargs grep -l "google\|gms" 2>/dev/null | head -5

Length of output: 96


๐Ÿ Script executed:

#!/bin/bash
# Search for any comments or documentation explaining why nonce was commented out
rg -n "replay\|setNonce" --type kotlin --type java -B5 -A5

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Look for server-side token validation logic
rg -n "verify|validate" --type kotlin --type java -i | grep -i "token\|nonce\|jwt\|google" | head -10

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check Google Play Services dependency version
find . -name "build.gradle*" | xargs cat 2>/dev/null | grep -A2 -B2 "play.*services.*auth"

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Search for any authentication verification controller or service
fd -e "\.kt$" -e "\.java$" | xargs grep -l "GoogleIdToken\|idToken\|verify" | head -10

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Look at the full GoogleLoginHelper.kt file
find . -name "GoogleLoginHelper.kt" -type f 2>/dev/null -exec cat {} \;

Length of output: 3518


๐Ÿ Script executed:

#!/bin/bash
# Search for server endpoint that might validate Google tokens
rg -n "google.*token\|id.*token" --type kotlin --type java -i | head -15

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check if there's documentation or configuration about security settings
find . -name "*.md" -o -name "*.txt" | xargs grep -l "nonce\|security" 2>/dev/null | head -5

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Search for any existing issue tracker references or TODOs related to nonce
rg -n "TODO|FIXME|XXX" --type kotlin | grep -i "nonce\|security\|replay"

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Look for Google Sign-In implementation details
rg -n "credentialResponse\|credential" --type kotlin -B3 -A3 | head -30

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check for any security-related tests or validation logic
fd -e "Test.kt" -e "Test.java" | xargs grep -l "nonce\|GoogleLogin" 2>/dev/null

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Look for the server-side implementation that receives the token
rg -n "id_token\|idToken" --type kotlin --type java | head -15

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Search for GoogleIdTokenVerifier or similar verification
rg -n "Verifier\|Verify" --type java --type kotlin | grep -i google

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check application properties or configuration for security settings
find . -name "application*.yml" -o -name "application*.properties" | xargs cat 2>/dev/null | grep -i nonce

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Look at git history to see if nonce was commented intentionally
git log --oneline feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt 2>/dev/null | head -10

Length of output: 104


๐Ÿ Script executed:

#!/bin/bash
# Check for any existing nonce validation on the backend
rg -n "setNonce\|getNonce\|validateNonce" --type java --type kotlin

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Look for any comments or documentation files
find . -path "*oauth*" -name "*.md" -o -path "*oauth*" -name "README*" 2>/dev/null

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Get broader context about the OAuth implementation
find . -path "*oauth*" -type f \( -name "*.kt" -o -name "*.java" \) | head -20

Length of output: 1603


๐Ÿ Script executed:

#!/bin/bash
# Check for ID token validation on server
rg -n "verify.*IdToken\|validateIdToken" --type java --type kotlin

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Search for Google API client library usage
rg -n "GoogleIdTokenVerifier\|TokenVerifier" --type java

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check if there's any exception handling related to nonce
rg -n "NonceException\|InvalidNonce" --type java --type kotlin

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Look for the complete token exchange process
rg -n "exchange\|credential.*token" --type kotlin -B2 -A2 | head -30

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Search for server endpoint path that handles token verification
rg -n "@PostMapping\|@GetMapping\|@PutMapping" --type kotlin | grep -i "token\|auth\|google\|login"

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check if nonce is being used elsewhere in the codebase
find . -type f \( -name "*.kt" -o -name "*.java" \) -exec grep -l "nonce" {} \;

Length of output: 78


๐Ÿ Script executed:

#!/bin/bash
# Look for documentation on Google Sign-In requirements
find . -name "*.md" -o -name "*.txt" -o -name "*.adoc" 2>/dev/null | xargs grep -l "Google\|OAuth\|Sign-In" 2>/dev/null | head -5

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check for any vulnerability scanning or security audit files
find . -name "*.json" -o -name "*.yaml" | xargs grep -l "security\|vulnerability\|nonce" 2>/dev/null | head -5

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Get imports from GoogleLoginHelper to understand the library version
rg -n "^import" feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt 2>/dev/null || rg -n "^import" . --type kotlin | grep -i google | head -10

Length of output: 709


๐Ÿ Script executed:

#!/bin/bash
# Check the Google Sign-In Android library documentation reference
cat build.gradle.kts 2>/dev/null || cat build.gradle 2>/dev/null || find . -name "build.gradle*" -type f | head -1 | xargs cat

Length of output: 637


๐Ÿ Script executed:

#!/bin/bash
# Look for any recent commit messages about nonce
git log --all --grep="nonce" --oneline 2>/dev/null || echo "No git history available"

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Final check: get the exact structure of the GoogleLoginHelper.kt file around the nonce area
find . -name "GoogleLoginHelper.kt" -type f 2>/dev/null -exec head -50 {} \;

Length of output: 1954


๐Ÿ Script executed:

#!/bin/bash
# Look for server-side Google token verification configuration
find . -name "*.properties" -o -name "*.yml" -o -name "*.yaml" 2>/dev/null | xargs grep -i "google\|client.*id\|secret" 2>/dev/null | head -15

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check for Spring Security or other security framework configuration
rg -n "@EnableWebSecurity\|@Configuration\|securityFilterChain" --type java -B2 -A10 | head -40

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Search for JWT or token parsing logic
rg -n "JwtDecoder\|verifyIdToken\|parseToken" --type java -B2 -A5

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Look for Google client library initialization
rg -n "GoogleCredential\|GoogleAuthorizationCodeFlow\|GoogleClientSecrets" --type java

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check if nonce validation happens in a filter or interceptor
rg -n "OncePerRequestFilter\|HandlerInterceptor" --type java -B2 -A10

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Get comprehensive view of OAuth module structure
find feature/oauth -type f 2>/dev/null | head -30

Length of output: 525


๐Ÿ Script executed:

#!/bin/bash
# Look at documentation or SECURITY.md files
find . -iname "*security*" -type f 2>/dev/null | head -10

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check for any architecture decision records or ADRs
find . -iname "*adr*" -o -iname "*decision*" -type f 2>/dev/null | head -10

Length of output: 94


๐Ÿ Script executed:

#!/bin/bash
# Final comprehensive search for nonce implementation
rg -rn "nonce" --type-list 2>/dev/null | head -5
rg -rn "nonce" . 2>/dev/null | head -20

Length of output: 229


๐Ÿ Script executed:

#!/bin/bash
# Check if setNonce is available in the GetGoogleIdOption API
rg -n "GetGoogleIdOption" . --type kotlin -A20 2>/dev/null | head -40

Length of output: 4825


๐Ÿ Script executed:

#!/bin/bash
# Look for version constraints or documentation
cat README.md 2>/dev/null | grep -i "google\|oauth\|security" || echo "No README or no matches"

Length of output: 71


๐Ÿ Script executed:

#!/bin/bash
# Check all files in the OAuth feature module
ls -la feature/oauth/ 2>/dev/null || find . -path "*oauth*" -type d | head -5

Length of output: 289


๐Ÿ Script executed:

#!/bin/bash
# Last attempt - find the exact file and show context
find . -name "GoogleLoginHelper.kt" 2>/dev/null -exec echo "=== File: {} ===" \; -exec cat {} \;

Length of output: 3611


๐Ÿ Script executed:

#!/bin/bash
# Check for Google Play Services version in dependencies
rg -n "com\.google\.android\.gms" . --type kotlin --type java | head -10

Length of output: 306


๐Ÿ Script executed:

#!/bin/bash
# Look for version strings
rg -n "gms:play-services.*auth" . | head -5

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Check if there's a docs folder
find . -type d -name "docs" -o -type d -name "documentation" 2>/dev/null

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Search for any CHANGELOG or release notes
find . -iname "CHANGELOG*" -o -iname "RELEASE*" 2>/dev/null | xargs grep -i nonce 2>/dev/null

Length of output: 0


๐Ÿ Script executed:

#!/bin/bash
# Verify the exact lines mentioned in the review
sed -n '29,34p' feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt 2>/dev/null || echo "File path may differ"

Length of output: 278


๐ŸŒ Web query:

Google Identity Services GetGoogleIdOption setNonce method API documentation

๐Ÿ’ก Result:

setNonce is a method on GetGoogleIdOption.Builder that sets the nonce used when generating a Google ID token. Use it when you build GetGoogleIdOption to have the ID token include the provided nonce.

Example (Kotlin):
val googleIdOption = GetGoogleIdOption.Builder()
.setServerClientId(WEB_CLIENT_ID)
.setNonce(nonce)
.build()

Docs: GetGoogleIdOption.Builder (method: setNonce). [1][2]

Sources
[1] GetGoogleIdOption.Builder โ€” Google Developers reference.
[2] Authenticate users with Sign in with Google (Android) โ€” example showing setNonce.


๐ŸŒ Web query:

androidx.credentials GetGoogleIdOption.Builder setNonce API

๐Ÿ’ก Result:

Yes โ€” GetGoogleIdOption.Builder has a setNonce(...) method. It accepts a String nonce and sets the nonce used when generating the Google ID token.

Signatures / usage examples:

  • Kotlin: .setNonce(nonce: String?) on GetGoogleIdOption.Builder. [1]
  • Java: public @nonnull GetGoogleIdOption.Builder setNonce(String nonce). [2]

Example (Kotlin):
val googleIdOption = GetGoogleIdOption.Builder()
.setServerClientId(WEB_CLIENT_ID)
.setNonce(nonce)
.build()

Sources:
[1] Android Developers โ€” Credential Manager: GetGoogleIdOption.Builder (example).
[2] Google Developers reference โ€” GetGoogleIdOption.Builder API.


๐ŸŒ Web query:

Google Sign-In nonce replay attack prevention Android 2024 2025

๐Ÿ’ก Result:

Short answer โ€” use Googleโ€™s nonce support + server-side single-use verification and device attestation:

Key points and recommended implementation

  • Include a cryptographically strong nonce in each Android Signโ€‘in with Google request (setNonce / setNonce(nonce)). This nonce is intended to prevent replay attacks. [1][2][3]
  • Generate the nonce serverโ€‘side or in the app using a CSPRNG (unpredictable), encode URLโ€‘safe Base64, and meet provider rules (recommend โ‰ฅ16 bytes). Treat each nonce as singleโ€‘use. Store/hash it serverโ€‘side and mark consumed when an ID token/response is accepted. Reject reused or expired nonces. [2][4]
  • Verify the ID token on your backend: verify signature, aud/client_id, exp/iat, and that the token contains the same nonce you issued. Only accept tokens whose nonce matches a currently valid, unused nonce. [1][3]
  • Optionally harden highโ€‘value flows by combining nonce with a request hash or a serverโ€‘issued unique value and using Play Integrity / SafetyNet attestation (nonce field) to bind the response to the specific request and detect tampering. Check and verify attestation tokens serverโ€‘side. [4][5]
  • For OAuth code flows, also use PKCE on top of the above; for OIDC ID tokens rely on the nonce claim to prevent replay. [3]

Quick checklist

  1. Generate CSPRNG nonce (server or app), URLโ€‘safe Base64, โ‰ฅ16 bytes. [4]
  2. Call setNonce(...) when building the Google signโ€‘in request on Android. [1][2][6]
  3. Exchange/receive ID token on server; verify signature, aud, exp, iat, and nonce == stored value. Mark nonce used. [1][3]
  4. Consider Play Integrity / SafetyNet attestation and request-specific hashes for extra protection. [4][5]

Sources
[1] Google Identity Android docs โ€” BeginSignInRequest / GetSignInIntentRequest nonce docs.
[2] Android Developer: Authenticate users with Sign in with Google (nonce guidance).
[3] Google Signโ€‘in / OpenID Connect guidance (ID token verification / nonce role).
[4] Play Integrity and SafetyNet docs โ€” using nonce to prevent replay/tampering.
[5] Google Signโ€‘in Security bundle / claims (auth_time and additional trust signals).


Nonce ํ™œ์„ฑํ™” ๋ฐ ์„œ๋ฒ„ ์ธก ๊ฒ€์ฆ ๊ตฌํ˜„ ํ•„์š”

ํด๋ผ์ด์–ธํŠธ: GetGoogleIdOption.Builder์˜ setNonce() ๋ฉ”์„œ๋“œ๊ฐ€ Google ๊ณต์‹ API์—์„œ ์ง€์›๋˜๋ฉฐ, nonce๋Š” ์žฌ์ƒ ๊ณต๊ฒฉ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ ํ‘œ์ค€ ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ nonce๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ์œผ๋‚˜(29์ค„) ์ฃผ์„ ์ฒ˜๋ฆฌ๋˜์–ด ์‚ฌ์šฉ๋˜์ง€ ์•Š๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์„œ๋ฒ„: ์ €์žฅ์†Œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ nonce ๊ฒ€์ฆ ๋กœ์ง์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Google ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด ์„œ๋ฒ„๋Š” ID ํ† ํฐ์˜ nonce ํด๋ ˆ์ž„์„ ๋ฐœ๊ธ‰๋œ nonce์™€ ๋น„๊ตํ•˜์—ฌ ๊ฒ€์ฆํ•ด์•ผ ํ•˜๋ฉฐ, ๊ฐ nonce๋Š” ๋‹จ์ผ ์‚ฌ์šฉ ์šฉ๋„๋กœ ์ทจ๊ธ‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
        .setServerClientId(WEB_CLIENT_ID) // ์›น ํด๋ผ์ด์–ธํŠธ ID
        .setFilterByAuthorizedAccounts(false)
-//        .setNonce(nonce)
+        .setNonce(nonce)
        .build()

์„œ๋ฒ„ ์ธก์—์„œ ์ด nonce๋ฅผ ID ํ† ํฐ์˜ nonce ํด๋ ˆ์ž„๊ณผ ๋Œ€์กฐํ•˜์—ฌ ๊ฒ€์ฆํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ 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
private val nonce = UUID.randomUUID().toString()
private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setServerClientId(WEB_CLIENT_ID) // ์›น ํด๋ผ์ด์–ธํŠธ ID
.setFilterByAuthorizedAccounts(false)
// .setNonce(nonce)
.build()
private val nonce = UUID.randomUUID().toString()
private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setServerClientId(WEB_CLIENT_ID) // ์›น ํด๋ผ์ด์–ธํŠธ ID
.setFilterByAuthorizedAccounts(false)
.setNonce(nonce)
.build()
๐Ÿค– Prompt for AI Agents
In feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt
around lines 29โ€“34, the client creates a nonce but it's commented out and also
generated as a single class-level val; enable nonce usage and make it
per-login-request by generating a fresh UUID for each auth attempt and pass it
to GetGoogleIdOption.setNonce(nonce). On the server side, implement persistent
single-use nonce handling: when starting an auth flow persist the nonce (e.g.,
DB/Redis) with an expiry, accept the ID token from the client and decode its
nonce claim, compare it to the stored nonce, reject mismatches or
expired/nonexistent nonces, and delete/mark the nonce as used so it cannot be
reused.

private val request: GetCredentialRequest = GetCredentialRequest.Builder()
.addCredentialOption(googleIdOption)
.build()
private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main)
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major

์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ณ ๋ คํ•˜์ง€ ์•Š์€ CoroutineScope๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

CoroutineScope(Dispatchers.Main)์„ ์ง์ ‘ ์ƒ์„ฑํ•˜๋ฉด Activity/Fragment๊ฐ€ ์ข…๋ฃŒ๋˜์–ด๋„ ์ฝ”๋ฃจํ‹ด์ด ๊ณ„์† ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ ์šฉํ•˜์„ธ์š”:

  1. ๊ถŒ์žฅ: Activity์˜ lifecycleScope๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๊ธฐ
class GoogleLoginHelper(
    private val context: Context,
    private val scope: CoroutineScope
)
// Usage: GoogleLoginHelper(context, lifecycleScope)
  1. ๋Œ€์•ˆ: SupervisorJob์„ ์‚ฌ์šฉํ•˜๊ณ  ๋ช…์‹œ์ ์œผ๋กœ ์ทจ์†Œ
private val job = SupervisorJob()
private val coroutineScope = CoroutineScope(Dispatchers.Main + job)

fun dispose() {
    job.cancel()
}
๐Ÿค– Prompt for AI Agents
In feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt
around line 38, the helper creates a raw CoroutineScope with Dispatchers.Main
which can outlive Activity/Fragment and cause memory leaks; change the class to
accept a CoroutineScope (preferably lifecycleScope) as a constructor parameter
and use that scope for launches, or alternatively create the scope with a
SupervisorJob combined with Dispatchers.Main and expose a dispose/clear method
that cancels the job; update usages to pass lifecycleScope from
Activities/Fragments when instantiating the helper.

Comment on lines +51 to +54
} catch (e: GetCredentialException) {
Log.e("Google Sign-in failed", " ${e.localizedMessage}")
}
}
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ onFailure ์ฝœ๋ฐฑ์ด ํ˜ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

GetCredentialException์ด ๋ฐœ์ƒํ•˜๋ฉด ๋กœ๊ทธ๋งŒ ๋‚จ๊ธฐ๊ณ  onFailure ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•˜์ง€ ์•Š์•„ UI๊ฐ€ ๋กœ๊ทธ์ธ ์‹คํŒจ๋ฅผ ๊ฐ์ง€ํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ๋กœ๊ทธ์ธ์ด ์ง„ํ–‰ ์ค‘์ธ์ง€ ์‹คํŒจํ–ˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•˜์„ธ์š”:

             } catch (e: GetCredentialException) {
                 Log.e("Google Sign-in failed", " ${e.localizedMessage}")
+                onFailure(e.localizedMessage ?: "๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค.")
             }
๐Ÿ“ 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
} catch (e: GetCredentialException) {
Log.e("Google Sign-in failed", " ${e.localizedMessage}")
}
}
} catch (e: GetCredentialException) {
Log.e("Google Sign-in failed", " ${e.localizedMessage}")
onFailure(e.localizedMessage ?: "๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค.")
}
}
๐Ÿค– Prompt for AI Agents
In feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt
around lines 51โ€“54, the catch block for GetCredentialException currently only
logs the error so the UI never learns the login failed; update the catch to
invoke the provided onFailure callback with the exception (e.g., onFailure(e))
so failure is propagated to the caller, and if onFailure must run on the UI
thread, post/invoke it on the main thread before returning.

Comment on lines +73 to +75
} catch (e: GoogleIdTokenParsingException) {
// Log.e(TAG, "Received an invalid google id token response", e)
}
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major

์˜ˆ์™ธ๊ฐ€ ์‚ผ์ผœ์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

GoogleIdTokenParsingException์ด ๋ฐœ์ƒํ•ด๋„ ์•„๋ฌด ์ฒ˜๋ฆฌ๋„ ํ•˜์ง€ ์•Š์•„ ์‚ฌ์šฉ์ž๊ฐ€ ์‹คํŒจ๋ฅผ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. Detekt๋„ ์ด๋ฅผ ๊ฒฝ๊ณ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ์‹คํŒจ ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•˜์„ธ์š”:

                     } catch (e: GoogleIdTokenParsingException) {
-//                        Log.e(TAG, "Received an invalid google id token response", e)
+                        Log.e(TAG, "Received an invalid google id token response", e)
+                        onFailure("๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ํ† ํฐ ํŒŒ์‹ฑ์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค.")
                     }
๐Ÿ“ 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
} catch (e: GoogleIdTokenParsingException) {
// Log.e(TAG, "Received an invalid google id token response", e)
}
} catch (e: GoogleIdTokenParsingException) {
Log.e(TAG, "Received an invalid google id token response", e)
onFailure("๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ํ† ํฐ ํŒŒ์‹ฑ์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค.")
}
๐Ÿงฐ Tools
๐Ÿช› detekt (1.23.8)

[warning] 73-73: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

๐Ÿค– Prompt for AI Agents
In feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt
around lines 73-75, the catch block for GoogleIdTokenParsingException currently
swallows the exception; replace it so the exception is logged and the login
failure path is invoked (e.g., call the existing failure callback or listener
with the exception or an appropriate error object). Ensure you do not rethrow
unnecessarily, but propagate the error to the caller by invoking the module's
failure callback (and include the exception in the log message and callback
parameters).

Comment on lines +68 to +79
OauthSideEffect.StartGoogleLogin -> googleLoginHelper.requestGoogleLogin(
onSuccess = { accessToken ->
viewModel.sendIntent(
OauthIntent.GoogleLoginSuccess(
provider = "GOOGLE",
accessToken = accessToken
)
)
},
onFailure = {}
)

Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ๋กœ์ง์ด ์ค‘๋ณต๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ๋กœ์ง์ด ๋‘ ๊ณณ์— ์ค‘๋ณต ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

  1. Lines 68-79: OauthSideEffect.StartGoogleLogin ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ ์ฒ˜๋ฆฌ
  2. Lines 88-100: googleLoginClick ์ฝœ๋ฐฑ์—์„œ ์ง์ ‘ ํ˜ธ์ถœ

์ด๋Š” ์˜๋„ํ•˜์ง€ ์•Š์€ ๋™์ž‘์„ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์นด์นด์˜ค ๋กœ๊ทธ์ธ๊ณผ ๋™์ผํ•˜๊ฒŒ ViewModel์„ ํ†ตํ•œ ๋‹จ์ผ ํ”Œ๋กœ์šฐ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•˜์—ฌ ์นด์นด์˜ค ๋กœ๊ทธ์ธ๊ณผ ์ผ๊ด€๋œ ํŒจํ„ด์„ ์œ ์ง€ํ•˜์„ธ์š”:

     OauthScreen(
         kakaoLoginClick = { viewModel.sendIntent(OauthIntent.KakaoLoginClick) },
-        googleLoginClick = {
-            googleLoginHelper.requestGoogleLogin(
-                onSuccess = { accessToken ->
-                    viewModel.sendIntent(
-                        OauthIntent.GoogleLoginSuccess(
-                            provider = "GOOGLE",
-                            accessToken = accessToken
-                        )
-                    )
-                },
-                onFailure = {}
-            )
-        }
+        googleLoginClick = { viewModel.sendIntent(OauthIntent.GoogleLoginClick) }
     )

Also applies to: 88-100

๐Ÿค– Prompt for AI Agents
In feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt around
lines 68-79 and 88-100 there is duplicated Google login logic: the same
googleLoginHelper.requestGoogleLogin call is invoked both from the
OauthSideEffect.StartGoogleLogin handler and from the googleLoginClick callback.
Remove the direct request call from the googleLoginClick callback (lines
~88-100) and instead dispatch a single ViewModel intent from the click handler
(e.g., send an intent like OauthIntent.StartGoogleLogin or similar) so that the
side-effect handler (lines ~68-79) is the sole place that calls
googleLoginHelper.requestGoogleLogin; also propagate success/failure through the
existing ViewModel intents rather than handling login directly in the UI
callback.

)
)
},
onFailure = {}
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸก Minor

์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

onFailure ์ฝœ๋ฐฑ์ด ๋นˆ ๋žŒ๋‹ค {}๋กœ ์ฒ˜๋ฆฌ๋˜์–ด ์žˆ์–ด ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ์‹คํŒจ๋ฅผ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ† ์ŠคํŠธ/์Šค๋‚ต๋ฐ”๋กœ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

onFailure = { errorMessage ->
    Log.e("OauthScreen", "Google login failed: $errorMessage")
    // TODO: Show error message to user
}

Also applies to: 98-98

๐Ÿค– Prompt for AI Agents
In feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt around
lines 77 and 98, the onFailure callbacks are empty lambdas so login failures are
swallowed; update both callbacks to accept the error (or message) parameter, log
the error (e.g., Log.e with a clear tag and message) and surface feedback to the
user (show a Toast or Snackbar with a user-friendly message); ensure you handle
nullable/unknown error text safely and avoid crashing when showing the UI
feedback.

Comment on lines +28 to +37
OauthIntent.GoogleLoginClick -> postSideEffect(OauthSideEffect.StartGoogleLogin)

is OauthIntent.GoogleLoginSuccess -> postSocialLogin(
provider = intent.provider,
oauthAccessToken = intent.accessToken
)

is OauthIntent.GoogleLoginFailure -> {
TODO()
}
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

Google ๋กœ๊ทธ์ธ ์‹คํŒจ ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Google ๋กœ๊ทธ์ธ ํ๋ฆ„์ด ์ถ”๊ฐ€๋˜์—ˆ์œผ๋‚˜ GoogleLoginFailure์˜ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ฐ€ TODO()๋กœ ๋‚จ์•„์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋Ÿฐํƒ€์ž„ ์‹œ NotImplementedError๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž์—๊ฒŒ ์ ์ ˆํ•œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•˜๊ฑฐ๋‚˜ ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๋Š” ๋“ฑ์˜ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

Kakao ๋กœ๊ทธ์ธ ์‹คํŒจ ์ฒ˜๋ฆฌ๋„ ๋™์ผํ•˜๊ฒŒ TODO()๋กœ ๋‚จ์•„์žˆ์Šต๋‹ˆ๋‹ค(Line 24-26). ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ตฌํ˜„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ตฌํ˜„์„ ๋„์™€๋“œ๋ฆด๊นŒ์š”?

๐Ÿค– Prompt for AI Agents
feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthViewModel.kt around
lines 24-26 and 28-37: both KakaoLoginFailure and GoogleLoginFailure currently
call TODO() which throws NotImplementedError at runtime; replace each TODO with
concrete failure handling by posting an appropriate side effect (e.g.,
postSideEffect(OauthSideEffect.ShowError(...)) with a user-friendly message and
include/log the underlying error for diagnostics), and ensure any cleanup or
state reset needed after a failed social login is performed (e.g., clear loading
state or reset flags).

Comment on lines +93 to +94
credentials = "1.6.0-beta03"
googleid = "1.1.1"
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major

๐Ÿงฉ Analysis chain

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ„์ „ ํ™•์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

credentials ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋ฒ ํƒ€ ๋ฒ„์ „(1.6.0-beta03)์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์•ˆ์ • ๋ฒ„์ „ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ๋ช…๋ น์œผ๋กœ ์ตœ์‹  ์•ˆ์ • ๋ฒ„์ „์„ ํ™•์ธํ•˜์„ธ์š”:


๐ŸŒ Web query:

What is the latest stable version of androidx.credentials library?

๐Ÿ’ก Result:

The latest stable release is androidx.credentials:credentials version 1.5.0 (released March 12, 2025). [1]

Sources
[1] Android Jetpack โ€” Credentials release notes.


์ตœ์‹  ์ •๋ณด๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ ๊ฒ€์ƒ‰์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์•ˆ์ • ๋ฒ„์ „(1.5.0)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ๊ฐ€ ์•„์ง ๋ฒ ํƒ€ ๋‹จ๊ณ„์ธ androidx.credentials:credentials:1.6.0-beta03์„ ์‚ฌ์šฉ ์ค‘์ž…๋‹ˆ๋‹ค. ์ตœ์‹  ์•ˆ์ • ๋ฒ„์ „์€ 1.5.0์ž…๋‹ˆ๋‹ค. ๋ฒ ํƒ€ ๋ฒ„์ „์€ ๋ฏธ์™„์„ฑ ๊ธฐ๋Šฅ๊ณผ ์ž ์žฌ์  ๋ฒ„๊ทธ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ํ”„๋กœ๋•์…˜ ๋ฐฐํฌ ์ „์— ์•ˆ์ • ๋ฒ„์ „์œผ๋กœ ๋ณ€๊ฒฝํ•˜์„ธ์š”.

credentials = "1.5.0"์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜, 1.6.0 ๋ฒ ํƒ€ ๋ฒ„์ „ ์‚ฌ์šฉ์ด ํ•„์ˆ˜์ธ ๊ฒฝ์šฐ ๊ทธ ์ด์œ ๋ฅผ ๋ช…์‹œํ•˜์„ธ์š”.

๐Ÿค– Prompt for AI Agents
gradle/libs.versions.toml lines 93-94: the project references the beta artifact
androidx.credentials:credentials 1.6.0-beta03 which is not recommended for
production; update the version to the latest stable release by changing
credentials = "1.6.0-beta03" to credentials = "1.5.0", or if you must keep the
beta, add a short comment next to the entry explaining why the beta is required
and what feature or fix depends on it.

Copy link
Contributor

@88guri 88guri left a comment

Choose a reason for hiding this comment

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

๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ๐Ÿ‘ Good~

@nagaeng nagaeng self-requested a review January 5, 2026 07:10
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: 0

๐Ÿงน Nitpick comments (1)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt (1)

129-131: ๊ณ ์ • ๋†’์ด์™€ weight ํ˜ผ์šฉ์œผ๋กœ ์ธํ•œ ๋ ˆ์ด์•„์›ƒ ๋ถˆ์ผ์น˜

์ผ๋ถ€ Spacer๋งŒ ๊ณ ์ • ๋†’์ด(height)๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๊ณ , Line 197์˜ Spacer(modifier = Modifier.weight(12f))๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด:

  1. ๊ณ ์ • ๋†’์ด Spacer๋“ค์€ ํ™”๋ฉด ํฌ๊ธฐ์— ๊ด€๊ณ„์—†์ด ํ•ญ์ƒ ๋™์ผํ•œ ๊ณต๊ฐ„์„ ์ฐจ์ง€
  2. weight Spacer๋Š” ๋‚จ์€ ๊ณต๊ฐ„์„ ๋ชจ๋‘ ์ฐจ์ง€
  3. Arrangement.SpaceBetween๊ณผ ์กฐํ•ฉ ์‹œ ์˜๋„์น˜ ์•Š์€ ๋ ˆ์ด์•„์›ƒ ๋ฐœ์ƒ ๊ฐ€๋Šฅ

ํ™”๋ฉด ํฌ๊ธฐ๋ณ„ ๋Œ€์‘์ด ํ•„์š”ํ•˜๋‹ค๋ฉด weight ๋ฐฉ์‹์œผ๋กœ ํ†ต์ผํ•˜๊ฑฐ๋‚˜, ๊ณ ์ • ๋ ˆ์ด์•„์›ƒ์ด ์˜๋„๋ผ๋ฉด ๋ชจ๋“  Spacer๋ฅผ ๊ณ ์ • ๋†’์ด๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

โ™ป๏ธ ์ผ๊ด€๋œ ๋ฐฉ์‹์œผ๋กœ ์ˆ˜์ • ์ œ์•ˆ (๊ณ ์ • ๋†’์ด ๋ฐฉ์‹)
-        Spacer(modifier = Modifier.weight(12f))
+        Spacer(modifier = Modifier.weight(1f))

๋˜๋Š” ๋ชจ๋“  spacer๋ฅผ weight ๊ธฐ๋ฐ˜์œผ๋กœ ๋ณต์›:

-            modifier = Modifier.height(16.dp)
+            modifier = Modifier.weight(1f)
-        Spacer(modifier = Modifier.height(32.dp))
+        Spacer(modifier = Modifier.weight(2f))
-        Spacer(modifier = Modifier.height(24.dp))
+        Spacer(modifier = Modifier.weight(1.5f))

Also applies to: 141-141, 169-169

๐Ÿ“œ Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between a3a96c3 and d18d30d.

๐Ÿ“’ Files selected for processing (2)
  • feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt
  • feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthViewModel.kt
๐Ÿšง Files skipped from review as they are similar to previous changes (1)
  • feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthViewModel.kt
๐Ÿ”‡ Additional comments (1)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt (1)

117-124: Arrangement.SpaceBetween๊ณผ Spacer ์กฐํ•ฉ ์žฌ๊ฒ€ํ†  ํ•„์š”

ํ˜„์žฌ Column์ด verticalArrangement = Arrangement.SpaceBetween์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด ์ž์‹ ์š”์†Œ๋“ค ์‚ฌ์ด์— ์ž๋™์œผ๋กœ ๊ท ๋“ฑํ•œ ๊ฐ„๊ฒฉ์ด ๋ฐฐ๋ถ„๋ฉ๋‹ˆ๋‹ค. ์ด ์ƒํƒœ์—์„œ ๊ณ ์ • ๋†’์ด Spacer๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด Spacer ์ž์ฒด๊ฐ€ "์ฝ˜ํ…์ธ "๋กœ ๊ฐ„์ฃผ๋˜์–ด ์˜๋„ํ•œ ๋ ˆ์ด์•„์›ƒ๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SpaceBetween์„ ์œ ์ง€ํ•˜๋ฉด์„œ ํŠน์ • ๊ฐ„๊ฒฉ์„ ์กฐ์ ˆํ•˜๋ ค๋ฉด Spacer ๋Œ€์‹  ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์˜ padding์ด๋‚˜ Modifier.padding()์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋ช…ํ™•ํ•ฉ๋‹ˆ๋‹ค.

@ImHyungsuk ImHyungsuk merged commit afd8991 into develop Jan 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ํ˜•์„ ๐Ÿง๐Ÿ€ ๊ทธ๋‚  ์ธ๋ฅ˜๋Š” ๋– ์˜ฌ๋ ธ๋‹ค . ์ง„๊ฒฉ์˜ ํ˜•์„์„œ์„œ์„œ์„

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] ๊ตฌ๊ธ€๋กœ๊ทธ์ธ ๊ฐ€๋ณด์ž์ž‡

3 participants