앱 서비스를 운영하다 보면 ‘회원탈퇴’ 기능은 필수 요소 중 하나입니다. 특히 Google이나 Apple 같은 소셜 로그인을 사용하는 앱이라면, 단순한 로그아웃 이상의 처리가 필요해요. “탈퇴 후 다시 가입하면 되지”라고 생각하기 쉽지만, Supabase와 같은 인증 시스템에서는 그렇게 간단하지 않습니다. 한 번 가입한 이메일은 삭제되지 않는 이상 재사용이 불가능한 구조이기 때문입니다.
이번 글에서는 Supabase 기반의 Flutter 앱에서 회원탈퇴 기능을 어떻게 설계하고 구현할 수 있는지, 완전 삭제(Hard Delete)와 소프트 삭제(Soft Delete)를 비교하면서 현실적인 전략을 함께 정리해볼게요. 특히 인증 시스템과 데이터 보존 사이의 균형을 잡는 것이 핵심 포인트입니다.
회원탈퇴 기능에서 반드시 고려해야 할 현실적인 문제들
Flutter로 앱을 만들고, 인증은 Supabase의 소셜 로그인 기능을 활용하고 있다면, 회원탈퇴 기능은 생각보다 까다로운 문제를 내포하고 있습니다.
우선 Supabase는 이메일을 고정된 식별자로 사용합니다. 즉, Google이나 Apple로 로그인을 하면 해당 이메일이 auth.users 테이블에 등록되며, 이 이메일은 단 하나만 존재할 수 있어요. 여기서 문제는, 사용자가 탈퇴한 후 다시 동일한 이메일로 가입하려고 하면 Supabase가 이를 허용하지 않는다는 점입니다. 단순히 계정 정보를 숨기거나 상태만 바꾼다고 해서 이메일이 비워지는 게 아니에요.
즉, 진짜 삭제하지 않는 한, 동일한 이메일로 재가입할 수 없습니다.
이건 개발자에게 큰 결정을 요구하는 지점이에요. 유저 데이터를 완전히 삭제할 것인가? 아니면 탈퇴 상태로만 두고 시스템 내부적으로 차단할 것인가? 이 선택에 따라 서비스 운영 방식과 사용자 경험이 크게 달라질 수 있죠.
이 문제를 해결하기 위한 대표적인 방법은 두 가지입니다. 하나는 유저 정보를 아예 삭제해버리는 Hard Delete, 또 하나는 탈퇴 여부만 표시해두고 계정은 남기는 Soft Delete 방식이에요. 다음 본론에서는 이 두 방법의 장단점을 비교해볼게요.
Hard Delete vs Soft Delete
회원탈퇴를 구현할 때, 가장 먼저 선택해야 하는 전략은 계정을 실제로 삭제할 것인가, 아니면 상태만 변경할 것인가입니다. Supabase 환경에서는 특히 이 선택이 중요해요. 왜냐하면 auth.users 테이블에 저장된 이메일은 삭제되지 않는 이상 중복 등록이 불가능하기 때문입니다.
1. Hard Delete – 완전 삭제
Hard Delete는 말 그대로 사용자의 계정을 포함한 모든 정보를 시스템에서 삭제하는 방식입니다. Supabase에서는 클라이언트에서 auth.users를 직접 삭제할 수 없기 때문에, 이를 위해선 Edge Function을 만들어야 합니다.
예를 들어, 아래처럼 Edge Function에서 supabase.auth.admin.deleteUser(user_id) API를 호출하는 방식으로 구현할 수 있어요. 이 방법의 장점은 유저 입장에서 정말 ‘깔끔한 탈퇴 경험’을 제공할 수 있다는 것입니다. 탈퇴 후 같은 이메일로 다시 가입도 가능하고, 유저가 남긴 데이터도 모두 삭제되니 개인정보 보호 측면에서도 강점을 가집니다.
하지만 동시에, 유저의 활동 기록이나 통계 데이터를 전부 잃게 된다는 단점도 있어요. 이후 복구 요청이 와도 시스템 차원에서 되돌릴 방법이 없다는 것이 리스크입니다.
2. Soft Delete – 탈퇴 상태만 기록
반대로 Soft Delete는 유저 데이터를 완전히 삭제하지 않고, 대신 탈퇴 여부를 기록하는 방식입니다. 예를 들어 profiles 테이블에 is_deleted나 deleted_at 필드를 추가하고, 탈퇴 시 이 값을 true로 설정하는 식입니다.
그리고 Supabase의 Row Level Security(RLS) 정책에서 이 is_deleted = false 조건을 붙여두면, 탈퇴한 계정은 자동으로 시스템 접근이 제한돼요. 사용자는 여전히 auth.users에 존재하지만, 앱 내에서는 더 이상 로그인할 수 없고, “탈퇴한 계정입니다”라는 메시지를 띄워 UX를 설계할 수 있습니다.
Soft Delete는 데이터 보존 측면에서 훨씬 유연합니다. 유저가 다시 돌아오고 싶어질 때, 기존 계정을 ‘복구’ 형태로 되살릴 수 있으니까요. 다만, 앞서 언급했듯이 Supabase 구조상 동일한 이메일로 재가입은 불가능하다는 점을 유의해야 합니다.
결국 이 두 방식은 데이터 보존과 사용자 경험 사이의 트레이드오프를 어떻게 조율할 것인지에 대한 선택입니다.
실제 서비스에선 어떤 전략이 적합할까?
실무 환경에서 회원탈퇴 기능은 단순한 삭제 버튼 하나로 끝나는 기능이 아닙니다. 장기적인 사용자 경험과 재가입 흐름, 데이터 보존 전략까지 고려한 설계가 필요하죠.
가장 권장되는 방식은 Soft Delete 방식에 계정 복구 흐름을 함께 설계하는 것입니다. 재가입을 막기보다는, “이미 탈퇴한 계정입니다. 복구하시겠습니까?”와 같은 안내를 통해 계정을 재활성화할 수 있도록 하는 UX가 실제 서비스에서 많이 채택되고 있어요.
이 흐름을 Supabase 기반으로 구현할 경우 다음과 같은 절차를 따를 수 있습니다:
- 탈퇴 버튼 클릭 시 사용자에게 ‘정말 탈퇴하시겠습니까?’와 같은 확인 모달을 띄워 이탈을 방지하거나, 의도된 행동임을 분명히 합니다.
- 탈퇴를 확정하면 profiles 테이블에서 is_deleted = true, deleted_at = now() 등의 처리를 진행합니다. 동시에 유저는 로그아웃 처리합니다.
- 이후 로그인 시도 시 is_deleted 값을 체크하여 차단하거나, 복구 안내 페이지로 유도할 수 있습니다.
- 복구 요청이 있을 경우 is_deleted = false로 되돌려 간단히 계정을 활성화할 수 있습니다. 이때 인증 메일 확인 등의 절차를 추가하면 보안도 챙길 수 있어요.
이러한 전략은 데이터 보존을 유지하면서도 사용자에게 유연한 선택지를 제공하고, 반복되는 재가입 시도를 막아 불필요한 문제를 줄여줍니다.
마치며...
회원탈퇴는 사용자 lifecycle의 마지막에 위치하지만, 결코 사소하게 다룰 수 없는 기능입니다. 특히 소셜 로그인 환경에서는 한 번의 잘못된 처리로 재가입 자체가 불가능해지는 구조적 제약이 있기 때문에, 처음 설계부터 데이터와 UX를 함께 고려한 전략이 필요합니다.
Supabase와 같은 modern backend 서비스에서는 Soft Delete 방식이 비교적 쉽게 구현 가능하며, 여기에 계정 복구 UX를 결합하면 유지보수성과 사용자 만족도 모두를 잡을 수 있습니다.
Flutter 앱에서도 이 구조를 잘 녹여낸다면, 로그인부터 탈퇴까지 자연스러운 사용자 여정을 설계할 수 있어요. 작은 기능 하나가 전체 사용자 경험에 큰 영향을 미친다는 점, 잊지 말아야겠습니다.
'IT' 카테고리의 다른 글
flutter run과 flutter build의 차이는 무엇일까? (0) | 2025.06.20 |
---|---|
Supabase Realtime으로 실시간 협업 구현 (0) | 2025.06.18 |
Firebase로 손쉽게 테스트 앱 배포하기 (0) | 2025.06.17 |
바이브 코딩으로 앱 개발 하다가 겪은 병목들 (6) | 2025.06.13 |
나의 챗봇에도 RAG 붙이기 (8) | 2025.06.12 |