Skip to content

[Fix] 강제 로그아웃 시 전송 대기 행 보존 #602

Description

@edv-Shin

어떤 기능인가요?

강제 로그아웃이 서버로 올리지 못한 전송 대기 행을 함께 지웁니다. 오프라인에서 만든 타이머가 사용자가 의도하지 않은 경로로 사라질 수 있습니다.

RoomSessionDataCleaner.clearAll()database.clearAllTables()입니다. 대기 행과 동기화 완료 행을 구분하지 않습니다. 호출 경로는 ClearSessionUseCase 하나이고, MainViewModel.transitionToLogin()이 그것을 부릅니다. 그런데 transitionToLogin()의 트리거 여섯 개가 전부 사용자가 의도하지 않은 경로입니다.

MainViewModel 트리거
76 진입 플로우 catch-all 예외
86 !state.isAuthorized
90 getMemberIdUseCase()가 비어 있음
103 invalid_grant
112 NoRefreshToken, ConfigError
127 forceLogoutFlow

오프라인을 오래 쓰면 리프레시 토큰이 만료되기 쉽습니다. 그 사용자가 오프라인에서 만든 타이머는 아직 서버에 없는데, 강제 로그아웃 한 번에 알림 없이 사라집니다. 설계 문서 6) 보관 기간은 "동기화 대기(_PENDING) 행은 오래돼도 정리하지 않습니다. 아직 서버에 반영되지 않은 사용자 데이터입니다"라고 정해 두었습니다. 지금 동작은 그 규칙과 어긋납니다.

정리 경로를 세 갈래로 나눕니다.

경로 처리 근거
명시적 로그아웃, 탈퇴 전부 삭제 사용자가 의도한 정리. 설계 규칙 D9
강제 로그아웃(세션 만료 등) 대기 행 보존, 동기화 완료 행만 삭제 의도하지 않은 이탈. 올리지 못한 데이터를 지킴
계정 전환 전부 삭제 다른 계정 데이터가 보이면 안 됨. 위험 요소 1

같은 계정으로 다시 로그인하면 대기 행이 남아 있어 전송이 이어집니다. 다른 계정으로 로그인하면 AuthRepositoryImpl.checkIsRegistered()가 회원ID 변경을 감지해 전부 지웁니다. #593에서 넣은 경로를 그대로 씁니다.

이 이슈는 정리 범위 분기까지입니다. 전송 자체는 #588에서 다룹니다.

작업 상세 내용

  • SessionDataCleaner에 동기화 완료 행만 지우는 연산 추가. 기존 clearAll()은 그대로 유지
  • ClearSessionUseCase가 명시적 이탈과 강제 이탈을 구분해 정리 범위를 고름
  • MainViewModel.transitionToLogin()은 강제 이탈로 호출. 대기 행을 남김
  • SettingFragment.performLogout의 로그아웃과 탈퇴는 명시적 이탈로 호출. 전부 지움
  • 계정 전환 경로는 지금처럼 전부 지움
  • 캐시 삭제가 실패해도 세션 정리와 예약 작업 취소는 수행. #593에서 넣은 try/finally 유지
  • 대기 행을 남길 때 예약 작업을 취소할지 결정. 세션이 없으면 전송할 수 없으므로 취소하고, 다시 로그인할 때 재예약하는 쪽을 기본으로 봄
  • 강제 이탈에서 대기 행이 남는지, 동기화 완료 행은 지워지는지 테스트
  • 명시적 이탈에서 전부 지워지는지 테스트
  • 계정 전환에서 전부 지워지는지 테스트 ([Fix] 계정 전환 시 이전 계정의 로컬 캐시가 남는 문제 #593 테스트 유지)
  • 오프라인에서 타이머 생성 후 토큰 만료로 로그인 화면 전이 → 같은 계정 재로그인 → 만든 타이머가 남아 있는지 수동 확인

참고할만한 자료(선택)

오프라인 기능 지원 설계 문서의 설계 규칙 D9(로그아웃·탈퇴 시 전부 지움), 6) 보관 기간(대기 행은 정리하지 않음), 위험 요소 1(계정 전환 시 이전 사용자 데이터 노출)이 기준입니다.

D9는 로그아웃과 탈퇴를 대상으로 적었고, 강제 로그아웃을 그 범위에 넣을지는 문서에 없습니다. 이 이슈에서 "의도한 이탈만 전부 지운다"로 좁힙니다.

#588 TimerSyncWorker 설계가 이 결정에 의존합니다. 대기 행을 남기기로 하면 워커는 재로그인 후 이어서 전송해야 하고, 작업 입력의 memberId와 현재 세션을 비교하는 방어가 그대로 유효합니다.

전송 대기 행이 남은 채 사용자가 다시 로그인하지 않으면 행이 영구히 남습니다. 타이머는 계정당 소수라 용량 문제는 없다고 봅니다.

Activity

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions