Intro
저는 본인인증 DI가 같은 계정이 여러 개 생기는 문제를 겪었습니다. 사용자에게 “이미 인증한 계정이 있어요”라고 안내하고 싶었지만, RLS 때문에 클라이언트가 마음대로 프로필을 조회할 수 없었죠. 그래서 서비스 롤 클라이언트를 이용해 중복 계정을 탐지하는 API를 만들었습니다.
핵심 아이디어 요약
- DI 값을 파라미터로 받아 동일한 프로필을 모두 조회합니다.
- 세션 사용자가 있으면 본인을 제외한 계정만 반환합니다.
- Supabase Auth의 사용자 정보까지 결합해 어떤 계정이 활성 상태인지 표시합니다.
준비와 선택
- 서비스 롤: 프로필과 Auth 정보를 함께 조회해야 해서 서비스 롤 클라이언트를 사용했습니다.
- 현재 사용자 구분: 세션에서 user ID를 읽어 같은 DI라도 현재 로그인한 계정은 제외했습니다.
- fallback: DI 파라미터가 없으면 현재 사용자 프로필에서 DI를 가져와 조회했습니다.
구현 여정
Step 1: DI 결정
쿼리에 di가 없으면 세션 사용자 프로필을 조회해 DI를 찾습니다. 둘 다 없으면 400으로 종료합니다.
Step 2: 프로필 조회
프로필 테이블에서 동일한 DI를 가진 항목을 모두 가져옵니다. 필요한 필드는 이름, 전화번호, 인증 여부 등입니다.
Step 3: Auth 사용자 매칭
각 프로필 ID로 admin.auth.admin.getUserById를 호출해 활성/비활성 상태를 확인합니다. 현재 사용자와 동일하면 otherUsers에서 제외합니다.
import { createAdminClient } from './supabaseAdmin';
const adminClient = createAdminClient();
const { data: profiles } = await adminClient
.from('profile')
.select('id, di, full_name, phone_number, is_verified, is_complete')
.eq('di', di);
const users = await Promise.all(
(profiles ?? []).map(async profile => {
const { data } = await adminClient.auth.admin.getUserById(profile.id);
return data?.user ?? null;
}),
);
const otherUsers = users.filter(
user => user && (!currentUserId || user.id !== currentUserId),
);
return {
success: true,
di,
profiles,
users,
otherUsers,
isDuplicated: otherUsers.length > 0,
};
겪은 이슈와 해결 과정
- 권한 문제: 서비스 롤이 아니면 프로필과 Auth를 동시에 볼 수 없어, 관리자 클라이언트 사용을 강제했습니다.
- Auth 호출 실패: 일부 계정은 삭제되어 있어 조회가 실패했습니다. try/catch로 예외를 무시하고 null을 반환해 흐름을 유지했습니다.
- 응답 형식: 프런트에서 활용하기 쉽도록
isDuplicated플래그와otherUsers배열을 포함해 반환했습니다.
결과와 회고
이제는 DI가 중복된 사용자가 있으면 UI에서 즉시 알려줄 수 있습니다. 계정 복구나 고객센터 응대도 훨씬 빨라졌죠. 다음에는 중복 계정을 자동으로 잠그는 정책을 검토해볼 생각입니다.
여러분은 본인인증 식별자를 어떻게 관리하고 계신가요? 다른 사례가 있다면 댓글로 공유해주세요.