Skip to content

fix: 로그인 관련 API 에러 처리 방식 개선#196

Merged
easyhooon merged 8 commits intodevelopfrom
BOOK-367-feature/#195
Oct 21, 2025
Merged

fix: 로그인 관련 API 에러 처리 방식 개선#196
easyhooon merged 8 commits intodevelopfrom
BOOK-367-feature/#195

Conversation

@easyhooon
Copy link
Copy Markdown
Contributor

@easyhooon easyhooon commented Oct 20, 2025

누락된 ErrorScope.Login + Dialog 에러 처리 적용

🔗 관련 이슈

📙 작업 설명

지훈

  • 로그인 에러 발생시 에러 다이얼로그를 통해 사용자에게 안내

서윤

  • 에러 다이얼로그에 title 속성 추가
  • 로그인 세션 만료 시 다이얼로그 기반 에러 처리
  • 홈, 내서재 로그인 세션 만료 에러 대응

🧪 테스트 내역 (선택)

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

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

에러 처리 적용 전 적용 후

(최종)로그인 에러 다이얼로그 타이틀 적용

Reed_.mp4

로그인 세션 만료

Reed_.mp4

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

지훈

  • 기존에 정의되었던 전역 에러 다이얼로그 적용했는데, 문구 수정이 필요하다면 반영 하도록 하겠습니다.(서버 에러일 경우 다시 로그인하는게 의미가 없을 수 있기에)

서윤

