Skip to content

[fix] splash화면에서 간헐적으로 넘어가지 않는 오류 수정#650

Open
yrsel wants to merge 11 commits intodevelopfrom
feature/#591
Open

[fix] splash화면에서 간헐적으로 넘어가지 않는 오류 수정#650
yrsel wants to merge 11 commits intodevelopfrom
feature/#591

Conversation

@yrsel
Copy link
Copy Markdown
Contributor

@yrsel yrsel commented Mar 27, 2026

Issues

✔️ Check-list

  • : Label을 지정해 주세요.
  • : Merge할 브랜치를 확인해 주세요.

🗒️ Work Description

1. 액세스 토큰과 리프레시 토큰이 모두 만료된 상황에서 재발급이 실패하는 문제 해결

문제 원인

Ktor의 Auth 플러그인에서 loadTokens { }를 통해 Bearer 토큰을 자동으로 Authorization 헤더에 추가하는데, 이 설정이 refreshTokens { } 블럭 내부에서 수행되는 토큰 재발급 요청에도 동일하게 적용되는 문제가 있었습니다.

그 결과, 리프레시 토큰이 유효한 경우에도 만료된 액세스 토큰이 Authorization 헤더에 포함된 상태로 요청이 전송되었고,
서버에서 이를 인증 실패로 판단하여 401 응답을 반환하는 문제가 발생했습니다.

해결 방법

토큰 재발급 요청에는 Authorization 헤더가 포함되지 않도록 네트워크 계층을 분리했습니다.

  • Authorization 헤더 포함 여부에 따라 Ktor HttpClient를 분리
  • 각각의 HttpClient를 기반으로 Ktorfit 인스턴스를 별도로 생성
  • 동일한 인터페이스를 유지하면서 Qualifier를 활용해 상황에 맞는 구현을 주입하도록 구성

이를 통해 토큰 재발급 요청이 인증 헤더의 영향을 받지 않도록 보장했습니다.

2. 세션 상태 및 토큰 초기화 시점 관리를 위한 SessionManager 도입

  • 세션 만료 및 로그아웃 상황에서 토큰을 일관되게 관리할 수 있도록 단일 책임 객체인 SessionManager를 도입했습니다.
  • 커밋 내역: 223cd95

3. DataSource 네이밍 컨벤션 정리

  • DataSource 파일 중 일부가 컨벤션이 지켜지지 않아 수정했습니다.
  • 커밋 내역: f193e2d

4. 로그인 중단 시 잘못된 에러 메시지 노출 문제 수정

  • 사용자가 로그인 과정에서 이탈한 경우에도 서버 에러 메시지가 노출되던 문제를 수정했습니다.
  • 커밋 내역: 3568a69

📷 Screenshot

세션 만료

default.webm

리프레시토큰으로 토큰 갱신

default.webm

📚 Reference

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 세션 전환 관리자 추가로 로그인/게스트 전환이 일관되게 처리됨
    • 초기 인증 상태 판별 후 자동으로 적절한 화면으로 이동
  • Bug Fixes

    • 토큰 재발급·검증 흐름 개선으로 인증 실패 시 앱 내 복구 안정성 향상
    • 토큰 만료 발생 시 자동으로 게스트 상태 전환 및 로그인 안내 적용
  • Refactor

    • 인증·세션 및 네트워크 계층 구조 재정비로 모듈화 및 유지보수성 향상

@yrsel yrsel self-assigned this Mar 27, 2026
@yrsel yrsel added 🌰 채넛 우아한 테크코스 7기 안드로이드 채넛 🤖 Android 안드로이드얌 refactor labels Mar 27, 2026
@github-actions github-actions bot requested a review from jerry8282 March 27, 2026 05:15
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

Walkthrough

세션 관리 구현을 SessionStore에서 새로운 싱글톤 SessionManager로 전환하고, 인증 관련 리모트 데이터소스를 재분리(AuthRemoteDataSource, AuthRefreshRemoteDataSource)하며 여러 qualified DI HttpClient/Ktorfit 인스턴스를 도입해 네트워크·에러 처리 로직과 DI 바인딩을 재구성했습니다.

Changes

Cohort / File(s) Summary
SessionManager 추가 / SessionStore 제거
android/app/src/main/java/com/on/turip/core/session/SessionManager.kt, android/app/src/main/java/com/on/turip/domain/session/SessionStore.kt, android/app/src/main/java/com/on/turip/data/session/DefaultSessionStore.kt, android/app/src/main/java/com/on/turip/di/SessionModule.kt
새로운 SessionManager 싱글톤 추가; 기존 SessionStore 인터페이스 및 DefaultSessionStore 구현과 DI 바인딩 제거.
세션 상태 타입 이동 / AuthStatus 추가
android/app/src/main/java/com/on/turip/core/session/SessionState.kt, android/app/src/main/java/com/on/turip/domain/session/AuthStatus.kt
SessionState 패키지 이동(domain.sessioncore.session), AuthStatus 봉인 인터페이스 추가.
Auth 리모트 데이터소스 분리 및 구현 추가
.../data/login/datasource/AuthDataSource.kt, AuthRemoteDataSource.kt, AuthRefreshRemoteDataSource.kt, DefaultAuthRemoteDataSource.kt, DefaultAuthRefreshRemoteDataSource.kt
기존 AuthDataSource 제거·리팩토링, AuthRemoteDataSource를 인터페이스로 변경하고 리프레시 전용 AuthRefreshRemoteDataSource 추가 및 각각의 Default* 구현체 추가.
Guest/Member RemoteDataSource 리팩토링 및 Default 구현 추가
.../data/login/datasource/GuestDataSource.kt, GuestRemoteDataSource.kt, DefaultGuestRemoteDataSource.kt, MemberDataSource.kt, MemberRemoteDataSource.kt, DefaultMemberRemoteDataSource.kt
GuestDataSource/MemberDataSource 제거, *RemoteDataSource를 인터페이스로 변경하고 Default*RemoteDataSource 구현 추가.
Repository 의존성 업데이트
android/app/src/main/java/com/on/turip/data/login/repository/DefaultAuthRepository.kt, DefaultGuestRepository.kt, DefaultMemberRepository.kt
리포지토리들이 *DataSource*RemoteDataSource(및 리프레시 전용 데이터소스)로 의존성 변경; 토큰 검증 호출이 새 인터페이스로 대체됨.
AuthService API 변경
android/app/src/main/java/com/on/turip/data/login/service/AuthService.kt
토큰 검증 엔드포인트 서명 변경: getTokenVerification(@Header token)verifyToken() (헤더 파라미터 제거).
API 오류 모델 및 safeApiCall 개선
android/app/src/main/java/com/on/turip/data/result/ApiException.kt, SafeApiCall.kt
ApiException 봉인 클래스 추가 및 safeApiCall에서 ApiException별 분기 처리 추가(네트워크/인증/에러 매핑).
Network DI: 다중 HttpClient/Ktorfit 도입 및 에러 흐름 변경
android/app/src/main/java/com/on/turip/di/NetworkModule.kt, ServiceModule.kt, DataSourceModule.kt
단일 HttpClient/Ktorfit → @Default, @NoAuth, @Sse 한정자별 인스턴스 제공; AuthService에 대해 @DefaultAuthService/@NoAuthAuthService 추가; 토큰 리프레시 실패 시 ApiException 던지도록 로직 변경.
DI Qualifier 재배치/추가
android/app/src/main/java/com/on/turip/di/qualifier/NetworkQualifiers.kt, AuthQualifiers.kt, 삭제: android/app/src/main/java/com/on/turip/di/SseHttpClient.kt
새한정자 파일로 이동/추가(예: DefaultKtorfit, NoAuthKtorfit, DefaultHttpClient, NoAuthHttpClient, SseHttpClient, DefaultAuthService, NoAuthAuthService), 기존 SseHttpClient 파일 삭제.
토큰 캐시 컨트롤러 DI 어노테이션 업데이트
android/app/src/main/java/com/on/turip/data/session/DefaultAuthTokenCacheController.kt
Provider<HttpClient>@DefaultHttpClient 한정자 추가.
도메인/UseCase 리팩토링
.../domain/session/usecase/DetermineInitialSessionUseCase.kt, SwitchToGuestUseCase.kt(삭제), .../domain/invitation/usecase/DetermineInvitationEntryRouteUseCase.kt, .../domain/login/usecase/LoginUseCase.kt
SessionStore 의존 제거, 일부 UseCase가 SessionManager 또는 AuthStatus로 반환형/파라미터 변경, SwitchToGuestUseCase 삭제.
ViewModel/Compose 레이어: SessionManager 주입 및 인증 실패 처리 추가
android/app/src/main/java/com/on/turip/ui/compose/**/*ViewModel.kt, MyPageScreen.kt, MyPageSettingsSection.kt, LoginViewmodel.kt, 등 다수 파일
여러 ViewModel이 SessionStoreSessionManager 전환; TokenExpired/ErrorType.Auth처리 시 sessionManager.switchToGuest() 호출 추가 및 로그인 네비게이션 트리거 강화.
UI 에러 매핑 미세조정
android/app/src/main/java/com/on/turip/ui/common/error/UiErrorExtensions.kt
ErrorType.Auth.UnAuthorizedTokenExpired와 동일하게 매핑하도록 변경.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ViewModel
    participant AuthRemoteDataSource
    participant AuthService
    participant TokenManager
    participant SessionManager

    User->>ViewModel: loginWithIdToken(idToken)
    ViewModel->>AuthRemoteDataSource: postIdToken(idToken)
    AuthRemoteDataSource->>AuthService: POST /auth/tokens (idToken)
    AuthService-->>AuthRemoteDataSource: LoginJwtTokenResponse
    AuthRemoteDataSource-->>ViewModel: TuripResult.Success(tokens)
    ViewModel->>TokenManager: setTokens(tokens)
    TokenManager-->>ViewModel: Result.Success
    ViewModel->>SessionManager: switchToMember()
    SessionManager->>SessionManager: _state.value = SessionState.Member
    SessionManager-->>ViewModel: done
