탈퇴 화면, 결제 이력은 어떻게 보여줘야 할까
결제 이력이 남는 탈퇴 플로우를 프론트에서 어떻게 설계했는지, 화면 구성과 컴포넌트 분리 기준을 정리했어요.
탈퇴 버튼 하나 만드는 데 하루가 걸렸어요. 로직이 어려워서가 아니라, 화면에 뭘 써야 할지 몰라서요.
개인정보보호법 21조 3항을 보면, 다른 법령상 보존 의무가 있는 정보는 파기하지 않되 다른 개인정보와 분리해서 저장·관리해야 해요. 결제 이력이 딱 여기 걸립니다. 전자상거래법상 계약·대금결제 기록은 5년 보존이거든요. 그러니까 사용자가 탈퇴해도 결제 기록은 남아요. 문제는 이걸 화면에서 어떻게 말하냐는 거였어요.
"전부 삭제됩니다"라고 쓰면 거짓말이 돼요
처음 만든 확인 모달에는 이렇게 적혀 있었어요. "모든 데이터가 삭제되며 복구할 수 없습니다." 직접 스키마를 확인해 보니 이 문장이 틀렸더라고요. 결제 테이블 행은 그대로 남고, 식별자만 익명 토큰으로 바뀔 뿐이었어요.
그래서 모달 문구를 세 덩어리로 나눴어요.
- 즉시 삭제되는 것
- 법정 기간 보관되는 것
- 보관 종료 시점
이렇게 나누니까 카피가 짧아졌어요. "프로필·작성글은 즉시 삭제돼요. 결제·환불 기록은 관련 법에 따라 5년간 별도로 보관한 뒤 파기해요." 두 문장이면 충분하더라고요.
프론트에서 실수하기 쉬운 지점
적용해 봤더니 걸린 게 두 가지였어요.
첫째, 탈퇴 후 마이페이지 캐시. React Query 캐시를 안 비우고 라우팅만 시키면, 뒤로가기 한 번에 지워졌어야 할 프로필이 잠깐 다시 보여요. 서버는 이미 지웠는데 화면만 남은 거죠. 탈퇴 성공 응답을 받으면 queryClient.clear()를 부르고 나서 이동시켰어요.
둘째, 결제 이력 화면을 그대로 재사용하면 안 돼요. 탈퇴한 계정의 보관 기록은 일반 조회 경로에서 막혀 있어야 해요. 그래서 기존 <PaymentList />를 재사용하지 않고, 관리 목적의 별도 화면으로 분리했어요. 컴포넌트 이름부터 다르게 두니까 나중에 "여기 왜 접근 되지?" 하는 사고를 줄일 수 있었어요.
확인 단계는 두 단계면 충분해요
탈퇴 플로우를 몇 번 다시 만들어 보니 이 구조로 수렴했어요.
3단계 이상으로 늘리면 해지 방해로 읽힐 수 있어요. 공정거래위원회가 지적하는 다크패턴 유형 중에 해지를 어렵게 만드는 게 들어 있거든요. 탈퇴는 가입만큼 쉬워야 해요. 대신 되돌릴 수 없는 동작이니까 마지막에 비밀번호 재확인 한 번은 넣었어요.
체크박스 문구도 "동의합니다" 같은 뭉뚱그린 표현 대신 "결제 기록이 법정 기간 보관되는 것을 확인했어요"로 바꿨어요. 무엇에 동의하는지가 문장 안에 들어 있어야 해요.
개발자 화면에도 경계를 그어요
보관 데이터를 조회하는 어드민 화면은 접근 로그가 남게 만들었어요. 법이 말하는 "분리 저장·관리"에서 관리 쪽이 이걸 요구한다고 봤거든요. 스키마만 나누고 누가 언제 봤는지 모르면 관리라고 부르기 어렵죠. 프론트에서는 조회 목적을 선택하는 셀렉트를 조회 버튼 앞에 붙였어요. 입력 항목 하나 늘었지만, 나중에 감사 로그를 볼 때 이게 전부더라고요.
법령 문구를 직접 확인하는 게 제일 확실한데, 저는 이럴 때 플랜엘로 조문을 찾아봐요. 국가법령정보센터 데이터 기반이라 개보법 조문을 원문 그대로 볼 수 있어요. 월 3건까지 무료라 개발 중 한두 번 확인하기엔 넉넉했어요. 블로그 요약이나 AI 답변만 믿고 화면 카피를 쓰면 위험해요. 조문은 개정되니까요.
정리하면
탈퇴 화면은 기능이 아니라 약속이에요. 화면에 쓴 문장이 실제 DB 동작과 다르면, 그건 UI 버그가 아니라 신뢰 문제가 돼요. 스키마를 먼저 열어 보고 문구를 쓰는 순서를 지키면 이 어긋남은 잘 안 생기더라고요. 만드는 데 10분, 문구 정하는 데 반나절 걸리는 화면이지만 그럴 값어치는 있어요. 🙂
관련 글
댓글
아직 댓글이 없어요. 첫 댓글을 남겨주세요.