Repository navigation
[NM-446] 탈퇴 401 세션 만료 처리 · 약관 개정 재동의 안내 - #164
Merged
Merged
Conversation
spec 이 §토큰·세션에서 "401 이면 세션 만료(탈퇴·폐기 포함)로 보고 로그인 화면으로
유도" 라며 탈퇴를 콕 집어 적어뒀는데, 지금은 401 을 다른 오류와 똑같이
"계정 삭제 실패" 창으로 처리했다. 화면 전환은 인터셉터가 쏜 .authSessionExpired 로
따로 일어나서, 두 안내가 동시에 뜨고 사용자는 삭제가 실패한 건지 로그아웃된 건지
알 수 없었다.
**`network(401, _)` 을 보면 안 된다.** 만료 판정은 인터셉터가 이미 끝내고
tokenReissuanceFailed 로 바꿔 올린다("갱신 1회 → 그래도 401"). 여기까지
network(401, _) 로 오는 건 그 판정을 통과하지 못한 401 — APP_CHECK_FAILED
(앱 무결성, 세션과 무관) 가 대표적이라, 그걸 만료로 처리하면 멀쩡히 로그인한
사용자를 로그아웃시킨다(NM-421 에서 고친 그 증상).
- AuthRepository: tokenReissuanceFailed → AuthError.sessionExpired
- AuthUseCase: 로그아웃 + 계정 스코프 캐시 폐기 후 재던짐. 500 은 기존대로 유지
- AppCoordinator: 알럿 중복 제거. 대신 탈퇴 중이었으면 세션 만료 안내를
"계정 삭제를 완료하지 못했어요 / 다시 로그인한 뒤 시도해 주세요" 로 바꾼다
— errors.md §DELETE /users/me 의 클라이언트 대응이 "재로그인 후 재시도" 다.
세션 안내만 띄우면 사용자는 계정이 삭제된 줄 알고 떠난다.
플래그는 한 런루프 뒤에 내린다. 인터셉터의 알림이 요청 실패보다 먼저 메인 큐에
실려서, 바로 내리면 옵저버가 이미 false 를 읽는 경우가 생긴다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ch9vPGGKfeTUWMKEsZ3NWM
이미 동의하고 쓰던 사람에게 동의 화면이 예고 없이 다시 뜨면 앱이 동의를
잃어버린 것으로 읽힌다. 개정으로 다시 묻는 경우에는 시트 앞에 안내를 한 장 세운다.
약관이 변경되었어요
서비스를 계속 이용하려면 변경된 약관에 다시 동의해 주세요.
최초 가입자는 흐름상 동의가 당연한 단계라 안내 없이 곧장 시트로 간다.
판별은 `agreed && !satisfied` — "동의는 했는데 그 버전이 현재 필수 버전이 아니다".
satisfied 의 정의가 openapi 에 그대로 있다("현재 필수 버전 충족 여부(동의 & 최신 버전)").
한 번도 동의한 적 없는 항목은 agreed == false 라 걸리지 않는다.
이 값은 **안내 문구만** 가른다. 화면 게이트는 그대로 서버의 onboardingRequired 가
쥔다 — "클라이언트가 consents 로 다시 계산하지 않는다"(domains/auth.md §동의)는
그 게이트에 대한 규칙이고, 여기서 그걸 다시 세지 않는다. 틀려도 잘못된 문구가
나갈 뿐 들여보낼 사람을 막거나 막을 사람을 들이지 않는다.
띄우는 시점은 **앱을 켤 때**다 — spec §동의 온보딩이 약관 개정을 "다음 진입 때"로
못박는다. 포그라운드 복귀마다 재판정하지 않는다.
dev 서버가 필수 버전을 2026-09-10 으로 올린 실제 상태에서 확인했다
(개정 감지 → 모달 → 동의 → 정상화).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ch9vPGGKfeTUWMKEsZ3NWM
약관이 업데이트됐어요. 새 내용을 확인해 주세요.
↓
약관이 변경되어 다시 불러왔어요. 확인 후 동의해 주세요.
사용자에게 보이는 자리에서 세 단어가 섞여 있었다 — 재동의 안내는 「변경」(이 PR),
버전 불일치 400 은 iOS 「업데이트」·Android 「개정」. 계약 서술은 「개정」을 유지하고
**화면 문구는 「변경」으로 통일**한다.
정본 출처: spec PR #127 [NM-462] 약관 재동의 흐름 정본화 §용어 통일.
그 PR 은 이 한 줄을 NM-451 로 분리해 뒀지만, 같은 화면의 문구를 두 PR 로 나누면
리뷰가 갈라지고 그 사이에 두 문구가 공존한다 — 여기서 함께 맞춘다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ch9vPGGKfeTUWMKEsZ3NWM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
관련 이슈
변경 요약
탈퇴가 401 로 실패할 때 세션 만료로 처리하고(NM-446 ④), 약관 개정으로 다시 동의를 받을 때 이유를 알리는 모달을 추가한다. 커밋 2개로 나눠 두었다.
변경 내용
[NM-446] fix: 탈퇴가 401 이면 세션 만료로 처리한다(④)spec 이 §토큰·세션에서 "401 이면 세션 만료(탈퇴·폐기 포함)로 보고 로그인 화면으로 유도" 라며 탈퇴를 콕 집어 적어뒀는데, 지금은 401 을 다른 오류와 똑같이 "계정 삭제 실패" 창으로 처리했다. 화면 전환은 인터셉터가 쏜
.authSessionExpired로 따로 일어나서, 두 안내가 동시에 뜨고 사용자는 삭제가 실패한 건지 로그아웃된 건지 알 수 없었다.AuthRepository—tokenReissuanceFailed→AuthError.sessionExpiredAuthUseCase— 로그아웃 + 계정 스코프 캐시 폐기 후 재던짐. 500 은 기존대로 로그아웃하지 않음AppCoordinator— 알럿 중복 제거. 대신 탈퇴 중이었으면 안내 문구를 바꾼다문구를 가르는 근거는
errors.md§DELETE /users/me의 클라이언트 대응이 "재로그인 후 재시도" 이기 때문이다. 세션 안내만 띄우면 사용자는 계정이 삭제된 줄 알고 떠나는데, 계정은 그대로 남아 있다.[NM-446] feat: 약관 개정 시 재동의 안내 모달을 띄운다이미 동의하고 쓰던 사람에게 동의 화면이 예고 없이 다시 뜨면 앱이 동의를 잃어버린 것으로 읽힌다. 개정으로 다시 묻는 경우에만 시트 앞에 안내를 세운다. 최초 가입자는 곧장 시트로 간다.
판별은
AuthUser.needsReconsent=agreed && !satisfied.리뷰에서 봐줬으면 하는 것
1.
network(401, _)이 아니라tokenReissuanceFailed를 본다. 만료 판정은 인터셉터가 이미 끝내고("갱신 1회 → 그래도 401") 그 타입으로 바꿔 올린다. 여기까지network(401, _)로 오는 건 그 판정을 통과하지 못한 401 —APP_CHECK_FAILED(앱 무결성, 세션과 무관)가 대표적이라, 그걸 만료로 처리하면 멀쩡히 로그인한 사용자를 로그아웃시킨다(NM-421 에서 고친 그 증상).2.
isDeletingAccount플래그를 한 런루프 뒤에 내린다. 인터셉터의 알림이 요청 실패보다 먼저 메인 큐에 실려서, 바로 내리면 옵저버가 이미false를 읽는 경우가 생긴다.3.
needsReconsent는 안내 문구만 가른다. 화면 게이트는 그대로 서버의onboardingRequired가 쥔다 — "클라이언트가 consents 로 다시 계산하지 않는다"(domains/auth.md §동의)는 그 게이트에 대한 규칙이고, 여기서 그걸 다시 세지 않는다. 틀려도 잘못된 문구가 나갈 뿐 들여보낼 사람을 막거나 막을 사람을 들이지 않는다.테스트
tuist build App성공2026-09-10으로 올린 실제 상태에서 개정 감지 → 모달 → 동의 → 정상화 전 구간 확인각 커밋이 독립적으로 빌드·테스트를 통과한다.
체크리스트
[NM-XXX] 요약형식<type>/NM-XXX-요약형식[NM-XXX] type: 요약형식NM-446 나머지 항목
bd3cbf2(PR #161).AuthUseCase.keepsSession+presentSessionRestoreRetry+ 테스트로 고정돼 있다ConsentType이 openapi 에서[TERMS, PRIVACY]로 닫혀 있어 현재 계약상 발생 불가. 세 번째 항목을 추가하는 작업에 묶는 게 맞다②를 제외한 이유 — 티켓은 §진입 라우팅 9행("앱 실행·포그라운드 복귀마다")을 근거로 들지만, 같은 문서 §동의 온보딩 56행이 약관 개정을 "다음 진입 때" 로 못박는다. 약관 개정이라는 주제를 직접 다루는 구체 조항이 후자이고, 현재 코드(콜드런치에만 판정)는 그쪽을 지키고 있다. 세션 만료도 §토큰·세션이 401 반응으로만 규정하며 포그라운드를 언급하지 않는다.
같은 문장을 읽고 다른 결론이 나오는 상태라, spec 9행 문구를 56행과 어긋나지 않게 다듬는 별도 PR(spec 레포)이 필요해 보인다.