Skip to content

[Refactor] #162 HttpClient의 토큰 캐싱 옵션 설정 추가 및 일부 API 버전 상향#163

Merged
Ojongseok merged 7 commits intodevelopfrom
refactor/#162-disable-ktor-token-caching
Mar 2, 2026
Merged

[Refactor] #162 HttpClient의 토큰 캐싱 옵션 설정 추가 및 일부 API 버전 상향#163
Ojongseok merged 7 commits intodevelopfrom
refactor/#162-disable-ktor-token-caching

Conversation

@Ojongseok
Copy link
Member

@Ojongseok Ojongseok commented Mar 2, 2026

🔗 관련 이슈

📙 작업 설명

  • Ktor 버전 3.4.0으로 상향
  • Kotlin, ksp, hilt 버전 ktor-3.4.0을 지원하는 최소 버전으로 상향
  • 개발기/상용기에 따라 cacheTokens 옵션 활성화되도록 cacheTokens = !BuildConfig.DEBUG 구문 추가
  • 수동으로 토큰을 제거하던 AuthCacheManager 제거

🧪 테스트 내역 (선택)

  • 개발기에서 AccessToken, RefreshToken 만료 시 각각 AccessToken 갱신 및 로그인 화면으로 이동하는 것 확인했습니다.

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

  • 현재 서버의 Access/Refresh 토큰의 만료 주기가 상용 : 1시간/14일, 개발 : 1시간/2시간 설정되어 있고, 상용기에서는 비교적 RefreshToken의 만료 주기가 길기 때문에 불필요한 TokenRepository 조회 횟수를 줄이기 위해 cacheTokens 옵션을 활성화 할 수 있도록 했습니다.

Q. 토끼 리뷰에 따라 로그아웃/탈퇴 시 HttpClient에 저장된 토큰을 명시적으로 제거해 주어야 해서 반영했습니다. 0a2c091
TokenRepositoryImplHttpClient를 주입해서 기존 clearTokens()httpClient.get().authProvider<BearerAuthProvider>()?.clearToken() 구문을 추가했습니다.
위 커밋처럼 Impl에 HttpClient를 Lazy 주입하는 방법이 좋을까요? (Lazy 주입을 하는 이유는 HttpClient -> TokenRepository -> HttpClient로 참조하기 때문입니다.)

혹은 HttpClient를 Impl에 주입하지 않고, NetworkModuleHttpClient 인스턴스를 정의하는 provideHttpClient() 내부에서 인터셉터를 추가해 로그아웃/탈퇴 요청이라면 httpClient.get().authProvider<BearerAuthProvider>()?.clearToken() 해당 구문을 추가하는 방식이 좋을까요?

install(HttpSend) {
    intercept { request ->
        val response = execute(request)

        val isLogoutOrWithdraw = request.url.encodedPath in listOf(
            "/api/auth/logout",
            "/api/members/withdraw"
        )

        if (isLogoutOrWithdraw && response.response.status.isSuccess()) {
            authProvider<BearerAuthProvider>()?.clearToken()
        }

        response
    }
}

익성님 의견은 어떠신지 궁금합니다.

@Ojongseok Ojongseok requested a review from ikseong00 March 2, 2026 10:09
@Ojongseok Ojongseok self-assigned this Mar 2, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 2, 2026

Walkthrough

Ktor 3.4.0로 업그레이드하면서 수동 토큰 캐시(AuthCacheManager)를 제거하고, NetworkModule에서 Ktor의 내장 토큰 캐싱을 활성화하며(TokenRepository 및 호출부의 메서드명 변경 포함), 빌드 로직의 Kotlin JVM 타겟 설정 방식을 Kotlin DSL로 전환했습니다.

Changes

Cohort / File(s) Summary
Build configuration / Kotlin DSL
build-logic/src/main/java/com/neki/android/buildlogic/extensions/Android.kt
기존 configureAndroidOptions 확장 제거 후 KotlinAndroidProjectExtension 기반 DSL로 JVM 타겟 설정 방식으로 변경. 관련 ExtensionAware/KotlinJvmOptions imports 제거 및 교체.
토큰 캐시 제거 및 Ktor 캐싱 활성화
core/data-api/src/main/java/com/neki/android/core/dataapi/auth/AuthCacheManager.kt, core/data/src/main/java/com/neki/android/core/data/remote/di/NetworkModule.kt
AuthCacheManager 인터페이스 삭제. NetworkModule에서 Ktor cacheTokens = !BuildConfig.DEBUG 설정 추가로 내장 토큰 캐싱 사용, 기존 제공자(provideAuthCacheManager) 제거 및 인증 실패 시 토큰 무효화 흐름 조정.
토큰 저장소 변경
core/data/src/main/java/com/neki/android/core/data/repository/impl/TokenRepositoryImpl.kt, core/data-api/src/main/java/com/neki/android/core/dataapi/repository/TokenRepository.kt, feature/mypage/impl/.../MyPageViewModel.kt
TokenRepository API clearTokens()clearTokensWithAuthCache()로 이름 변경. TokenRepositoryImplAuthCacheManager 대신 Lazy<HttpClient>를 주입받고, 토큰 삭제 시 httpClient.get().authProvider<BearerAuthProvider>()?.clearToken() 호출로 Ktor 캐시를 직접 정리하도록 변경. 호출부(MyPageViewModel)의 호출명 업데이트.
의존성 버전 업그레이드
gradle/libs.versions.toml
Kotlin, KSP, Hilt, Ktor 등 버전 상향: kotlin/jetbrainsKotlinJvm 2.1.0→2.3.0, ksp 2.1.0-1.0.29→2.3.0, hilt 2.54→2.58, ktor 2.3.12→3.4.0 등; jetbrainsKotlinJvmVersion 제거 및 플러그인 매핑 업데이트.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant Ktor as Ktor(HttpClient)
    participant Network as NetworkModule
    participant Repo as TokenRepositoryImpl
    participant Store as Datastore
    participant AuthEvt as AuthEventManager

    Note over Ktor: cacheTokens = !BuildConfig.DEBUG (enabled)
    Client->>Ktor: API 요청 (Bearer 토큰 포함)
    Ktor-->>Client: 401 Unauthorized
    Network->>Repo: refreshToken() 호출
    Repo->>Ktor: 요청 (토큰 갱신)
    alt refresh 성공
        Repo->>Store: saveTokens(...)
        Repo-->>Ktor: 새 토큰으로 응답 흐름 재시도 (자동 캐시 사용)
    else refresh 실패
        Repo->>Ktor: authProvider.clearToken()  rgba(255,0,0,0.5)
        Repo->>Store: clear token 데이터 (clearTokensWithAuthCache)
        Repo->>AuthEvt: emit(TokenExpired)
    end
    AuthEvt->>Client: 토큰 만료 이벤트 전파
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 토큰은 이제 Ktor가 맡겼네,
수동선은 사라지고 흐름은 가벼워졌네.
버전은 쑥쑥, 코드도 쓱쓱,
디버그만 피하면 캐시가 반짝✨
토끼가 축하한다고 깡총깡총! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항(HttpClient 토큰 캐싱 옵션 설정 추가 및 API 버전 상향)을 명확하고 간결하게 요약하고 있습니다.
Linked Issues check ✅ Passed 모든 코드 변경사항이 #162 이슈의 요구사항을 충족합니다: Ktor 3.4.0 업그레이드, 관련 도구 버전 상향, AuthCacheManager 제거, 환경별 토큰 캐싱 제어.
Out of Scope Changes check ✅ Passed 모든 변경사항이 #162의 목표 범위 내에 있으며 기술 부채 제거 및 토큰 캐싱 최적화에 정확히 부합합니다.
Description check ✅ Passed PR 설명이 필수 섹션인 관련 이슈, 작업 설명, 테스트 내역을 모두 포함하고 있으며, 변경 사항이 명확하게 기술되어 있습니다.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/#162-disable-ktor-token-caching

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@build-logic/src/main/java/com/neki/android/buildlogic/extensions/Android.kt`:
- Around line 30-34: The direct call to
extensions.configure<KotlinAndroidProjectExtension>("kotlin") can throw if the
Kotlin Android plugin isn't applied; guard this configuration with a plugin
check (e.g., use pluginManager.withPlugin("org.jetbrains.kotlin.android") or
plugins.withId) before calling configure so the block that sets compilerOptions
and jvmTarget (referencing KotlinAndroidProjectExtension, "kotlin",
compilerOptions, jvmTarget, BuildConst.JDK_VERSION) only runs when the Kotlin
Android plugin is present.

In
`@core/data/src/main/java/com/neki/android/core/data/remote/di/NetworkModule.kt`:
- Line 75: The Ktor bearer token caching is enabled by cacheTokens =
!BuildConfig.DEBUG, which allows a cached in-memory token to persist after
TokenRepository.clearTokens() is called; to fix, either set cacheTokens = false
in the NetworkModule configuration (disable caching), or add explicit
invalidation on logout by recreating the HttpClient or clearing Ktor's bearer
auth cache when TokenRepository.clearTokens() is invoked; reference the
cacheTokens configuration in NetworkModule, TokenRepository.clearTokens(), and
the HttpClient/bearer auth setup to implement one of these approaches so logout
truly prevents reuse of the old token.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eae358f and be1c065.

📒 Files selected for processing (5)
  • build-logic/src/main/java/com/neki/android/buildlogic/extensions/Android.kt
  • core/data-api/src/main/java/com/neki/android/core/dataapi/auth/AuthCacheManager.kt
  • core/data/src/main/java/com/neki/android/core/data/remote/di/NetworkModule.kt
  • core/data/src/main/java/com/neki/android/core/data/repository/impl/TokenRepositoryImpl.kt
  • gradle/libs.versions.toml
💤 Files with no reviewable changes (2)
  • core/data/src/main/java/com/neki/android/core/data/repository/impl/TokenRepositoryImpl.kt
  • core/data-api/src/main/java/com/neki/android/core/dataapi/auth/AuthCacheManager.kt

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

🧹 Nitpick comments (1)
core/data-api/src/main/java/com/neki/android/core/dataapi/repository/TokenRepository.kt (1)

13-13: 퍼블릭 API 네이밍에서 구현 디테일 노출을 줄이는 것을 권장합니다.

clearTokensWithAuthCache()는 데이터 API 계약에 인프라 세부사항이 드러납니다. 인터페이스는 clearTokens()처럼 의도 중심으로 유지하고, Auth 캐시 정리는 구현체 내부 책임으로 두는 편이 변경 내성이 좋습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/data-api/src/main/java/com/neki/android/core/dataapi/repository/TokenRepository.kt`
at line 13, Rename the public interface method clearTokensWithAuthCache() to a
more intention-revealing name like clearTokens() on TokenRepository and move any
Auth cache-specific logic into the concrete implementation (e.g., the class
implementing TokenRepository) so the interface no longer exposes infrastructure
details; update all callers to use TokenRepository.clearTokens() and keep cache
clearing as an internal step inside the implementation's clearTokens() method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@core/data/src/main/java/com/neki/android/core/data/repository/impl/TokenRepositoryImpl.kt`:
- Around line 59-64: clearTokensWithAuthCache currently performs
authProvider.clearToken() then dataStore.edit sequentially so a failure in the
first prevents the second from running; change it to run each cleanup in its own
runCatching block so both are attempted: wrap the
httpClient.get().authProvider<BearerAuthProvider>()?.clearToken() call in
runCatching and wrap the dataStore.edit { preferences.remove(ACCESS_TOKEN);
preferences.remove(REFRESH_TOKEN) } call in a separate runCatching, then if
either runCatching failed, rethrow a combined exception (e.g., aggregate the
non-null exceptions or throw the first with the second as suppressed) so callers
still receive an error but both cleanup attempts were made.

