Skip to content

feat: 회원 탈퇴를 공급자 인가 왕복 흐름에 맞춘다 - #97

Merged
TrossYou merged 1 commit into
devfrom
feature/withdrawal-authorization-round-trip
Aug 4, 2026
Merged

feat: 회원 탈퇴를 공급자 인가 왕복 흐름에 맞춘다#97
TrossYou merged 1 commit into
devfrom
feature/withdrawal-authorization-round-trip

Conversation

@cherry-go-round

Copy link
Copy Markdown
Contributor

관련 이슈

Closes #93

작업 내용

백엔드가 DELETE /me를 **204(즉시 삭제)에서 200 + authorizationUrl(왕복 시작)**로 바꿨다(08 §3.6, back#181). 연결 해제에 공급자 토큰이 필요한데 서버가 그것을 보관하지 않아, 탈퇴 시점에 인가를 한 번 더 받는다.

DELETE /me → 200 { authorizationUrl }   (아직 아무것도 안 지워짐)
  → 그 주소로 페이지 이동 → 공급자 인가 화면
  → 콜백 → 연결 해제 → 성공한 경우에만 삭제

이 대응이 없으면 탈퇴가 조용히 깨진다. 응답 본문을 버리므로 왕복이 시작되지 않는데 화면은 "탈퇴가 완료되었습니다"를 띄우고, logged_in이 남아 /login 가드가 홈으로 되돌린다.

  • deleteAccountPromise<void>Promise<WithdrawalStart>. 인터셉터가 envelope를 벗겨 준 response.data를 돌려준다.
  • useDeleteAccountMutation — 제네릭 교체. queryClient.clear()뺐다. 아직 아무것도 안 지워졌는데 캐시를 비우면, 공급자 화면에서 취소하고 돌아온 사용자의 멀쩡한 세션 캐시만 날린다.
  • WithdrawConfirmDialog — 성공 메시지·타이머 대신 window.location.href = authorizationUrl. 목적지가 공급자 화면이라 라우터 이동이나 XHR로는 사용자에게 보이지 않는다. 재인증이 필요하다는 안내 문구를 넣었다.
  • handleOAuthCallbackWITHDRAWAL_* 네 값을 분기해 각각의 문구를 보여준다. 이 경우 logoutRequest()를 호출하지 않는다 — 서버가 연결 해제에 성공한 경우에만 삭제하고 실패 시 인증 쿠키도 지우지 않으므로, 회원이 살아 있다. 로그아웃시키면 재시도하려는 사용자가 로그인부터 해야 한다.
  • oauthCallbackSearchSchemaz.object가 선언하지 않은 쿼리를 버린다는 주의를 주석으로 남겼다.
?error= 문구
(없음) 탈퇴 완료. 쿠키가 만료된 채 착지해 기존 앱 시작 흐름이 로그인으로 보낸다
WITHDRAWAL_CANCELLED 탈퇴를 취소했습니다.
WITHDRAWAL_FAILED · WITHDRAWAL_UNLINK_FAILED 탈퇴에 실패했습니다. 잠시 후 다시 시도해 주세요.
WITHDRAWAL_ACCOUNT_MISMATCH 가입에 사용한 계정으로 인증해야 탈퇴할 수 있습니다.
OAUTH_FAILED (기존) 로그인에 실패했습니다.

변경 유형

  • feat (기능)
  • fix (버그)
  • refactor / chore / docs / style / test

확인 방법

로컬에서 백엔드(dev)와 함께 종단 확인했다. vite 프록시(/apilocalhost:8080)를 통해 프론트가 실제로 타는 경로 그대로 호출했다.

GET    /api/core/v1/me/summary   → 200
DELETE /api/core/v1/me           → {"success":true,"data":{"authorizationUrl":"..."}}
그 주소로 이동                    → 302 https://accounts.google.com/...  code_challenge_method=S256
그 시점 DB                        → member_deleted=null   (아무것도 안 지워짐)

브라우저로 3사(Google·Kakao·Naver) 실제 탈퇴까지 돌렸고, 백엔드 로그에서 social account unlinked before withdrawalwithdrawal completed를 확인했다.

재현 절차

  1. 백엔드를 dev로 로컬 기동 (AUTH_CLIENT_REDIRECT_URI=http://localhost:5173/auth/callback)
  2. npm run dev → 로그인
  3. 설정 → 탈퇴 → 「예」 → 공급자 화면 → 승인
  4. 공급자 계정 설정에서 연결이 사라졌는지 확인
  5. 취소도 눌러본다 — 「탈퇴를 취소했습니다」가 뜨고 로그인이 유지되어야 정상

테스트 8건 추가. tsc --noEmit · eslint · vitest 64건 통과.

체크리스트

  • 공개 화면(Feed, 타인 Shelf, Collection 상세)에 Context 원문·신원 정보를 노출하지 않았다
  • member.id(내부 사용자 ID)를 URL·요청·응답에 사용하지 않았다 (진입점은 Collection id)
  • Keyword는 label만 사용하고 code를 노출하지 않았다
  • Context 수정 후 새 contextId로 쿼리 키·URL·선택 상태를 교체했다 — 해당 없음
  • keywords: [] 등 빈 결과를 오류로 처리하지 않았고 로딩·오류·401 상태를 처리했다
  • docs/conventions.md(용어·any·컴포넌트 직접 API 호출 금지)를 지켰다

배포 순서 ⚠️

백엔드가 먼저 배포되어야 한다. 현재 배포된 백엔드는 2026-07-31(bad3c09) 버전이라 아직 204를 준다 — 이 PR만 먼저 나가면 authorizationUrlundefined가 되어 탈퇴가 아예 동작하지 않는다.

infrabackend-image-update(cron)가 7/31 이후 태그를 갱신하지 않고 있어 별도 확인이 필요하다.

알려진 미결 (백엔드 쪽)

Google은 연결이 실제로 끊기지 않는다. 서버가 access token을 /revoke에 보내 200을 받지만, 그것은 토큰 폐기이지 승인 해제가 아니다 — Google 계정의 서드파티 목록에 앱이 그대로 남는 것을 확인했다. Kakao·Naver는 연결 단위 API라 정상이다. 백엔드에서 별도 티켓으로 처리한다.

이 PR의 프론트 동작에는 영향이 없다. 왕복·분기·문구는 세 공급자 모두 동일하다.

백엔드가 DELETE /me를 204(즉시 삭제)에서 200 + authorizationUrl(왕복 시작)로 바꿨다
(08 §3.6). 연결 해제에 공급자 토큰이 필요한데 서버가 그것을 보관하지 않아, 탈퇴
시점에 인가를 한 번 더 받는다.

- deleteAccount가 응답을 읽어 authorizationUrl을 돌려준다. 버리면 왕복을 시작할 수
  없고, 화면은 "탈퇴 완료"를 띄우는데 서버는 아무것도 안 지운 상태가 된다.
- 다이얼로그가 성공 메시지 대신 window.location.href로 전체 페이지 이동을 한다.
  목적지가 공급자 화면이라 라우터 이동이나 XHR로는 사용자에게 보이지 않는다.
- 성공 메시지를 지웠다. 「예」를 눌러 받는 것은 완료가 아니라 진입 주소이고 사용자는
  공급자 화면에서 취소할 수 있다.
- queryClient.clear()를 지웠다. 아직 아무것도 안 지워졌는데 캐시를 비우면 취소하고
  돌아온 사용자의 멀쩡한 세션 캐시만 날린다.
- 콜백이 WITHDRAWAL_* 네 값을 분기해 각각의 문구를 보여준다. 이 경우 로그아웃을
  호출하지 않는다 — 회원이 살아 있어서, 로그아웃시키면 재시도에 로그인이 앞선다.

테스트 8건 추가(64건 통과).

Closes #93

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

회원 탈퇴 API 계약 변경 대응 — 204에서 200 + authorizationUrl로, 탈퇴가 2단계가 된다

2 participants