@easyhooon 에러 핸들링 정책 리마인드 (연관 PR: #118 (comment))

✅ 전체 화면 에러 (화면에 데이터를 불러와 렌더링 해야하는 경우)

  • 네트워크 에러 문구 : 네트워크 연결이 불안정합니다. 인터넷 연결을 확인해주세요
  • 그 외 서버 에러 문구 : 알 수 없는 문제가 발생했어요. 다시 시도해주세요

✅ 토스트 메세지 (이미 화면을 보고 있는 상태에서 요청이 있는 경우)

  • 네트워크 에러 문구 : 네트워크 연결이 불안정합니다. 인터넷 연결을 확인해주세요
  • 그 외 서버 에러 문구 : 서버 errorBody 파싱해서 사용

✅ 다이얼로그 (특수한 상황 ex.로그인 에러, 세션 만료 에러)

image image

Summary by CodeRabbit

변경 요약

  • 버그 수정

    • 로그인/프로필 실패 시 즉시 토스트 대신 통합된 대화형 오류 창으로 표시됩니다.
    • 세션 만료 시 별도 안내 대화창으로 재로그인 안내가 제공됩니다.
    • 로그인 실패 시 메시지 누락 시에도 기본 안내 문구가 표시됩니다.
  • 개선

    • 오류 대화창에 선택적 제목이 추가되어 안내가 더 직관적으로 전달됩니다.
    • 홈·라이브러리 오류 시 필요한 경우 자동으로 로그인 화면으로 이동해 흐름이 개선되었습니다.

누락된 ErrorScope.Login + Dialog 에러 처리 적용
@github-actions github-actions Bot added the 🐞 fix Something isn't working label Oct 20, 2025
@github-actions github-actions Bot requested a review from seoyoon513 October 20, 2025 07:57
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Oct 20, 2025

Walkthrough

로그인 및 공통 에러 처리 흐름을 토스트 기반 사이드 이펙트에서 중앙화된 에러 다이얼로그 흐름으로 전환했습니다. ErrorDialogSpec에 선택적 제목이 추가되고 ErrorScope에 AUTH_SESSION_EXPIRED가 도입됐으며, HandleException과 여러 Presenter에서 다이얼로그 호출 및 로그인 재유도 로직이 사용되도록 변경되었습니다. KakaoLogin 사이드이펙트는 인스턴스화 가능한 클래스가 되었습니다.

Changes

응집 / 파일(s) 요약
로그인 프레젠터
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt
로그인/프로필 실패 경로에서 per-event 토스트(LoginSideEffect.ShowToast) 대신 postErrorDialog(ErrorScope.LOGIN, exception, ...) 호출로 전환; KakaoLogin() 인스턴스화 사용; 실패 로깅 유지
로그인 UI 상태
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUiState.kt
data object KakaoLogindata class KakaoLogin(private val key: String = UUID.randomUUID().toString())로 변경(인스턴스별 고유 키 도입, 동등성/인스턴스화 방식 변경)
공통 에러 스펙
core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorDialogSpec.kt
ErrorDialogSpec에 선택적 title: String? = null 속성 추가(데이터 클래스 생성자 변경)
에러 범위(enum)
core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorScope.kt
ErrorScope 멤버 업데이트: 기존 GLOBAL, LOGIN, BOOK_REGISTER, RECORD_REGISTERGLOBAL, LOGIN, AUTH_SESSION_EXPIRED (BOOK_REGISTER, RECORD_REGISTER 제거; AUTH_SESSION_EXPIRED 추가)
예외 처리 유틸리티
core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt
postErrorDialog 재작성: 예외 유형·스코프 기반으로 (title, message) 결정 후 ErrorDialogSpec(title, message, buttonLabelResId, action) 생성 및 즉시 전송; 401(HttpException) 시 AUTH_SESSION_EXPIRED 스코프와 onLoginRequired 연결; 기존 buildDialog 제거
메인 액티비티 다이얼로그
feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/MainActivity.kt
ReedDialog 호출에 title = spec.title 인자 추가하여 다이얼로그 제목 전달
홈 / 라이브러리 Presenter
feature/home/src/main/kotlin/.../HomePresenter.kt, feature/library/src/main/kotlin/.../LibraryPresenter.kt
데이터 로드 실패 시 기존 UiState 설정 유지하면서 handleException(exception, onLoginRequired = { navigator.resetRoot(LoginScreen()) }) 호출 추가; Library에서 게스트인지 검사하여 필터 동작 조건화

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Presenter
    participant Server
    participant HandleException
    participant ErrorEventBus
    participant MainActivity

    User->>Presenter: 요청 (로그인/데이터)
    Presenter->>Server: API 호출
    Server-->>Presenter: 예외 응답
    Presenter->>HandleException: postErrorDialog(exception, ErrorScope)
    Note over HandleException: 예외 타입 + 스코프 기반\n(title, message) 결정
    HandleException->>ErrorEventBus: ErrorEvent.ShowDialog(ErrorDialogSpec)
    ErrorEventBus->>MainActivity: ErrorDialogSpec 전달
    MainActivity->>User: ReedDialog(title?, description, confirm)
    alt AUTH_SESSION_EXPIRED -> 재로그인 필요
        MainActivity->>Presenter: onConfirm -> onLoginRequired (resetRoot LoginScreen)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 깡총깡총 코드 길 따라,
토스트 대신 문을 두드려요 🥕
제목 하나, 스코프 하나 더해,
다이얼로그로 묻고 응답하네,
"다시 로그인할래요?"

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed PR 제목 "fix: 로그인 관련 API 에러 처리 방식 개선"은 변경사항의 핵심을 명확하게 반영하고 있습니다. 실제 코드 변경사항을 보면 로그인 실패 시 토스트 기반 에러 처리에서 다이얼로그 기반 에러 처리로 전환하고, ErrorDialogSpec에 title 속성을 추가하며, ErrorScope에 LOGIN 및 AUTH_SESSION_EXPIRED를 추가하는 등 로그인 관련 에러 처리 방식의 전반적인 개선이 이루어졌습니다. 제목은 구체적이고 읽기 쉬우며, 팀 동료들이 히스토리를 스캔할 때 변경의 핵심을 이해할 수 있습니다.
Linked Issues Check ✅ Passed 연결된 이슈 #195는 "로그인 화면 서버 에러 처리 개선"을 요구하며, 작업 항목으로 "서버 에러 처리 개선"을 명시하고 있습니다. PR 변경사항은 이 요구사항을 충분히 충족합니다. LoginPresenter에서 로그인 실패 시 에러 다이얼로그를 통한 처리를 구현했고, ErrorDialogSpec에 title 속성을 추가하여 다이얼로그 UI를 개선했으며, ErrorScope에 LOGIN과 AUTH_SESSION_EXPIRED를 추가하여 세션 만료 등의 에러 상황을 체계적으로 처리하도록 구현했습니다. 또한 HomePresenter와 LibraryPresenter에서 로그인 관련 에러 발생 시 로그인 화면으로 이동하도록 처리를 추가했으므로, 로그인 화면뿐만 아니라 전체 앱 차원에서 서버 에러 처리 방식을 개선한 것으로 볼 수 있습니다.
Out of Scope Changes Check ✅ Passed PR의 모든 변경사항이 로그인 관련 에러 처리 개선이라는 범위 내에 있습니다. LoginPresenter의 에러 처리 로직 변경, ErrorDialogSpec과 ErrorScope의 업데이트, HandleException의 에러 다이얼로그 로직 구현, MainActivity의 다이얼로그 title 전달, HomePresenter와 LibraryPresenter의 로그인 필요 시 에러 처리 추가 등 모든 변경사항이 일관성 있게 로그인 에러 처리 개선을 목표로 하고 있습니다. LoginUiState에서 KakaoLogin을 data object에서 data class로 변경한 것도 에러 처리 흐름 상 사이드 이펙트의 유일성을 보장하기 위한 것으로 이해되며, 전체 변경사항들이 긴밀하게 연관되어 있습니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch BOOK-367-feature/#195

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.

@seoyoon513
Copy link
Copy Markdown
Contributor

@easyhooon Figma 보니까 Dialog 타이틀도 필요하겠네요. 요건 제가 작업해서 넣겠습니다~!

image

@easyhooon
Copy link
Copy Markdown
Contributor Author

Figma 보니까 Dialog 타이틀도 필요하겠네요. 요건 제가 작업해서 넣겠습니다~

@seoyoon513 이 브랜치에서 마저 작업하고 끝내면 될거같슴다

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

🧹 Nitpick comments (1)
core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt (1)

60-94: 에러 메시지들을 string resource로 관리해야 합니다.

로직과 구조는 훌륭하지만, 다이얼로그 타이틀과 메시지들이 하드코딩되어 있어 i18n과 유지보수 측면에서 개선이 필요합니다:

  • Line 62: "네트워크 연결이 불안정합니다.\n인터넷 연결을 확인해주세요"
  • Line 68: "알 수 없는 문제가 발생했어요.\n다시 시도해주세요"
  • Line 72: "로그인 오류"
  • Line 73: "예기치 않은 오류가 발생했습니다.\n다시 로그인 해주세요."
  • Line 77: "세션이 만료되었어요.\n다시 로그인 해주세요"
  • Line 83: "알 수 없는 문제가 발생했어요.\n다시 시도해주세요"

이러한 문자열들을 strings.xml로 이동하면 다국어 지원과 일관된 문구 관리가 용이해집니다.

예시:

+// strings.xml에 추가
+<string name="error_network_connection">네트워크 연결이 불안정합니다.\n인터넷 연결을 확인해주세요</string>
+<string name="error_login_title">로그인 오류</string>
+<string name="error_login_message">예기치 않은 오류가 발생했습니다.\n다시 로그인 해주세요.</string>
+<string name="error_session_expired">세션이 만료되었어요.\n다시 로그인 해주세요</string>
+<string name="error_unknown">알 수 없는 문제가 발생했어요.\n다시 시도해주세요</string>

그런 다음 코드에서는:

fun postErrorDialog(
    context: Context, // Context 파라미터 추가 필요
    errorScope: ErrorScope,
    exception: Throwable,
    @StringRes buttonLabelResId: Int = R.string.confirm,
    action: () -> Unit = {},
) {
    val (title, message) = when {
        exception.isNetworkError() -> {
            null to context.getString(R.string.error_network_connection)
        }
        exception is HttpException -> {
            when (errorScope) {
                ErrorScope.GLOBAL -> {
                    null to context.getString(R.string.error_unknown)
                }
                ErrorScope.LOGIN -> {
                    context.getString(R.string.error_login_title) to 
                        context.getString(R.string.error_login_message)
                }
                ErrorScope.AUTH_SESSION_EXPIRED -> {
                    null to context.getString(R.string.error_session_expired)
                }
            }
        }
        else -> {
            null to context.getString(R.string.error_unknown)
        }
    }
    // ...
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ef67f21 and 24954eb.

📒 Files selected for processing (6)
  • core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorDialogSpec.kt (1 hunks)
  • core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorScope.kt (1 hunks)
  • core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt (2 hunks)
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt (4 hunks)
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUiState.kt (1 hunks)
  • feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/MainActivity.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci-build
🔇 Additional comments (5)
feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/MainActivity.kt (1)

73-73: LGTM! 다이얼로그 타이틀 지원이 올바르게 적용되었습니다.

ErrorDialogSpec의 새로운 title 속성을 ReedDialog에 전달하는 변경사항이 정확합니다. nullable 타입도 적절하게 처리되고 있습니다.

core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorDialogSpec.kt (1)

6-6: LGTM! 타이틀 속성이 적절하게 추가되었습니다.

nullable 타입과 기본값 설정으로 하위 호환성을 유지하면서 새로운 기능을 추가한 좋은 설계입니다.

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

18-18: LGTM! Side effect 처리를 위한 중요한 변경입니다.

data object에서 data class로 변경하고 UUID 기반 key를 추가한 것은 Circuit의 side effect 시스템에서 매우 중요한 수정입니다. data object는 싱글톤이므로 동일한 side effect가 여러 번 발생해도 재구성(recomposition)이 트리거되지 않지만, UUID 키를 가진 data class는 매번 새로운 인스턴스를 생성하여 각 로그인 시도마다 정상적으로 side effect가 트리거됩니다.

이미 ShowToast에서 사용하던 패턴과도 일관성이 있습니다.

core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt (1)

26-32: LGTM! 401 에러 처리가 올바르게 개선되었습니다.

세션 만료 시 AUTH_SESSION_EXPIRED scope를 사용하여 다이얼로그 기반 에러 처리를 적용한 것이 적절합니다. onLoginRequired 콜백을 통해 재로그인 플로우로 연결되는 것도 좋습니다.

core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorScope.kt (1)

4-4: 제거된 ErrorScope 값 사용처 확인 완료

검증 결과, BOOK_REGISTERRECORD_REGISTER는 코드베이스 내 어디에서도 사용되지 않고 있습니다. 따라서 이들을 제거하고 AUTH_SESSION_EXPIRED를 추가한 변경은 완전히 안전하며, 컴파일 오류나 참조 누락 문제가 발생하지 않습니다.

@Immutable
sealed interface LoginSideEffect {
data object KakaoLogin : LoginSideEffect
data class KakaoLogin(private val key: String = UUID.randomUUID().toString()) : LoginSideEffect
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.

@easyhooon 로그인 API 에러 처리 방식을 개선하면서 LoginSideEffect를 초기화해주는 로직이 필요해졌습니다. (안그러면 카카오 로그인 재시도 시 무한로딩 발생) 토스트메세지 이벤트처럼 UUID 값을 사용하는 방식으로 변경했는데 확인 부탁드립니다

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.

아 무한로딩 발생하는게 이거 때문이었군여
분명 타임아웃 시간이 지나서 로딩이 끝날때가 되었는데 계속 돌길래 뭔가했는데

Copy link
Copy Markdown
Contributor Author

@easyhooon easyhooon Oct 21, 2025

Choose a reason for hiding this comment

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

        fun handleEvent(event: LoginUiEvent) {
            when (event) {
                is LoginUiEvent.OnKakaoLoginButtonClick -> {
                    isLoading = true
                    sideEffect = LoginSideEffect.KakaoLogin()
                }
  1. 사용자가 카카오 로그인 버튼 클릭
  2. sideEffect = LoginSideEffect.KakaoLogin() → RememberedEffect 실행
  3. 카카오 로그인 실패 → eventSink(LoginUiEvent.LoginFailure(...))
  4. sideEffect = LoginSideEffect.ShowToast(...) → RememberedEffect 실행 (Toast 표시)
  5. 사용자가 다시 카카오 로그인 버튼 클릭
  6. sideEffect = LoginSideEffect.KakaoLogin()
    -> 문제:프로퍼티가 없는 LoginSideEffect.KakaoLogin()은 구조적으로 동일한 값으로 인식됨
  7. Compose가 state.sideEffect가 변경되지 않았다고 판단
  8. RememberedEffect가 재실행되지 않음
  9. 카카오 로그인이 다시 시작되지 않음
  10. isLoading = true만 남아 무한 로딩

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.

uuid 방식으로 해결할 수 있는 케이스라 괜찮은거같습니다!

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

🧹 Nitpick comments (1)
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt (1)

62-68: 방어적 코딩을 위해 Guest 체크 추가를 권장합니다.

에러 발생 시 handleException을 호출하여 401 에러를 처리하는 로직이 추가되었습니다.

다음 사항들을 검토해주세요:

  1. Guest 체크 누락: LibraryPresenter와 달리 명시적인 guest 체크가 없습니다. 현재는 RememberedEffect (lines 109-113)에서 non-guest만 loadHomeContent()를 호출하므로 문제가 없지만, 나중에 다른 경로에서 이 함수가 호출될 경우 guest 사용자에게도 handleException이 실행될 수 있습니다. 일관성과 방어적 코딩을 위해 다음과 같은 체크를 추가하는 것을 고려해보세요:
                    .onFailure { exception ->
                        uiState = UiState.Error(exception)

+                       if (userState !is UserState.Guest) {
                            handleException(
                                exception = exception,
                                onError = {},
                                onLoginRequired = {
                                    navigator.resetRoot(LoginScreen())
                                },
                            )
+                       }
                    }
  1. 빈 onError 람다: LibraryPresenter와 마찬가지로 onError = {}로 전달되어 401이 아닌 다른 에러들은 다이얼로그로 표시되지 않습니다. 기존 UI 에러 표시 (line 60)를 유지하면서 401만 다이얼로그로 처리하려는 의도로 보이는데, 이것이 의도한 동작이 맞는지 확인해주세요.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 24954eb and 1914ff2.

📒 Files selected for processing (2)
  • feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt (2 hunks)
  • feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-28T12:25:54.058Z
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#174
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchPresenter.kt:128-133
Timestamp: 2025-08-28T12:25:54.058Z
Learning: In BookSearchPresenter.kt, when a guest user tries to register a book and is redirected to login, the bottom sheet (isBookRegisterBottomSheetVisible) and selection state (selectedBookIsbn, selectedBookStatus) are intentionally kept open/preserved so that when the user returns from login, they can continue from where they left off without losing context.

Applied to files:

  • feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt
  • feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt
🧬 Code graph analysis (2)
feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt (1)
core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt (1)
  • handleException (19-52)
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt (1)
core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt (1)
  • handleException (19-52)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci-build
🔇 Additional comments (3)
feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt (2)

11-11: LGTM! 필요한 import가 올바르게 추가되었습니다.

중앙화된 에러 처리를 위한 handleException과 로그인 화면 내비게이션을 위한 LoginScreen import가 적절하게 추가되었습니다.

Also applies to: 20-20


111-119: 네비게이션 메서드 일관성 검토가 필요합니다.

Guest가 아닌 사용자에 대한 에러 처리 로직이 추가되었으며, 401 에러 발생 시 로그인 화면으로 이동하도록 구현되었습니다.

다음 사항들을 확인해주세요:

  1. 네비게이션 메서드 불일치: Line 116에서는 navigator.resetRoot(LoginScreen())을 사용하지만, Line 134에서는 navigator.redirectToLogin()을 사용합니다.

    • 세션 만료 시나리오 (401)에서는 상태를 완전히 초기화하는 resetRoot가 더 적절할 수 있습니다.
    • 하지만 일관성을 위해 두 경우 모두 같은 메서드를 사용하거나, 차이점을 코멘트로 명시하는 것을 고려해보세요.
  2. 빈 onError 람다: onError = {}로 전달되어 401이 아닌 다른 에러들은 다이얼로그로 표시되지 않습니다. 기존 UI 에러 표시 로직 (lines 105-109)을 유지하면서 401만 다이얼로그로 처리하려는 의도로 보이는데, 이것이 의도한 동작이 맞는지 확인해주세요.

feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt (1)

9-9: LGTM! 필요한 import가 올바르게 추가되었습니다.

중앙화된 에러 처리를 위한 handleException과 로그인 화면 내비게이션을 위한 LoginScreen import가 적절하게 추가되었습니다.

Also applies to: 17-17

ErrorScope.LOGIN -> {
"예기치 않은 오류가 발생했습니다.\n다시 로그인 해주세요."
val loginErrorTitle = "로그인 오류"
loginErrorTitle to "예기치 않은 오류가 발생했습니다.\n다시 로그인 해주세요."
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.

굳이 변수로 안빼도될거같네여
빼려면 다 빼고 안빼려면 다 안빼고 하드코딩하는게 통일성 측면에서 좋을거같슴다

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.

반영 완료 61910e2

@easyhooon
Copy link
Copy Markdown
Contributor Author

@seoyoon513 제가 올린 PR이라 approve를 못하는 관계로

굳이 변수로 안빼도될거같네여

이부분만 반영 후 approve 눌러주시면 merge할게요

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

🧹 Nitpick comments (1)
core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt (1)

60-94: 에러 다이얼로그 처리 로직이 명확하게 개선되었습니다.

title과 message를 직접 계산하여 ErrorDialogSpec을 생성하는 구조가 간결하고 이해하기 쉽습니다. 다만 유지보수성 향상을 위해 다음 사항들을 고려해보시기 바랍니다:

  1. 메시지 중복 제거: 68번과 82번 라인의 "알 수 없는 문제가 발생했어요.\n다시 시도해주세요" 메시지가 중복됩니다. 상수로 추출하면 향후 문구 수정 시 일관성을 유지할 수 있습니다.

  2. 문장 부호 일관성: 72번 라인 LOGIN 스코프 메시지만 마침표("해주세요.")로 끝나고, 나머지 메시지들은 마침표 없이 끝납니다. 사용자 경험 일관성을 위해 통일하는 것을 권장합니다.

+private const val UNKNOWN_ERROR_MESSAGE = "알 수 없는 문제가 발생했어요.\n다시 시도해주세요"
+
 fun postErrorDialog(
     errorScope: ErrorScope,
     exception: Throwable,
     @StringRes buttonLabelResId: Int = R.string.confirm,
     action: () -> Unit = {},
 ) {
     val (title, message) = when {
         exception.isNetworkError() -> {
             null to "네트워크 연결이 불안정합니다.\n인터넷 연결을 확인해주세요"
         }

         exception is HttpException -> {
             when (errorScope) {
                 ErrorScope.GLOBAL -> {
-                    null to "알 수 없는 문제가 발생했어요.\n다시 시도해주세요"
+                    null to UNKNOWN_ERROR_MESSAGE
                 }

                 ErrorScope.LOGIN -> {
-                    "로그인 오류" to "예기치 않은 오류가 발생했습니다.\n다시 로그인 해주세요."
+                    "로그인 오류" to "예기치 않은 오류가 발생했습니다.\n다시 로그인 해주세요"
                 }

                 ErrorScope.AUTH_SESSION_EXPIRED -> {
                     null to "세션이 만료되었어요.\n다시 로그인 해주세요"
                 }
             }
         }

         else -> {
-            null to "알 수 없는 문제가 발생했어요.\n다시 시도해주세요"
+            null to UNKNOWN_ERROR_MESSAGE
         }
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b68ed25 and 61910e2.

📒 Files selected for processing (1)
  • core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci-build
🔇 Additional comments (1)
core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt (1)

25-33: 세션 만료 처리 로직이 올바르게 구현되었습니다.

401 에러 발생 시 AUTH_SESSION_EXPIRED 스코프로 에러 다이얼로그를 표시하고, 사용자가 확인 버튼을 누르면 onLoginRequired()를 실행하여 로그인 화면으로 유도하는 흐름이 명확하고 정확합니다.

@easyhooon easyhooon merged commit 49a1eaa into develop Oct 21, 2025
3 checks passed
@easyhooon easyhooon deleted the BOOK-367-feature/#195 branch October 21, 2025 04:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐞 fix Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BOOK-367/feat] 로그인 화면 서버 에러 처리 개선

2 participants