Back-End/Supabase
Next.js + Supabase로 시작하는 인증 및 DB 연동
봉의일상
2025. 5. 7. 15:07
Next.js에서 Supabase를 활용해 인증 및 데이터베이스 연동을 시작하는 방법을 단계별로 정리한 글입니다.
Supabase는 Firebase의 오픈소스 대안으로, Postgres 기반의 데이터베이스와 인증, 스토리지 기능을 제공합니다.
프로젝트 준비
1. Supabase 프로젝트 생성
- https://supabase.com에 가입 및 로그인
- New Project 클릭 후 프로젝트 생성 (비밀번호는 꼭 기억)
- 생성 후 Settings > API에서 다음 정보 확인:
- Project URL
- anon/public API key
2. Next.js 프로젝트 설정
npx create-next-app@latest next-supabase-demo
cd next-supabase-demo
npm install @supabase/supabase-js
3. Supabase 클라이언트 설정
lib/supabaseClient.ts 파일 생성:
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
.env.local 파일:
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
소셜 로그인, 직접 구축할까?
Supabase는 Google, GitHub, Facebook 등의 OAuth 기반 소셜 로그인을 기본 제공하지만, 실무에서는 사용자 정보와 인증 흐름을 직접 제어할 수 있는 커스터마이징이 더 바람직할 수 있습니다.
왜 직접 구현하는 게 좋을까?
- 토큰 저장 및 갱신을 우리 서비스에서 직접 제어 가능
- 사용자 정보를 우리 DB 테이블에 명확히 저장 가능
- 고급 기능 (예: 친구 목록, 캘린더 접근 등) 연동 가능
- 향후 SSO, 2FA 등의 확장에도 유리함
커스텀 OAuth 흐름 요약
[프론트] 로그인 버튼 클릭
→ /api/auth/kakao 등으로 리다이렉트
→ Kakao/Google에서 로그인
→ access_token 반환
→ 백엔드에서 사용자 정보 저장 + 세션 발급
예제 코드: Kakao OAuth (API Route)
// pages/api/auth/kakao/callback.ts
import type { NextApiRequest, NextApiResponse } from 'next'
import axios from 'axios'
import { supabase } from '@/lib/supabaseClient'
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const code = req.query.code as string
const { data: tokenRes } = await axios.post(
'https://kauth.kakao.com/oauth/token',
new URLSearchParams({
grant_type: 'authorization_code',
client_id: process.env.KAKAO_CLIENT_ID!,
redirect_uri: process.env.KAKAO_REDIRECT_URI!,
code,
client_secret: process.env.KAKAO_CLIENT_SECRET!,
}),
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
)
const kakaoAccessToken = tokenRes.access_token
const { data: userRes } = await axios.get('https://kapi.kakao.com/v2/user/me', {
headers: { Authorization: `Bearer ${kakaoAccessToken}` },
})
const kakaoUser = userRes
await supabase.from('users').upsert({
id: kakaoUser.id,
email: kakaoUser.kakao_account.email,
nickname: kakaoUser.properties.nickname,
provider: 'kakao',
})
res.redirect('/')
}
테이블 생성 및 연동
예시: todos 테이블 생성
- 필드: id, title, is_done, user_id
- RLS (Row-Level Security) 설정 후 다음 정책 추가:
create policy "Users can view own todos"
on todos for select
using (auth.uid() = user_id);
프론트엔드 연동 예시:
const { data, error } = await supabase
.from('todos')
.select('*')
.eq('user_id', user.id)
await supabase.from('todos').insert([
{ title: '블로그 쓰기', is_done: false, user_id: user.id }
])
테이블 생성 및 연동
아래는 Supabase SQL Editor나 초기 설정 시 사용할 수 있는 회원 및 할 일 테이블 생성 쿼리 예시입니다.
회원 테이블: users
create table if not exists users (
id bigint primary key,
email text unique not null,
nickname text,
provider text,
created_at timestamp with time zone default timezone('utc'::text, now())
);
할 일 테이블: todos
create table if not exists todos (
id bigint generated always as identity primary key,
title text not null,
is_done boolean default false,
user_id bigint references users(id),
created_at timestamp with time zone default timezone('utc'::text, now())
);
RLS 정책 (todos)
alter table todos enable row level security;
create policy "Users can view own todos"
on todos for select
using (auth.uid()::bigint = user_id);
create policy "Users can insert their own todos"
on todos for insert
with check (auth.uid()::bigint = user_id);
마무리 및 다음 단계
- Supabase는 인증, DB, 스토리지, 실시간 기능까지 제공하는 매우 강력한 BaaS입니다.
- 커스터마이징된 소셜 로그인은 더 나은 통제력과 확장성을 제공합니다.
- Next.js와의 궁합도 좋아 SSR, SSG에서도 유연하게 사용할 수 있습니다.