Skip to content

feat: 클라이언트단 카카오 로그인 구현 #16

Merged
easyhooon merged 13 commits intodevelopfrom
BOOK-62-feature/#14
Jun 24, 2025
Merged

feat: 클라이언트단 카카오 로그인 구현 #16
easyhooon merged 13 commits intodevelopfrom
BOOK-62-feature/#14

Conversation

@easyhooon
Copy link
Copy Markdown
Contributor

@easyhooon easyhooon commented Jun 23, 2025

🔗 관련 이슈

📙 작업 설명

  • 카카오 로그인 관련 라이브러리 의존성 추가
  • 로그인 화면 및 카카오 로그인 버튼 임시 구현(core:ui 모듈 추가)
  • 카카오 로그인 구현 및 KAKAO REST API 토큰 발급 및 에러 처리 로직 구현

🧪 테스트 내역 (선택)

  • 주요 기능 정상 동작 확인
  • 브라우저/기기에서 동작 확인
  • 엣지 케이스 테스트 완료
  • 기존 기능 영향 없음

📸 스크린샷 또는 시연 영상 (선택)

기능 미리보기
임시 로그인 화면

💬 추가 설명 or 리뷰 포인트 (선택)

  • 로그인 이벤트 처리 흐름 관련에서 제 나름의 방식으로 구현을 해보았는데, 더 나은 방식이 있다면 언제든 제안 환영합니다!
  • KAKAO_NATIVE_APP_KEY 가 local.properties에 추가되었습니다. 노션 확인부탁드림다
  • keyHash를 카카오 디벨로퍼 사이트에 별도로 추가 해야하는 관계로, keyHash 추가 후 문제 되는 부분 있는지 추가 확인하도록 하겠습니다
  • 이전에 구현해두었던 BottomNavigation이 백스택 관련해서 의도치 않는 동작이 수행되는 것으로 파악되어,
    circuit bottom navigation example 아래 예제를 확인하여 동작 문제를 해결해보도록 하겠습니다
    • 의도치 않은 동작: 홈 화면이 아닌, 다른(도서 검색, 내 서재) 화면에서 시스템 백버튼을 누를 경우 바로 백스택에 홈화면만 남아야 하는데, 홈 -> 도서 검색 -> 내 서재 의 순서로 내 서재 화면 진입시 시스템 백버튼을 누를 경우 도서 검색 화면으로 이동함
  • 우려되는 부분: Circuit Navigation 의 경우, resetRoot() 라는 함수를 통해 navigation 의 root screen을 동적으로 바꿀 수 있는 강력한 함수를 제공함(compose navigation 대비).
    다만, goTo()함수와 마찬가지로 이동하려는 화면을 명시해야하기 때문에, 이동하려는 feature 모듈을 의존해야함.
    로그인만 있는 경우엔 문제가 없지만 로그아웃을 통해 설정 화면 -> 로그인 화면으로 이동하는 경우 마찬가지로 설정 화면이 로그인 모듈을 알아야할 수 있기 때문에, 모듈간의 순환 참조가 발생할 수 있음.
    이후 실제로 순환 참조가 발생하게 된다면 LoginScreen을 별도의 Activity로 구현하여 navigator 모듈을 도입하여 해결해야 함

Summary by CodeRabbit

  • 신규 기능

    • 카카오 로그인을 통한 인증 기능이 추가되었습니다.
    • 로그인 화면이 새롭게 도입되어 앱 실행 시 최초로 표시됩니다.
    • 커스텀 버튼(BooketButton) 컴포넌트가 추가되었습니다.
    • 로그인 화면에 카카오 전용 아이콘 및 "카카오 로그인" 텍스트가 적용되었습니다.
  • UI/스타일

    • 디자인 시스템에 카카오 전용 색상과 에러 메시지 문자열이 추가되었습니다.
    • 로그인 화면 UI가 개선되어 로딩 인디케이터와 토스트 메시지 지원이 추가되었습니다.
  • 버그 수정 및 안정성

    • 네트워크 및 서버 오류, 알 수 없는 오류에 대한 안내 메시지가 제공됩니다.
  • 설정 및 의존성

    • 카카오 SDK 및 관련 라이브러리 의존성이 추가되었습니다.
    • 앱에 인터넷 권한이 추가되었습니다.
    • 신규 core/ui 및 feature/login 모듈이 프로젝트에 포함되었습니다.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 23, 2025

"""

Walkthrough

카카오 로그인을 위한 클라이언트단 구현이 추가되었습니다. 카카오 SDK 의존성, 로그인 화면, 버튼, 인증 플로우, 관련 초기화 코드 및 리소스가 포함되었으며, 신규 모듈(feature/login, core/ui)과 빌드 설정, ProGuard 규칙, 색상·문자열 리소스 등도 함께 반영되었습니다.

Changes

파일/경로 그룹 변경 요약
app/build.gradle.kts, gradle/libs.versions.toml, settings.gradle.kts, app/proguard-rules.pro, app/src/main/AndroidManifest.xml 카카오 SDK 및 관련 라이브러리 의존성, 빌드 설정, ProGuard 규칙, AndroidManifest에 카카오 인증 Activity/메타데이터/권한 추가, Kakao Native App Key 처리 로직 도입
app/src/main/kotlin/com/ninecraft/booket/initializer/KakaoSdkInitializer.kt Kakao SDK 초기화용 Initializer 신규 추가
build-logic/src/main/kotlin/AndroidFeatureConventionPlugin.kt, core/ui/build.gradle.kts, core/ui/.gitignore core/ui 모듈 신규 추가 및 의존성 연결, 빌드 설정
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt 카카오 전용 색상 상수 추가
core/designsystem/src/main/res/values/strings.xml, feature/login/src/main/res/values/strings.xml 에러 메시지 및 카카오 로그인용 문자열 리소스 추가
core/network/build.gradle.kts 빌드 타입 블록 구문 간결화(기능 변화 없음)
feature/login/** (여러 파일) 로그인 화면, 버튼, 인증 클라이언트, Presenter, 사이드 이펙트 핸들러, 아이콘, 리소스 등 신규 구현 및 추가
feature/main/build.gradle.kts, feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/MainActivity.kt feature.login 모듈 및 카카오 라이브러리 의존성 추가, MainActivity의 최초 화면을 LoginScreen으로 변경

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LoginScreen
    participant KakaoAuthClient
    participant Kakao SDK
    participant App

    User->>LoginScreen: 카카오 로그인 버튼 클릭
    LoginScreen->>KakaoAuthClient: loginWithKakao(context, onSuccess, onFailure)
    KakaoAuthClient->>Kakao SDK: 카카오톡/계정 로그인 시도
    Kakao SDK-->>KakaoAuthClient: 로그인 결과 콜백
    alt 성공
        KakaoAuthClient->>Kakao SDK: 사용자 정보(me) 요청
        Kakao SDK-->>KakaoAuthClient: 사용자 정보/토큰 반환
        KakaoAuthClient->>LoginScreen: onSuccess(토큰)
        LoginScreen->>App: 홈 화면으로 이동
    else 실패
        KakaoAuthClient->>LoginScreen: onFailure(에러 메시지)
        LoginScreen->>LoginScreen: 토스트 메시지 표시
    end
Loading

Assessment against linked issues

Objective Addressed Explanation
카카오 로그인 관련 라이브러리 의존성 추가 (#14)
로그인 화면 및 카카오 로그인 버튼 임시 구현 (#14)
카카오 로그인 구현 및 api 토큰 발급 플로우 구현 (#14)

Assessment against linked issues: Out-of-scope changes

해당 변경 내역에는 명시된 이슈(#14)와 무관한 기능적 코드 변경이 발견되지 않았습니다.

Suggested labels

⚙️ chore

Suggested reviewers

  • seoyoon513

Poem

🐇
로그인 문이 활짝 열렸네
카카오 버튼 노랗게 빛나고
인증의 흐름이 부드럽게 흘러
홈 화면까지 깡충깡충
코드도 리소스도 한데 모아
북잇의 시작, 이제는 카카오와 함께!
🥕
"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe38e41 and ee826c5.

📒 Files selected for processing (2)
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/HandleLoginSideEffects.kt (1 hunks)
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginScreen.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/HandleLoginSideEffects.kt
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginScreen.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: ci-build
✨ 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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
Copy Markdown

@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

🧹 Nitpick comments (10)
gradle/libs.versions.toml (1)

86-86: 아이콘 라이브러리 버전 관리 확인
androidx-compose-material-icons-extended가 Compose BOM으로 관리되는지 확인하거나, 명시적 version.ref를 추가하는 방안을 검토해주세요.

core/network/build.gradle.kts (1)

20-27: 빌드 타입 프로퍼티 누락 시 예외 처리 필요
getServerBaseUrl("…")가 로컬 프로퍼티에 해당 키가 없으면 런타임에 예외가 발생할 수 있습니다. 디폴트 URL 제공 또는 유효성 검사 후 명확한 에러 메시지 추가를 고려하세요.

app/proguard-rules.pro (1)

23-30: Kakao SDK 모델 클래스 보존 범위 재검토
현재 -keep class com.kakao.sdk.**.model.* { <fields>; }는 모델 필드만 유지합니다. SDK의 추가 클래스나 메서드가 제거되지 않도록 필요한 범위를 재검토하거나 아래처럼 와일드카드로 확장하는 것을 권장합니다.

-keep class com.kakao.sdk.**.model.* { <fields>; }
+keep class com.kakao.sdk.** { *; }
app/build.gradle.kts (1)

64-66: 함수 정의 위치 개선 권장.

getApiKey 함수가 사용되는 위치(21번 라인) 이후에 정의되어 있습니다. 가독성을 위해 함수를 파일 상단으로 이동하는 것을 권장합니다.

core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/Button.kt (1)

58-78: 네이밍 일관성 개선 제안.

함수명이 TogetherButtonContent인데 컴포넌트명은 BooketButton입니다. 일관성을 위해 BooketButtonContent로 변경하는 것을 고려해보세요.

-private fun TogetherButtonContent(
+private fun BooketButtonContent(
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/KakaoLoginClient.kt (1)

60-61: TODO 주석 처리 필요

서버 로그인 로직이 미구현 상태입니다. 이 부분의 구현 계획을 명확히 하거나 이슈로 등록해 주세요.

서버 로그인 API 연동 코드 구현을 도와드릴까요? 또는 이를 추적할 이슈를 생성하시겠습니까?

feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt (2)

8-8: 모듈 간 결합도 검토 필요

feature/login 모듈이 feature/home 모듈에 직접 의존하고 있습니다. 이는 모듈 간 결합도를 높일 수 있습니다. 네비게이션 대상을 추상화하거나 상위 모듈에서 주입받는 방식을 고려해보세요.


18-18: 불필요한 @Suppress 어노테이션

새로 생성된 클래스에 @Suppress("unused") 어노테이션이 필요한지 검토해주세요. 실제로 사용되지 않는 경우라면 해당 어노테이션을 제거하는 것이 좋습니다.

-@Suppress("unused")
 class LoginPresenter @AssistedInject constructor(
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginScreen.kt (2)

91-96: 중복된 fontSize 설정 제거

Text 컴포넌트에서 fontSize가 두 번 설정되어 있습니다(91번 줄과 94번 줄). 중복을 제거해주세요.

                    Text(
                        text = stringResource(id = R.string.kakao_login),
-                        fontSize = 18.sp,
                        style = TextStyle(
                            fontWeight = FontWeight.SemiBold,
                            fontSize = 18.sp,
                            lineHeight = 25.sp,
                        ),
                    )

108-111: 로딩 인디케이터 접근성 개선

로딩 상태일 때 스크린 리더 사용자를 위한 접근성 정보를 추가하는 것을 고려해보세요.

            if (state.isLoading) {
-                CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
+                CircularProgressIndicator(
+                    modifier = Modifier.align(Alignment.Center)
+                        .semantics { contentDescription = "로그인 중..." }
+                )
            }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7e6dd4 and a8c7bd1.

📒 Files selected for processing (23)
  • app/build.gradle.kts (2 hunks)
  • app/proguard-rules.pro (1 hunks)
  • app/src/main/AndroidManifest.xml (2 hunks)
  • app/src/main/kotlin/com/ninecraft/booket/initializer/KakaoSdkInitializer.kt (1 hunks)
  • build-logic/src/main/kotlin/AndroidFeatureConventionPlugin.kt (1 hunks)
  • core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt (1 hunks)
  • core/designsystem/src/main/res/values/strings.xml (1 hunks)
  • core/network/build.gradle.kts (1 hunks)
  • core/ui/.gitignore (1 hunks)
  • core/ui/build.gradle.kts (1 hunks)
  • core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/Button.kt (1 hunks)
  • feature/login/.gitignore (1 hunks)
  • feature/login/build.gradle.kts (1 hunks)
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/HandleLoginSideEffects.kt (1 hunks)
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/KakaoLoginClient.kt (1 hunks)
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt (1 hunks)
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginScreen.kt (1 hunks)
  • feature/login/src/main/res/drawable/ic_kakao.xml (1 hunks)
  • feature/login/src/main/res/values/strings.xml (1 hunks)
  • feature/main/build.gradle.kts (2 hunks)
  • feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/MainActivity.kt (2 hunks)
  • gradle/libs.versions.toml (5 hunks)
  • settings.gradle.kts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: ci-build
🔇 Additional comments (28)
core/ui/.gitignore (1)

1-1: core/ui 모듈 빌드 아티팩트 무시
/build 디렉토리를 .gitignore에 추가해 빌드 결과물이 버전 관리에서 제외됩니다.

core/designsystem/src/main/res/values/strings.xml (1)

3-5: 오류 메시지 리소스 추가 승인
네트워크, 서버, 알 수 없는 오류에 대한 한국어 문자열 리소스를 적절히 추가했습니다.

gradle/libs.versions.toml (5)

61-62: 테스트 및 UI 라이브러리 버전 추가 확인
espresso-core = "3.6.1"material = "1.12.0"을 테스트 및 UI 지원을 위해 적절히 추가했습니다.


111-111: 카카오 인증 라이브러리 정의 승인
kakao-auth = { group = "com.kakao.sdk", name = "v2-user", version.ref = "kakao-core" }가 적절히 설정되었습니다.


115-116: 테스트와 UI 라이브러리 정의 승인
androidx-espresso-corematerial 라이브러리 정의가 올바르게 추가되었습니다.


154-155: 번들에 아이콘 라이브러리 포함 확인
androidx-compose 번들에 androidx-compose-material-icons-extended를 추가해 일관된 번들로 관리됩니다.


44-46: 카카오 SDK 버전 최신성 검증 필요
kakao-core = "2.21.4"가 현재 안정 최신 릴리즈인지 확인해주세요.

com.kakao.sdk:v2-user의 최신 버전은 무엇인가요?
feature/login/.gitignore (1)

1-1: feature/login 모듈 빌드 아티팩트 무시
/build 디렉토리를 .gitignore에 추가해 버전 관리에서 제외합니다.

feature/main/build.gradle.kts (2)

20-20: feature.login 모듈 의존성 추가 확인
메인 기능에 로그인 기능이 잘 통합되었습니다.


29-29: Kakao Auth 라이브러리 의존성 추가 확인
Kakao 인증 클라이언트 라이브러리(libs.kakao.auth)가 제대로 추가되었습니다.

core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt (1)

13-13: 카카오 브랜드 컬러 추가 승인

카카오의 공식 브랜드 컬러 (#FBD300)가 올바르게 추가되었습니다. 기존 컬러 정의 패턴을 잘 따르고 있습니다.

build-logic/src/main/kotlin/AndroidFeatureConventionPlugin.kt (1)

22-22: core:ui 모듈 의존성 추가 승인

피쳐 모듈들이 공통 UI 컴포넌트를 사용할 수 있도록 core:ui 의존성이 적절히 추가되었습니다.

feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/MainActivity.kt (2)

12-12: 로그인 화면 import 변경 승인

로그인 우선 플로우 구현을 위한 import 변경이 적절합니다.


34-34: 루트 화면을 로그인으로 변경 - UX 고려사항

로그인 화면을 루트로 설정한 것은 기능적으로 올바르지만, 기존 사용자들의 UX에 영향을 줄 수 있습니다. 이미 로그인한 사용자는 홈 화면으로 바로 이동하는 로직이 필요할 수 있습니다.

다음 스크립트로 로그인 상태 확인 로직이 구현되어 있는지 확인해보겠습니다:

#!/bin/bash
# 로그인 상태 확인 및 자동 네비게이션 로직 검색
rg -A 5 -B 5 "isLoggedIn|LoginState|authenticated" --type kotlin
feature/login/src/main/res/values/strings.xml (1)

1-4: 카카오 로그인 문자열 리소스 추가 승인

한국어 카카오 로그인 문자열이 올바르게 정의되었습니다. XML 구조와 네이밍이 적절합니다.

core/ui/build.gradle.kts (1)

13-18: 빌드 스크립트의 잠재적 구문 오류 확인 필요

implementations 함수가 사용되었는데, 이는 표준 Gradle DSL이 아닐 수 있습니다. 일반적으로는 각 의존성을 개별적으로 implementation()으로 선언합니다.

다음 스크립트로 프로젝트에서 implementations 함수가 정의되어 있는지 확인해보겠습니다:

#!/bin/bash
# implementations 함수 정의 확인
rg -A 10 -B 5 "fun implementations|implementations.*=" --type kotlin

# 다른 build.gradle.kts 파일들에서 사용 패턴 확인
fd "build.gradle.kts" --exec rg -l "implementations\(" {} \;
settings.gradle.kts (3)

18-21: Kakao Maven 저장소 추가 확인
Kakao SDK 종속성을 위해 개발용 Nexus 저장소가 추가되었습니다. FAIL_ON_PROJECT_REPOS 모드에도 문제없이 접근 가능한지 검증해주세요.


32-32: :feature:login 모듈 포함 확인
로그인 기능 모듈이 정상적으로 빌드에 포함되었습니다. 의존성 그래프에 예상대로 반영되었는지 CI 빌드 로그를 점검해주세요.


36-36: :core:ui 모듈 포함 순서 검증 요청
UI 공통 컴포넌트를 사용하는 feature 모듈들이 core:ui 변경을 인식하는지 확인이 필요합니다.

다음 스크립트로 settings.gradle.kts:core:ui가 포함됐는지 확인해보세요:

#!/bin/bash
grep -n "core:ui" settings.gradle.kts
feature/login/src/main/res/drawable/ic_kakao.xml (1)

1-32: 벡터 드로어블 리소스 추가 승인
아이콘 경로 및 색상 정의가 적절하며 불필요한 속성이 없습니다. Composable 환경에서도 잘 렌더링될 것으로 보입니다.

app/src/main/kotlin/com/ninecraft/booket/initializer/KakaoSdkInitializer.kt (1)

8-17: 카카오 SDK 초기화 구현이 올바릅니다.

AndroidX Startup 패턴을 정확히 따르고 있으며, SDK 초기화 로직이 깔끔하게 구현되어 있습니다.

app/build.gradle.kts (1)

21-23: 보안 고려사항: API 키 노출 위험성 검토 필요.

buildConfigField로 API 키를 설정하면 APK 디컴파일 시 키가 노출될 수 있습니다. 카카오 네이티브 앱 키는 공개 키이므로 문제없지만, 향후 민감한 API 키 처리 시 주의가 필요합니다.

다음 스크립트로 빌드된 APK에서 API 키 노출 여부를 확인해보세요:

#!/bin/bash
# APK 내 BuildConfig 클래스에서 API 키 확인
find . -name "*.apk" -exec unzip -l {} \; | grep BuildConfig || echo "APK 파일을 찾을 수 없습니다"
core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/Button.kt (1)

22-55: 우수한 재사용 가능한 버튼 컴포넌트 구현.

Material Design 원칙을 잘 따르고 있으며, 커스터마이징 옵션과 접근성을 고려한 구현이 훌륭합니다.

feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/HandleLoginSideEffects.kt (1)

17-37: 사이드 이펙트 처리 로직이 잘 구현되어 있습니다.

LaunchedEffect를 사용한 사이드 이펙트 처리와 콜백 기반 성공/실패 처리가 적절합니다.

app/src/main/AndroidManifest.xml (3)

5-5: 카카오 SDK 사용을 위한 필수 권한 추가.

INTERNET 권한이 카카오 SDK 통신을 위해 적절히 추가되었습니다.


29-32: 카카오 SDK 초기화 설정이 올바릅니다.

AndroidX Startup을 통한 KakaoSdkInitializer 등록이 정확하게 구성되어 있습니다.


35-51: OAuth 인증 처리를 위한 액티비티 설정 완료.

AuthCodeHandlerActivity와 intent-filter 설정이 카카오 OAuth 콜백 처리를 위해 올바르게 구성되어 있습니다. 커스텀 URI 스킴 설정도 적절합니다.

feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt (1)

54-57: 로그인 성공 후 네비게이션 패턴 확인

navigator.resetRoot(HomeScreen) 패턴이 로그인 플로우에 적절한지 확인해주세요. 백스택을 완전히 재설정하는 것이 의도된 동작인지 검토가 필요합니다.

Comment thread feature/login/build.gradle.kts
Comment thread app/proguard-rules.pro
Comment on lines +31 to +37
# refrofit2 (with r8 full mode)
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>
-keep,allowobfuscation,allowshrinking class retrofit2.Response
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

Retrofit2 R8 룰 문법 오류
플레이스홀더(<methods>, <1>, <3>)가 남아 있어 룰이 적용되지 않을 가능성이 높습니다. 공식 가이드에 맞게 다음과 같이 수정하세요.

-# Retrofit2 (with R8 full mode)
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>
-keep,allowobfuscation,allowshrinking class retrofit2.Response
+# Retrofit2 (with R8 full mode)
+# Retrofit HTTP 인터페이스 및 응답 타입 보존
+keep class retrofit2.** { *; }
+keep interface retrofit2.http.** { *; }
+keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation

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

🤖 Prompt for AI Agents
In app/proguard-rules.pro around lines 31 to 37, the Retrofit2 R8 rules contain
placeholder tokens like <methods>, <1>, and <3> which are invalid and prevent
the rules from applying correctly. Replace these placeholders with proper
ProGuard syntax according to the official Retrofit2 R8 configuration guide,
ensuring all interface and class specifications are correctly defined without
placeholders.

Comment thread app/build.gradle.kts Outdated
onFailure: (String) -> Unit,
) {
when {
(error is AuthError && error.response.error == "ProtocolError") -> {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

오류 처리 로직 개선 필요

문자열 비교로 프로토콜 오류를 확인하는 방식은 취약할 수 있습니다. Kakao SDK의 구체적인 오류 타입을 활용하는 것이 더 안전합니다.

-            (error is AuthError && error.response.error == "ProtocolError") -> {
+            (error is AuthError && error.response.error?.contains("Protocol", ignoreCase = true) == true) -> {
🤖 Prompt for AI Agents
In
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/KakaoLoginClient.kt
at line 38, the current error handling checks for a protocol error by comparing
the error response string, which is fragile. Instead, update the condition to
use the specific error type or constant provided by the Kakao SDK for protocol
errors to make the check more robust and reliable.

.height(56.dp)
.align(Alignment.BottomCenter),
containerColor = Kakao,
contentColor = Color(0xFF121212),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

하드코딩된 색상을 디자인 시스템으로 이동

Color(0xFF121212) 하드코딩된 색상 값을 디자인 시스템의 색상으로 대체해주세요.

-                contentColor = Color(0xFF121212),
+                contentColor = BooketTheme.colors.onSurface, // 또는 적절한 디자인 시스템 색상
📝 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
contentColor = Color(0xFF121212),
contentColor = BooketTheme.colors.onSurface, // 또는 적절한 디자인 시스템 색상
🤖 Prompt for AI Agents
In
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginScreen.kt
at line 87, replace the hardcoded color value Color(0xFF121212) with the
corresponding color from the design system. Locate the appropriate color
definition in the design system's color resources or theme and use that instead
of the hardcoded hex value.

) {
Box(modifier = modifier.fillMaxSize()) {
Text(
text = "로그인",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

하드코딩된 텍스트를 문자열 리소스로 이동

"로그인" 텍스트가 하드코딩되어 있습니다. 다국어 지원과 일관성을 위해 문자열 리소스를 사용해주세요.

-                text = "로그인",
+                text = stringResource(id = R.string.login),
🤖 Prompt for AI Agents
In
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginScreen.kt
at line 74, the text "로그인" is hardcoded. To support multiple languages and
maintain consistency, move this string to the appropriate string resource file
(e.g., strings.xml) and reference it in the code using the resource ID instead
of the hardcoded text.

Comment thread settings.gradle.kts Outdated
":feature:main",
":feature:search",
)
include(":core:ui")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

상단 include 블럭 내부에 넣어주세요 (저도 당했음;)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

반영 완료! fe38e41

@easyhooon easyhooon merged commit 5d05068 into develop Jun 24, 2025
3 checks passed
@easyhooon easyhooon deleted the BOOK-62-feature/#14 branch June 24, 2025 01:30

class KakaoSdkInitializer : Initializer<Unit> {

override fun create(context: Context) {
Copy link
Copy Markdown

@jisungbin jisungbin Jun 24, 2025

Choose a reason for hiding this comment

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

@easyhooon 제가 잘 몰라서 그러는데, android.app.Application 클래스의 onCreate에서 init 하는거랑, androidx.startup.Initializer 클래스의 create에서 init 하는거랑 무슨 차이가 있나요?

(init 불리는 시점이나 성능 차이..?)

Androidx Startup 나온지 꽤 됐는데 아직 한 번도 제대로 본 적이 없네요 😭

Copy link
Copy Markdown
Contributor Author

@easyhooon easyhooon Jun 24, 2025

Choose a reason for hiding this comment

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

image

@jisungbin InitializationProvider 코드를 보면 startup 라이브러리가 ContentProvider 추상클래스를 상속하여, ContentProvider를 기반으로 구현되어있음을 알 수 있습니다

ContentProvider는 Application.onCreate()보다 더 이른 시점에 실행되어, Application.onCreate()에서 Logger, FIrebaseCrashlytics, KakaoSdk등을 초기화하는 것보다 빠른 초기화를 할 수 있구, 공식문서에 따르면 여러 Initializer들이 하나의 ContentProvider를 공유하는 방식으로 동작하여, 각 컴포넌트마다 별도의 ContentProvider를 생성하는 것보다 성능상 이점을 얻을 수 있다고 합니다!

그외에도 depedencies() 함수를 override하여 초기화 순서를 관리할 수도 있는데, Application.onCreate()에서도 동일하게 코드 순서로 제어가 가능하긴해서 장점인지는 잘 모르겠네요(의존성을 직접 관리해서 초기화 시점을 조절해본 적은 없습니다 ^_^)

답변을 드리다가 문득 생각이 든게, Application Context의 초기화 시점보다 빠르게 초기화가 이뤄지면 문제가 생기지 않을까? 였는데 해당 글을 통해 문제가 없음을 확인할 수 있었습니다

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

아하!!! 제 핑거프린세스 질문에도 자세한 답변 감사합니다.

그러면 현재 시나리오에서는 Application.onCreate() 안에서 KakaoSdk.init를 진행하여도 문제 없어 보이는데(Application.onCreate() 보다 이른 시점에 진행하지 않아도 됨), Application 대신에 Initializer로 구현하신 결정 과정이 궁금해요.

Copy link
Copy Markdown
Contributor Author

@easyhooon easyhooon Jun 24, 2025

Choose a reason for hiding this comment

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

(Application.onCreate() 보다 이른 시점에 진행하지 않아도 됨)

음 말씀하신것처럼 반드시 이른 시점에 진행하지 않아도 되는 것은 맞지만, 저는 onCreate()보다 빠른 초기화를 할 수 있다는 점에서 메리트가 있다고 생각하여 채택했습니다!

벤치마크를 통해 직접 어느정도 이득을 볼 수 있는지 측정해보진 않았지만, Jetpack에서 지원하는 라이브러리이고, 사용하면 장점이 있다고 공식문서에서도 안내를 하기 때문에(사용한다고 trade off가 있는 것도 아닌걸로 판단됨) Intializer로 구현을 결정하였습니다

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

오 모두 공감됩니다.
감사합니다!

@coderabbitai coderabbitai Bot mentioned this pull request Jun 30, 2025
4 tasks
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.

[BOOK-62/feat] 클라이언트단 카카오 로그인 구현

3 participants