Loading
sequenceDiagram
    participant App
    participant SplashViewModel
    participant DetermineInitialSessionUseCase
    participant AuthRepository
    participant AuthRemoteDataSource
    participant SessionManager

    App->>SplashViewModel: determineStartDestination()
    SplashViewModel->>DetermineInitialSessionUseCase: invoke()
    DetermineInitialSessionUseCase->>AuthRepository: verifyToken()
    AuthRepository->>AuthRemoteDataSource: verifyToken()
    AuthRemoteDataSource-->>AuthRepository: TuripResult (Success|Failure)
    DetermineInitialSessionUseCase-->>SplashViewModel: AuthStatus.Authenticated / UnAuthenticated
    alt Authenticated
        SplashViewModel->>SessionManager: switchToMember()
    else UnAuthenticated
        SplashViewModel->>SessionManager: switchToGuest()
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.71% 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 제목이 주요 변경사항인 Splash 화면 네비게이션 오류 수정을 명확히 설명하고 있으며, 변경의 핵심 내용을 간결하게 요약하고 있습니다.
Description check ✅ Passed PR 설명이 템플릿의 주요 섹션(Issues, Check-list, Work Description, Screenshot, Reference)을 대부분 포함하고 있으며, 4개의 구체적인 작업 항목을 자세히 설명하고 있습니다.
Linked Issues check ✅ Passed 토큰 재발급 신뢰성 확보, 네트워크 계층 분리, SessionManager 도입, 세션 상태 관리 일원화 등 #591의 모든 주요 목표들이 코드 변경으로 구현되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 토큰 재발급 오류 해결, SessionManager 도입, DataSource 컨벤션 정리, 로그인 에러 메시지 처리 등 #591의 범위 내에 있습니다.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#591

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

🧹 Nitpick comments (1)
android/app/src/main/java/com/on/turip/data/result/ApiException.kt (1)

5-13: 잘 설계된 예외 계층 구조입니다.

sealed class를 사용하여 SafeApiCall에서 exhaustive한 when 표현식을 보장합니다.

선택적 개선 제안: 디버깅 및 로깅을 위해 message 또는 cause 속성을 추가하는 것을 고려해 볼 수 있습니다.

♻️ 선택적 개선안
-sealed class ApiException : Exception() {
+sealed class ApiException(
+    message: String? = null,
+    cause: Throwable? = null,
+) : Exception(message, cause) {
     data class Error(
         val errorType: ErrorType,
-    ) : ApiException()
+        override val message: String? = null,
+    ) : ApiException(message)

-    data object Auth : ApiException()
+    data object Auth : ApiException("Authentication failed")

-    data object Network : ApiException()
+    data object Network : ApiException("Network error")
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@android/app/src/main/java/com/on/turip/data/result/ApiException.kt` around
lines 5 - 13, Add optional message and/or cause to the ApiException hierarchy so
callers and logs can include debug context: update sealed class ApiException and
its subclasses (ApiException.Error, ApiException.Auth, ApiException.Network) to
accept an optional message: String? and/or cause: Throwable? (preserve existing
ErrorType on ApiException.Error) and propagate these parameters when
constructing exceptions in SafeApiCall and other throw sites so logs can read
exception.message and exception.cause.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@android/app/src/main/java/com/on/turip/core/session/SessionManager.kt`:
- Around line 21-27: switchToGuest currently swallows tokenManager.clearTokens()
failures and sets _state before knowing if clear succeeded; change its signature
to return Result<Unit> (e.g., suspend fun switchToGuest(): Result<Unit>), call
tokenManager.clearTokens(), if it fails return that Result immediately (do not
set _state), and only on success set _state.value = SessionState.Guest and
return Result.success(Unit); reference tokenManager.clearTokens(), _state, and
SessionState.Guest to locate the change.

In `@android/app/src/main/java/com/on/turip/data/result/SafeApiCall.kt`:
- Around line 17-22: The handling of ApiException.Error in SafeApiCall.kt
flattens to ErrorType.Unknown because e.toErrorType() doesn't read the embedded
errorType; update the catch branch to use the actual stored value (e.errorType)
or fix ApiException.Error.toErrorType() to return its internal errorType so the
TuripResult.Failure contains the original error type (refer to
ApiException.Error and the toErrorType/errorType symbols when making the
change).

In
`@android/app/src/main/java/com/on/turip/ui/compose/invitation/InvitationEntryViewModel.kt`:
- Around line 144-147: In confirmEnterInvitedTurip() add the same session
cleanup call as in the other branch by invoking switchToGuest() before sending
the navigation effect on authentication errors; specifically, locate the
auth-error handling that currently does
_uiEffect.send(InvitationEntryUiEffect.NavigateToLogin) and insert a call to
switchToGuest() (or ensure switchToGuest() is called) prior to returning so the
session is cleared on ErrorType.Auth.
- Around line 96-99: In InvitationEntryViewModel, when handling result.errorType
== ErrorType.Auth, call sessionManager.switchToGuest() before emitting
_uiEffect.send(InvitationEntryUiEffect.NavigateToLogin) so the token/session is
cleared and the app state becomes Guest; ensure sessionManager is provided as a
private constructor property on InvitationEntryViewModel (matching other
ViewModels) so switchToGuest() is accessible and invoked prior to the
NavigateToLogin emission.

In `@android/app/src/main/java/com/on/turip/ui/compose/mypage/MyPageViewModel.kt`:
- Around line 102-109: The error handling for session expiration is duplicated
only in the bookmark failure branch; centralize session-expiry handling so all
failures (e.g., loadProfile() and bookmark fetches) behave the same. Extract the
auth-check into a shared helper (e.g., handleError(errorType: ErrorType) or
unify into existing handleError()), have that helper call
sessionManager.switchToGuest() and send MyPageUiEffect.NavigateToLogin via
_uiEffect, and replace the inline session checks in onFailure blocks (including
the bookmark onFailure and loadProfile() failure) to call this helper instead.

In
`@android/app/src/main/java/com/on/turip/ui/compose/turipdetail/TuripDetailViewModel.kt`:
- Around line 713-715: In observeTuripStream(), handle the
TuripStreamResult.Fatal.TokenExpired branch the same way as sendErrorEffect():
call sessionManager.switchToGuest() to clear session state and then send the
navigation effect; specifically, update the TuripStreamResult.Fatal.TokenExpired
branch (in observeTuripStream()) to invoke sessionManager.switchToGuest() before
_uiEffect.send(TuripDetailUiEffect.NavigateToLogin) so session state remains
consistent with the other token-expiry paths.

---

Nitpick comments:
In `@android/app/src/main/java/com/on/turip/data/result/ApiException.kt`:
- Around line 5-13: Add optional message and/or cause to the ApiException
hierarchy so callers and logs can include debug context: update sealed class
ApiException and its subclasses (ApiException.Error, ApiException.Auth,
ApiException.Network) to accept an optional message: String? and/or cause:
Throwable? (preserve existing ErrorType on ApiException.Error) and propagate
these parameters when constructing exceptions in SafeApiCall and other throw
sites so logs can read exception.message and exception.cause.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 96544566-d8fd-409a-afd3-a237da655e1e

📥 Commits

Reviewing files that changed from the base of the PR and between 1b13c71 and e9644f3.

📒 Files selected for processing (51)
  • android/app/src/main/java/com/on/turip/core/session/SessionManager.kt
  • android/app/src/main/java/com/on/turip/core/session/SessionState.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/AuthDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/AuthRefreshRemoteDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/AuthRemoteDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/DefaultAuthRefreshRemoteDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/DefaultAuthRemoteDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/DefaultGuestRemoteDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/DefaultMemberRemoteDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/GuestDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/GuestRemoteDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/MemberDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/MemberRemoteDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/repository/DefaultAuthRepository.kt
  • android/app/src/main/java/com/on/turip/data/login/repository/DefaultGuestRepository.kt
  • android/app/src/main/java/com/on/turip/data/login/repository/DefaultMemberRepository.kt
  • android/app/src/main/java/com/on/turip/data/login/service/AuthService.kt
  • android/app/src/main/java/com/on/turip/data/result/ApiException.kt
  • android/app/src/main/java/com/on/turip/data/result/SafeApiCall.kt
  • android/app/src/main/java/com/on/turip/data/session/DefaultAuthTokenCacheController.kt
  • android/app/src/main/java/com/on/turip/data/session/DefaultSessionStore.kt
  • android/app/src/main/java/com/on/turip/data/turip/service/DefaultTuripStreamService.kt
  • android/app/src/main/java/com/on/turip/di/DataSourceModule.kt
  • android/app/src/main/java/com/on/turip/di/NetworkModule.kt
  • android/app/src/main/java/com/on/turip/di/ServiceModule.kt
  • android/app/src/main/java/com/on/turip/di/SessionModule.kt
  • android/app/src/main/java/com/on/turip/di/SseHttpClient.kt
  • android/app/src/main/java/com/on/turip/di/qualifier/AuthQualifiers.kt
  • android/app/src/main/java/com/on/turip/di/qualifier/NetworkQualifiers.kt
  • android/app/src/main/java/com/on/turip/domain/invitation/usecase/DetermineInvitationEntryRouteUseCase.kt
  • android/app/src/main/java/com/on/turip/domain/login/AuthRepository.kt
  • android/app/src/main/java/com/on/turip/domain/login/usecase/LoginUseCase.kt
  • android/app/src/main/java/com/on/turip/domain/session/AuthStatus.kt
  • android/app/src/main/java/com/on/turip/domain/session/SessionStore.kt
  • android/app/src/main/java/com/on/turip/domain/session/usecase/DetermineInitialSessionUseCase.kt
  • android/app/src/main/java/com/on/turip/domain/session/usecase/SwitchToGuestUseCase.kt
  • android/app/src/main/java/com/on/turip/ui/common/error/UiErrorExtensions.kt
  • android/app/src/main/java/com/on/turip/ui/compose/bookmark/BookmarkContentListViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/home/HomeViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/invitation/InvitationEntryViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/login/LoginViewmodel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/mypage/MyPageScreen.kt
  • android/app/src/main/java/com/on/turip/ui/compose/mypage/MyPageViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/mypage/component/MyPageSettingsSection.kt
  • android/app/src/main/java/com/on/turip/ui/compose/search/keyword/SearchViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/search/regionresult/RegionResultViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/splash/SplashViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/trip/TripDetailViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/trip/turipselection/PlaceTuripSelectionViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/turip/MyTuripViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/turipdetail/TuripDetailViewModel.kt
💤 Files with no reviewable changes (8)
  • android/app/src/main/java/com/on/turip/data/login/datasource/GuestDataSource.kt
  • android/app/src/main/java/com/on/turip/di/SseHttpClient.kt
  • android/app/src/main/java/com/on/turip/di/SessionModule.kt
  • android/app/src/main/java/com/on/turip/domain/session/usecase/SwitchToGuestUseCase.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/MemberDataSource.kt
  • android/app/src/main/java/com/on/turip/data/login/datasource/AuthDataSource.kt
  • android/app/src/main/java/com/on/turip/domain/session/SessionStore.kt
  • android/app/src/main/java/com/on/turip/data/session/DefaultSessionStore.kt

- SafeApiCall: ApiException에서 담아오는 ErrorType 활용하도록 수정
- InvitationEntryViewModel, TuripDetailViewModel: 토큰 만료시 세션 전환하도록 수정
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.

🧹 Nitpick comments (1)
android/app/src/main/java/com/on/turip/ui/compose/turipdetail/TuripDetailViewModel.kt (1)

192-193: 인증 실패 공통 처리 로직을 헬퍼로 추출해 중복을 줄이는 것을 권장합니다.

동일한 “게스트 전환 + 로그인 이동” 시퀀스가 여러 군데 반복되어 있어, 다음 수정 때 일부 분기만 누락될 위험이 있습니다.

♻️ 제안 diff
 class TuripDetailViewModel `@Inject` constructor(
@@
 ) : ViewModel() {
+    private suspend fun switchToGuestAndNavigateLogin() {
+        sessionManager.switchToGuest()
+        _uiEffect.send(TuripDetailUiEffect.NavigateToLogin)
+    }
@@
-                        TuripStreamResult.Fatal.TokenExpired -> {
-                            sessionManager.switchToGuest()
-                            _uiEffect.send(TuripDetailUiEffect.NavigateToLogin)
-                        }
+                        TuripStreamResult.Fatal.TokenExpired -> {
+                            switchToGuestAndNavigateLogin()
+                        }
@@
-                        if (errorType is ErrorType.Auth) {
-                            sessionManager.switchToGuest()
-                            _uiEffect.send(TuripDetailUiEffect.NavigateToLogin)
+                        if (errorType is ErrorType.Auth) {
+                            switchToGuestAndNavigateLogin()
                             return@onFailure
                         }
@@
-                    if (errorType is ErrorType.Auth) {
-                        sessionManager.switchToGuest()
-                        _uiEffect.send(TuripDetailUiEffect.NavigateToLogin)
+                    if (errorType is ErrorType.Auth) {
+                        switchToGuestAndNavigateLogin()
                         return@onFailure
                     }
@@
                 UiError.Global.TokenExpired -> {
-                    sessionManager.switchToGuest()
-                    _uiEffect.send(TuripDetailUiEffect.NavigateToLogin)
+                    switchToGuestAndNavigateLogin()
                 }

Also applies to: 357-359, 541-543, 715-716

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

In
`@android/app/src/main/java/com/on/turip/ui/compose/turipdetail/TuripDetailViewModel.kt`
around lines 192 - 193, Extract the repeated "switch to guest then navigate to
login" sequence into a single helper method on TuripDetailViewModel (e.g.,
handleAuthFailureAndNavigateToLogin) that calls sessionManager.switchToGuest()
and _uiEffect.send(TuripDetailUiEffect.NavigateToLogin), then replace the
duplicated blocks (currently using sessionManager.switchToGuest() followed by
_uiEffect.send(TuripDetailUiEffect.NavigateToLogin)) with a call to this new
helper; ensure the helper is used in all occurrences (including the ones around
the other noted locations) to avoid future omissions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@android/app/src/main/java/com/on/turip/ui/compose/turipdetail/TuripDetailViewModel.kt`:
- Around line 192-193: Extract the repeated "switch to guest then navigate to
login" sequence into a single helper method on TuripDetailViewModel (e.g.,
handleAuthFailureAndNavigateToLogin) that calls sessionManager.switchToGuest()
and _uiEffect.send(TuripDetailUiEffect.NavigateToLogin), then replace the
duplicated blocks (currently using sessionManager.switchToGuest() followed by
_uiEffect.send(TuripDetailUiEffect.NavigateToLogin)) with a call to this new
helper; ensure the helper is used in all occurrences (including the ones around
the other noted locations) to avoid future omissions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f64fbb7f-e6cd-4940-b139-78832e20b13e

📥 Commits

Reviewing files that changed from the base of the PR and between e9644f3 and 572b260.

📒 Files selected for processing (3)
  • android/app/src/main/java/com/on/turip/data/result/SafeApiCall.kt
  • android/app/src/main/java/com/on/turip/ui/compose/invitation/InvitationEntryViewModel.kt
  • android/app/src/main/java/com/on/turip/ui/compose/turipdetail/TuripDetailViewModel.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • android/app/src/main/java/com/on/turip/data/result/SafeApiCall.kt
  • android/app/src/main/java/com/on/turip/ui/compose/invitation/InvitationEntryViewModel.kt

Copy link
Copy Markdown
Contributor

@jerry8282 jerry8282 left a comment

Choose a reason for hiding this comment

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

깖끔한 코드 작성 너무 좋습니다 채넛!! 고생하셨습니다 몇가지 수정할 부분이 있어서 남겨보았습니다ㅎㅎ

) {
suspend operator fun invoke(): SessionState {
suspend operator fun invoke(): AuthStatus {
tokenManager.initialize()
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.

Suggested change
tokenManager.initialize()
tokenManager.initialize()
if (tokenManager.currentTokens == null) return AuthStatus.UnAuthenticated

r: 현재 게스트 상태일 때 오프라인으로 들어가면 홈화면으로 가지는데 위 코드를 추가해서 로그인 화면으로 가도록 해야 될 거 같습니다☺️

headerInterceptor(tokenManager, authRepository, fidProvider)
}
@DefaultKtorfit
fun provideDefaultKtrofit(
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.

a: provideDefaultKtorfit으로 네이밍 변경하면 좋겠네용ㅎㅎ

@Singleton
fun provideKtorfit(httpClient: HttpClient): Ktorfit =
@NoAuthKtorfit
fun provideNoAuthKtrofit(
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.

a: provideNoAuthKtrofit으로 네이밍 변경하면 좋겠네용ㅎㅎ

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.

r: 현재 SessionManager가 core인데 domain을 주입 받고 있어서 의존 방향이 이상한 거 같아요 domain으로 내려야 될 거 같아용

class DefaultGuestRemoteDataSource @Inject constructor(
private val guestService: GuestService,
) : GuestRemoteDataSource {
override suspend fun deleteGuest(): TuripResult<Unit> = safeApiCall { guestService.deleteGuest() }
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.

c: DefaultAuthRefreshRemoteDataSource에서 withContext로 전부 해주셔서 여기도 처리해주면 좋을 거 같아요!

Comment on lines +8 to +16
class DefaultMemberRemoteDataSource @Inject constructor(
private val memberService: MemberService,
) : MemberRemoteDataSource {
override suspend fun postMigration(): TuripResult<Unit> = safeApiCall { memberService.postMigration() }

override suspend fun postLogout(): TuripResult<Unit> = safeApiCall { memberService.postLogout() }

override suspend fun deleteMember(): TuripResult<Unit> = safeApiCall { memberService.deleteMember() }
}
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.

c: DefaultAuthRefreshRemoteDataSource에서 withContext로 전부 해주셔서 여기도 처리해주면 좋을 거 같아요!

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

Labels

🌰 채넛 우아한 테크코스 7기 안드로이드 채넛 🤖 Android 안드로이드얌 refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[fix] splash화면에서 간헐적으로 넘어가지 않는 오류 수정

2 participants