feat(mypage): 회원탈퇴 전 약관 안내 페이지 추가 - #87
Conversation
마이페이지에서 회원탈퇴 클릭 시 바로 모달이 뜨던 방식을 개선하여, 말해부엉 서비스 기준 탈퇴 안내 조항(5개 조, 약 5000자)을 담은 전용 페이지로 먼저 이동하고, 하단 '탈퇴하기' 버튼으로 최종 확인하는 흐름으로 변경. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthrough
Changes회원탈퇴 전용 페이지 및 소프트 삭제 관리
Sequence Diagram(s)sequenceDiagram
participant User as 사용자
participant WithdrawPage as WithdrawPage
participant Modal as ConfirmModal
participant API as DELETE /api/user/me
participant Auth as signOut
User->>WithdrawPage: 탈퇴하기 버튼 클릭
WithdrawPage->>Modal: confirmOpen = true (모달 오픈)
User->>Modal: 최종 확인 클릭
Modal->>WithdrawPage: onConfirm → handleWithdraw()
WithdrawPage->>API: DELETE /api/user/me (loading = true)
alt 응답 실패
API-->>WithdrawPage: !res.ok, error.message
WithdrawPage-->>User: alert(error.message), loading = false
else 응답 성공
API-->>WithdrawPage: 200 { success: true }
WithdrawPage->>Auth: signOut({ callbackUrl: '/login' })
Auth-->>User: /login 리다이렉트
else 예외 발생
WithdrawPage-->>User: 고정 문구 alert, loading = false
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
- DELETE /api/user/me: 소프트 딜리트(deletedAt, deletionRequestedAt 설정) 처리 및 AuditLog(USER_DELETED) 기록, 이미 탈퇴된 계정 재요청 시 409 반환 - signIn 콜백에서 deletedAt이 설정된 계정의 카카오 로그인을 차단(return false) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/`(page)/mypage/withdraw/page.module.scss:
- Around line 23-36: Fix the three stylelint errors in the withdraw page module
file. First, add a blank line between the closing brace of the previous selector
block and the &__body selector declaration to comply with spacing rules. Second,
add a blank line between the &__body selector block and the &__paragraph
selector block. Third, replace the legacy word-wrap property on line 36 with the
modern equivalent overflow-wrap property, as word-wrap is a legacy CSS property
that should use overflow-wrap: break-word instead.
In `@src/app/`(page)/mypage/withdraw/page.tsx:
- Around line 73-84: The handleWithdraw function lacks a re-entry guard that
prevents duplicate DELETE requests when users rapidly click the confirmation
button. Add an early return check at the beginning of handleWithdraw that
returns immediately if loading is already true. Additionally, the modal confirm
button (around lines 119-124) should be disabled by binding its disabled
attribute to the loading state so that users cannot trigger multiple requests
while one is already in progress.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 0802f405-f93d-4bad-a63d-80e572e493b9
📒 Files selected for processing (3)
src/app/(page)/mypage/page.tsxsrc/app/(page)/mypage/withdraw/page.module.scsssrc/app/(page)/mypage/withdraw/page.tsx
| const handleWithdraw = async () => { | ||
| setLoading(true); | ||
| try { | ||
| const res = await fetch('/api/user/me', { method: 'DELETE' }); | ||
| if (!res.ok) { | ||
| const json = await res.json().catch(() => null); | ||
| const message = json?.error?.message ?? '탈퇴 처리 중 오류가 발생했습니다.'; | ||
| alert(message); | ||
| setLoading(false); | ||
| return; | ||
| } | ||
| await signOut({ callbackUrl: '/login' }); |
There was a problem hiding this comment.
탈퇴 확인 모달에서 중복 DELETE 요청이 발생할 수 있습니다.
Line 73의 handleWithdraw에 재진입 가드가 없고, Line 119-124의 모달 확인 버튼도 loading 중 비활성화되지 않아 연속 클릭 시 DELETE /api/user/me가 중복 호출될 수 있습니다. 계정 삭제 요청은 단일 실행으로 제한하는 게 안전합니다.
중복 호출 방지 제안
const handleWithdraw = async () => {
+ if (loading) return;
setLoading(true);
+ setConfirmOpen(false);
try {
const res = await fetch('/api/user/me', { method: 'DELETE' });
if (!res.ok) {
const json = await res.json().catch(() => null);
const message = json?.error?.message ?? '탈퇴 처리 중 오류가 발생했습니다.';
alert(message);
- setLoading(false);
return;
}
await signOut({ callbackUrl: '/login' });
} catch {
alert('탈퇴 처리 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.');
- setLoading(false);
+ } finally {
+ setLoading(false);
}
};Also applies to: 119-124
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/`(page)/mypage/withdraw/page.tsx around lines 73 - 84, The
handleWithdraw function lacks a re-entry guard that prevents duplicate DELETE
requests when users rapidly click the confirmation button. Add an early return
check at the beginning of handleWithdraw that returns immediately if loading is
already true. Additionally, the modal confirm button (around lines 119-124)
should be disabled by binding its disabled attribute to the loading state so
that users cannot trigger multiple requests while one is already in progress.
- page.module.scss: @include 뒤 빈 줄 추가(declaration-empty-line-before) 2건 - page.module.scss: word-wrap → overflow-wrap (property-no-deprecated) 1건 - page.tsx: handleWithdraw 재진입 가드(if loading return) 추가 - page.tsx: setConfirmOpen(false)를 API 호출 전으로 이동 - page.tsx: setLoading(false)를 finally 블록으로 통합 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
DELETE /api/user/me엔드포인트 추가 (소프트 딜리트 + AuditLog 기록)signIn콜백)Changes
src/app/(page)/mypage/page.tsx—withdrawOpenstate·handleWithdraw함수·탈퇴 ConfirmModal 제거, 버튼 클릭 시/mypage/withdraw로 직접 이동src/app/(page)/mypage/withdraw/page.tsx— 말해부엉 서비스 탈퇴 약관 5개 조 렌더링, 하단 '탈퇴하기' 버튼으로 최종 ConfirmModal 오픈, 확인 시DELETE /api/user/me호출 후 signOutsrc/app/(page)/mypage/withdraw/page.module.scss— 프로젝트 내 mixin(text-title-s,text-body-s,respond-to),fn.r(), CSS 변수 활용한 스타일 추가, 하단 버튼 fixed 고정src/app/api/user/me/route.ts—DELETE핸들러 추가:deletedAt/deletionRequestedAt소프트 딜리트,AuditLog(USER_DELETED)기록, 이미 탈퇴된 계정 재요청 시 409 반환src/lib/auth/index.ts—signIn콜백에서deletedAt설정된 계정의 카카오 로그인 차단 (return false)Implementation Notes
DisputeRoom.creatorUserIdFK에 cascade 없어 hard delete 불가. 스키마의deletedAt/deletionRequestedAt필드를 활용signIn콜백에서false반환 → 로그인 페이지로 리다이렉트Test plan
/mypage/withdraw페이지로 이동 확인deleted_at/deletion_requested_at설정 확인USER_DELETED이벤트 기록 확인🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes