반응형
Supabase로 로그인 · 회원가입(인증) 로직 만들기 — 실전 가이드

Supabase Auth를 이용해 이메일/비밀번호 기반 회원가입·로그인, 세션 쿠키, 토큰 검증, 비밀번호 재설정까지 안전하게 구현하는 방법을 정리했습니다. 클라이언트 → 서버 → DB 접근 흐름과 보안 권장사항을 포함합니다.
목차
- 핵심 흐름 요약
- 사전 준비
- 클라이언트 예제 (SignUp / SignIn)
- 서버(Express) 예제 — 토큰 검증 + HttpOnly 쿠키
- 회원가입 후 프로필 생성 / 트리거
- 비밀번호 재설정 · 이메일 확인
- 세션/토큰 갱신 정책
- RLS(행 수준 보안) 추천 패턴
- 보안 체크리스트 & 디버깅 팁
1. 핵심 흐름 요약
- 클라이언트에서 이메일/비밀번호로 가입(signUp) 또는 로그인(signInWithPassword).
- Supabase Auth가 access_token + refresh_token을 발급.
- 서버는 클라이언트에서 전달받은 access_token을 검증하고 HttpOnly 쿠키로 저장(권장).
- 보호된 API는 서버에서 토큰 검증 후 사용자 컨텍스트(req.user)로 처리.
2. 사전 준비
- Supabase 프로젝트 생성 →
Project URL,anon key,service_role key확보 - 필수 패키지:
@supabase/supabase-js, (Express 사용 시)express,cookie-parser - 보안 원칙: service_role key는 절대 클라이언트 노출 금지 — 서버 전용.
3. 클라이언트 예제
브라우저/React에서 간단한 회원가입·로그인 예시
<script type="module">
import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm'
const SUPABASE_URL = 'https://your-project.supabase.co'
const SUPABASE_ANON_KEY = 'public-anon-key'
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
// 회원가입
async function signUp(email, password) {
const { data, error } = await supabase.auth.signUp({ email, password });
console.log({ data, error });
}
// 이메일+비밀번호 로그인
async function signIn(email, password) {
const { data, error } = await supabase.auth.signInWithPassword({ email, password });
console.log({ data, error }); // data.session.access_token 등 확인
}
</script>
권장: 클라이언트에서 로그인 후 토큰을 서버로 전달 → 서버가 쿠키로 저장
4. 서버(Express) 예제 — 토큰 검증 & HttpOnly 쿠키
클라이언트에서 받은 access_token을 서버가 검증하고 HttpOnly 쿠키로 저장하는 안전한 패턴
// server.js (요약)
require('dotenv').config();
const express = require('express');
const cookieParser = require('cookie-parser');
const { createClient } = require('@supabase/supabase-js');
const app = express();
app.use(express.json());
app.use(cookieParser());
const SUPABASE_URL = process.env.SUPABASE_URL;
const SUPABASE_ANON_KEY = process.env.SUPABASE_ANON_KEY;
const SUPABASE_SERVICE_ROLE = process.env.SUPABASE_SERVICE_ROLE;
const supabaseAdmin = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE);
const supabasePublic = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
app.post('/api/auth/login', async (req, res) => {
const { email, password } = req.body;
const { data, error } = await supabasePublic.auth.signInWithPassword({ email, password });
if (error) return res.status(400).json({ error: error.message });
const accessToken = data.session.access_token;
const refreshToken = data.session.refresh_token;
// 토큰 검증
const { data: userData, error: userErr } = await supabaseAdmin.auth.getUser(accessToken);
if (userErr) return res.status(401).json({ error: userErr.message });
// HttpOnly 쿠키로 저장
res.cookie('sb_access_token', accessToken, { httpOnly:true, secure:process.env.NODE_ENV==='production', sameSite:'lax', maxAge:7*24*3600*1000 });
res.cookie('sb_refresh_token', refreshToken, { httpOnly:true, secure:process.env.NODE_ENV==='production', sameSite:'lax', maxAge:30*24*3600*1000 });
return res.json({ user: userData.user });
});
보안: service_role 키는 서버 전용으로만 사용. HTTPS 필수.
5. 회원가입 후 프로필 생성 / 자동화
가입 직후 프로필 레코드를 추가하려면:
- 클라이언트에서 signUp 후 서버에 프로필 생성 요청
- 또는 Supabase의 Auth Trigger / Edge Function으로 자동 생성
// 서버에서 service_role로 profiles 테이블 생성 예
await supabaseAdmin.from('profiles').insert([{ id: user.id, email: user.email, full_name }]);
6. 비밀번호 재설정 · 이메일 확인
- signUp 옵션에서
redirectTo설정으로 이메일 클릭 후 리디렉션 제어 - 비밀번호 재설정: Supabase의 resetPasswordForEmail API 사용 → 프론트에서 새 비밀번호 제출
- 문제: 메일이 안 오면 SMTP 설정(프로젝트 설정) 확인
7. 세션 / 토큰 갱신 정책
- access_token 만료(예: 1시간) → refresh_token으로 갱신
- 클라이언트는
onAuthStateChange로 상태 변화 감지 가능 - 서버는 refresh_token을 이용해 새 세션을 발급하거나, 필요시 re-login 유도
8. RLS(행 수준 보안) 추천 패턴
Supabase RLS와 auth.uid()를 조합해 안전한 테이블 접근 제어를 구성하세요.
-- profiles 테이블 예시 정책
CREATE POLICY "Users can manage their profile."
ON public.profiles
USING ( auth.uid() = id );
주의: service_role 키로는 RLS를 우회할 수 있으니 서버 내부 로직에만 사용.
9. 보안 체크리스트 & 디버깅 팁
- service_role key: 절대 클라이언트 노출 금지, 환경변수로만 관리
- HTTPS: 로그인/토큰 전송 시 반드시 HTTPS
- 쿠키 옵션: HttpOnly, Secure, SameSite 적용
- 이메일 확인: 스팸/봇 가입 방지 위해 이메일 검증 활성화
- 브루트포스 방지: 로그인 시도 제한·CAPTCHA 적용 고려
- 디버깅: Supabase SDK의
data와error를 모두 로깅 - 시간 동기화: 토큰 검증 실패 시 서버 시간이 정확한지 확인
요약
- 클라이언트에서 signUp/signIn 처리 → 토큰 획득
- 서버에서 access_token 검증 → HttpOnly 쿠키로 저장(권장)
- RLS로 DB 접근 제한, service_role은 서버 전용으로만 사용
- HTTPS, 쿠키 보안, 이메일 확인 등 보안 설정 필수
반응형
'개발 · IT > 백엔드' 카테고리의 다른 글
| AI로 API 개발 속도 높이는 방법 (0) | 2026.01.15 |
|---|---|
| 동네 신호등 — Micro SaaS를 만들어 배포 후 운영까지 (0) | 2025.12.08 |
| Spring Boot vs Node.js — 어느 쪽을 선택할까? (0) | 2025.11.25 |
| PM2로 Node 서버 운영하기 — 설치부터 운영·모니터링·무중단 배포까지 (0) | 2025.11.21 |
| Express 미들웨어 실행 순서 완전 정리 (0) | 2025.11.21 |
댓글