---

Nitpick comments:
In
`@core/data-api/src/main/java/com/neki/android/core/dataapi/repository/TokenRepository.kt`:
- Line 13: Rename the public interface method clearTokensWithAuthCache() to a
more intention-revealing name like clearTokens() on TokenRepository and move any
Auth cache-specific logic into the concrete implementation (e.g., the class
implementing TokenRepository) so the interface no longer exposes infrastructure
details; update all callers to use TokenRepository.clearTokens() and keep cache
clearing as an internal step inside the implementation's clearTokens() method.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be1c065 and 0a2c091.

📒 Files selected for processing (4)
  • core/data-api/src/main/java/com/neki/android/core/dataapi/repository/TokenRepository.kt
  • core/data/src/main/java/com/neki/android/core/data/remote/di/NetworkModule.kt
  • core/data/src/main/java/com/neki/android/core/data/repository/impl/TokenRepositoryImpl.kt
  • feature/mypage/impl/src/main/java/com/neki/android/feature/mypage/impl/main/MyPageViewModel.kt

Copy link
Contributor

@ikseong00 ikseong00 left a comment

Choose a reason for hiding this comment

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

로그아웃/탈퇴는 비교적 적게 발생하는 API 인데, 인터셉터를 붙이면은 필요할 때보다,
불필요한 상황(ex) 사진 조회, 지도 핀 조회 등등)에서 조건이 많이 걸릴 것 같아요.

그래서 필요시 해당 clearToken() 함수를 직접 호출하는 형식으로 하고, 그렇게 하기 위해서 Lazy 를 넣는 방향이 조금 더 나은 것 같습니다

@Ojongseok Ojongseok merged commit 9c4c4aa into develop Mar 2, 2026
4 checks passed
@Ojongseok Ojongseok deleted the refactor/#162-disable-ktor-token-caching branch March 2, 2026 23:12
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.

[refactor] Ktor(HttpClient) 토큰 자동 캐싱 옵션 비활성화

2 participants