Skip to content

fix(core): 로그아웃 응답을 기다리는 동안 설정 화면을 떠나면 로컬 세션 정리가 취소된다 #2243

Closed

Description

@OnlyReadOneBook

작업 유형

bug — 버그·오동작

주 담당 모듈

core — 코어

개요

설정에서 로그아웃을 확인한 뒤 서버 응답을 기다리는 동안 뒤로가기로 설정 화면을 떠나면 로그아웃이 끝나지 않은 채 사라집니다. 서버는 로그아웃을 처리해 refresh 토큰을 지웠고 푸시 대상(DELETE users/push-tokens)도 해제됐는데, 앱에는 토큰과 로그인 상태가 그대로 남습니다. 다음 재기동에서 앱은 홈으로 들어가고 해제했던 푸시 대상을 다시 등록합니다. 액세스 토큰 수명(서버 설정 JWT_ACCESS_EXPIRATION, 배포 예시 설정 기준 1시간)이 다할 때 재발급이 400/1107 로 거절되어 그제서야 강제 로그아웃됩니다. 선제 재발급 deadline 이 살아 있는 프로세스라면 만료 60초 전 선제 재발급에서 같은 거절을 받습니다.

기준과 원인

2026-10-03 확인 기준은 develop 756e456f1f4d280a630fcbe119bb1645e683f97e입니다.

  • SettingViewModel.logout 79~85행은 viewModelScope.launch 안에서 authRepository.logout() 을 기다립니다. 설정 홈의 SettingViewModel 은 설정 홈 entry 범위입니다. 설정 로컬 스택이 홈 하나뿐일 때 시스템 뒤로가기는 루트 NavHost 로 흘러 Route.Setting host 가 루트 백스택에서 빠지고, 그 ViewModelStore 와 함께 이 ViewModel 이 정리되어 코루틴이 취소됩니다. 설정 안에서 더 깊이 들어가는 이동은 ViewModel 을 살려 두므로 취소는 host 이탈에서만 납니다.
  • AuthRepositoryImpl.logout 132~147행은 runCatchingCancellable 로 감싸 CancellationException 을 그대로 던집니다. HTTP 대기 중 취소되면 뒤의 localStoreRegistry.clearScope(StoreScope.SESSION) 과 expiryTracker.clear() 가 실행되지 않습니다. KDoc 의 "SESSION 스코프 로컬 저장소와 선제 reissue deadline 은 서버 호출 결과와 무관하게 항상 정리한다" 는 계약이 호출자 취소에는 지켜지지 않습니다.
  • 서버(Afternote-BE origin/main 6adc0c4 AuthService.logout)는 요청을 받은 이상 refresh 를 삭제합니다. 클라이언트의 취소는 서버에 전달되지 않습니다.

재현 순서

Android API 36 에뮬레이터에 756e456 빌드(서버 주소 상수와 cleartext 허용만 로컬 모의 서버용으로 바꿈)를 설치하고, 모의 서버가 POST auth/logout 처리를 해제 신호까지 보류하도록 했습니다. 실측에서는 도착 6초 뒤에 해제했습니다.

  1. A 세션으로 홈 진입 → 설정 → 로그아웃 → 예. DELETE users/push-tokens 200, POST auth/logout 도착.
  2. 응답을 기다리는 동안 뒤로가기 → 홈. 홈 재조회가 A 토큰으로 200.
  3. 서버가 로그아웃을 처리(refresh 삭제, 200 응답).
  4. 앱 상태를 읽습니다.

기대 결과는 로그아웃 확인 뒤에는 어디로 이동하든 로컬 세션이 정리되고 온보딩으로 가는 것입니다. 실제 결과는 홈 유지, DataStore 의 access·refresh·session_id 전부 그대로, 콜드 스타트도 홈, 기동 시 PUT users/push-tokens 로 푸시 대상 재등록입니다. 서버 쪽은 refresh 가 삭제된 상태입니다.

모의 서버 로그(발췌):

08:39:50.414 DELETE /users/push-tokens A-access-1 -> 200        (로그아웃 '예')
08:39:52.500 GET    /users/me          A-access-1 -> 200        (뒤로가기 → 홈 재조회)
08:39:56.483 POST   /auth/logout       A-access-1 -> 200 (6064ms 보류 후 처리, refresh 삭제)
08:40:05.987 GET    /app/version       A-access-1 -> 200        (콜드 스타트: 홈)
08:40:06.489 PUT    /users/push-tokens A-access-1 -> 200        (푸시 대상 재등록)

완료 조건

  • 로그아웃 확인 뒤 호출한 화면·ViewModel 이 사라져도 로컬 세션 정리와 로그인 상태 전환이 끝납니다.
  • 로그아웃 HTTP 가 취소되거나 실패해도 로컬 정리는 실행됩니다(기존 best-effort 계약 유지).
  • 호출자가 취소되는 중의 로그아웃을 회귀 테스트로 검증합니다.

참고

Activity

  1. added
    bugSomething isn't working
    area:core공용 코어·네트워크 기능 영역
    on Oct 2, 2026
  2. github-actions commented on Oct 2, 2026

    @github-actions
    Contributor

    bug 이슈는 사이드바 Fields > Priority 로 심각도를 지정해야 합니다. 판정 기준:

    • Urgent: 치명 — 크래시·데이터 소실·보안 무력화·핵심 경로 차단·가짜 성공
    • High: 심각 — 실패·틀린 값의 정상 위장, 핵심 기능 무동작
    • Medium: 불편 — 우회로가 있는 오동작·틀린 표시, 핵심 흐름은 유지
    • Low: 경미 — 문구·정렬·마감 품질 흠, 기능 영향 없음

    값이 비어 있어도 이슈를 닫지는 않습니다. 이 안내는 이슈당 한 번만 답니다.

  3. added
    pr-open이 이슈를 구현하는 PR 이 열려 있다 — base 가 기본 브랜치가 아니어도 드러낸다
    on Oct 3, 2026
  4. removed
    pr-open이 이슈를 구현하는 PR 이 열려 있다 — base 가 기본 브랜치가 아니어도 드러낸다
    on Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area:core공용 코어·네트워크 기능 영역bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions