Tech

Supabse를 활용한 통합 인증(SSO) 시스템 구축에 대한 기록

by탐험대장
2026년 4월 25일

현재 네모네AIM과 지금여기 2개의 서비스를 운영하면서 어쩔 수 없이 각각 2개의 회원 체계를 가지고 가고 있었는데 조만간 3번째 서비스 구축에 들어가면서 회원들의 통합 인증(SSO) 시스템 구축에 대한 니즈가 필요해졌다. 일반 회사에서는 대 작업이었겠지만 현재 서비스는 아주 가볍고 로그인이 활발한 서비스는 아니기에 빠르게 도입하는 것이 좋겠다고 생각했다.



📋 사전에 정의(결정)해야 할 사항

  1. 지원할 로그인 수단 (Auth Providers)


  •  이메일/비밀번호 가입을 유지할 것인가?
  •  소셜 로그인 채널은 무엇을 열 것인가? (예: Google 필수, Kakao/Naver/Apple 추가 여부)

  2. 회원 고유 식별자 (Primary Key) 정책


  •  기존에는 이메일(user_email)을 기준으로 데이터를 저장했다.
  •  Supabase는 가입 시 무조건 고유한 UUID를 발급하며 앞으로 모든 서비스의 DB(게시글, 댓글, 좋아요 등)는 이메일 대신 이 UUID를 기준으로 연결하는 것이 가장 안전하고 정석적인 방법이라고.

  3. 프로필 정보 저장 위치 (매우 중요)


  •  옵션 A (추천): 닉네임, 프로필 사진 등은 Supabase의 자체 DB(public.profiles 테이블)에 저장하고, 각 서비스의 FastAPI 백엔드는 "이 유저의 UUID가 이거구나!" 인증만 처리.
  •  옵션 B: Supabase는 오직 '로그인(토큰 발급)'만 담당하고, 기존처럼 각 서비스의 DB에 회원 테이블을 유지하여 가입 성공 시 동기화.



🚀 통합 로그인 개발 단계별 프로세스 (데이터 초기화 가정)

Phase 1: Supabase 초기 세팅 (Dashboard)

  1. 프로젝트 생성: Supabase에 가입하고 'Nemone SSO'라는 단일 프로젝트를 생성.

  2. 로그인 채널 설정: Google 클라우드 콘솔의 OAuth 키를 Supabase에 등록(이메일 가입 사용 시 인증 이메일 템플릿도 세팅)

  3. 리다이렉트 URL 등록: 로그인 성공 후 돌아갈 모든 서비스의 주소를 허용 목록에 추가.


 Phase 2: 백엔드(FastAPI) 전면 개편 (인증 로직 덜어내기)

  1. 자체 인증 코드 삭제: 기존 main.py에 있던 낡은 회원가입, 로그인, 비밀번호 해싱 코드를 완전히 삭제.

  2. DB 스키마(테이블) 변경:


  •  기존 DB의 users 테이블을 삭제하거나 역할을 축소합니다.
  •  comments, likes, saved_courses, themes 테이블의 user_email 컬럼을 모두 user_id (UUID 타입)로 변경.

  3. 토큰 검증 미들웨어 추가:


  •  프론트엔드가 API를 찌를 때 Authorization: Bearer <토큰>을 보내면, FastAPI가 Supabase의 JWT 시크릿 키를 이용해 "위조되지 않은 진짜 토큰인지" 검증하는 함수를 만듬.

 Phase 3: 프론트엔드 통합 (Next.js)

  1. 기존 NextAuth 제거: 네모네AIM과 지금여기에 설치된 무거운 next-auth 패키지와 관련 API 폴더(app/api/auth)를 모두 삭제.

  2. Supabase SSR 도입: @supabase/ssr 패키지를 설치하여, 서버와 클라이언트 양쪽에서 로그인 상태를 알 수 있게 세팅.

  3. 통합 쿠키(SSO) 설정:


  •  사용자가 nemoneai.com에서 로그인하면, 쿠키의 도메인을 .nemoneai.com으로 굽도록 설정.
  •  이렇게 하면 사용자가 now.nemoneai.com으로 넘어갔을 때, 다시 로그인할 필요 없이 자동으로 로그인된 상태(SSO)가 유지.

  4. UI 컴포넌트 수정: 기존 로그인 버튼들이 NextAuth 대신 Supabase Auth 함수를 호출하도록 연결합니다.



🆚 옵션 A vs 옵션 B 심층 비교

 🚀 옵션 A: Supabase에 모든 프로필 저장

 Supabase의 자체 DB(`public.profiles`)에 이메일, 닉네임, 프로필 사진을 모두 저장하고, 자체 백엔드(GCP DB)는 오직 UUID(고유번호)만

 가지고 게시글/댓글과 연결하는 방식.

  * 장점 (Pros):


  •  가장 완벽한 SSO (Single Sign-On): 네모네AIM에서 닉네임을 바꾸면, NOW HERE나 새로 만들 서비스에서도 즉시 바뀐 닉네임이적용. 진정한 '통합 계정'.
  •  백엔드 초경량화: 자체 백엔드(GCP DB)에 users 테이블 자체가 필요 없어집니다. 백엔드 코드가 매우 단순해짐.
  •  보안성 최상: 유저의 모든 개인정보가 암호화된 강력한 Supabase 인프라 안에 격리되므로, 자체 서버가 뚫리더라도 유저의 민감 정보는 안전.

  * 단점 (Cons):


  •  데이터 조인(Join)의 불편함: 게시글이나 댓글을 불러올 때 자체 DB(GCP)에는 '글 내용'과 '작성자 UUID'만 있음. 프론트엔드에서 작성자 닉네임을 보여주려면 Supabase API를 한 번 더 호출해서 가져와야 하므로, 초기 로딩 시 API 통신이 약간 늘어남.

 🏗 옵션 B: Supabase는 인증만, 프로필은 기존 DB(GCP)에 저장

 Supabase는 "이메일 맞음, 토큰 발급해줄게!" 역할만 하고, 유저가 가입/로그인할 때 발급된 UUID와 프로필 정보를 우리 백엔드(GCP DB의

 `users` 테이블)에 동기화해 두는 방식.

  * 장점 (Pros):


  •  조회 성능 최상: 게시글을 불러올 때 기존처럼 한 번의 SQL 쿼리(Join)로 작성자 닉네임, 사진까지 한 방에 가져올 수 있어 매우 빠름.
  •  데이터 주권: 모든 유저의 상세 활동 데이터와 프로필이 우리 통제하에 있는 GCP DB 한곳에 모여 있어 데이터 분석(통계)이 편리.

  * 단점 (Cons):


  •  동기화의 늪 (가장 큰 단점): 유저가 네모네AIM에서 닉네임을 바꿨을 때, NOW HERE DB에도 그 변경 사항을 쏴줘야 하는(혹은 중앙 DB를 따로 파서 각 백엔드가 바라보게 해야 하는) 복잡한 데이터 동기화 지옥이 시작.
  •  아키텍처 복잡: 회원가입 시 Supabase가 성공 응답을 주면, 백엔드의 Webhook이나 프론트엔드의 별도 API 호출을 통해 우리 DB에도 유저를 생성하는 코드를 짜야 해서 버그가 생길 확률이 높음.



[신규 회원가입 프로세스 시나리오]

1단계: 진입 (Entry)

유저가 '지금여기'나 '네모네AIM' 중 어느 곳에서 가입을 시도하든, 디자인과 로직이 통일된 통합 로그인/가입 페이지를 마주.


2단계: 약관 동의 (Consent)

가입 버튼을 누르면 가장 먼저 약관 동의 화면이 나옵니다. 여기서 '통합 회원'임을 명확히 인지시킵니다.


3단계: 인증 및 정보 입력 (Auth & Profile)

소셜 로그인(OAuth) 또는 이메일 인증을 진행합니다.


4단계: 가입 완료 및 웰컴 가이드 (Welcome)

가입이 끝나면 유저에게 이 계정의 가치를 설명해 줍니다.



💡 독립된 서브도메인 구축

  1. 도메인 통일: 가입 페이지의 주소를 auth.nemoneai.com과 같이 독립된 서브도메인으로 운영하여, 유저에게 "여기가 인증 센터구나"라는 신뢰감을 줌.
  2. 자동 리다이렉트: '지금여기'에서 가입을 시작했다면, 가입 완료 후 다시 '지금여기'의 메인 화면으로 자연스럽게 돌아가게끔 redirect_url 파라미터를 정교하게 세팅.
  3. 프로필 연동: Supabase Storage에 저장된 프로필 사진 하나가 모든 앱에서 똑같이 뜨게 함.
  4. 네모네만의 특별한 질문(예: "당신을 설레게 하는 것은 무엇인가요? ) : 향후 취향에 따른 메인페이지 설정에 활용 예정
# Supabse# auth# 통합인증# SSO# 로그인# 토큰# 쿠키# 서브도메인

COMMENTS

의견을 남기려면 로그인이 필요합니다.

NO COMMENTS YET.
Nemone Store Banner