ai-startup
CHAPTER 27 / 100
읽기 약 2분
FUNCTION
사용자 인증: Supabase Auth + 소셜 로그인
핵심 개념
Email/Password·Google·GitHub OAuth·Magic Link·RLS 통합.
본문
Supabase Auth 활성화
1. Supabase Console → Authentication → Providers
2. Email 활성 (기본)
3. Google OAuth 추가:
- Google Cloud Console에서 Client ID/Secret
- Supabase에 입력
4. GitHub 추가 (동일)
5. Magic Link (이메일만으로 로그인) 활성클라이언트 셋업
// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr';
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
);
}
// lib/supabase/server.ts (Server Components)
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';
export async function createClient() {
const cookieStore = await cookies();
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll: () => cookieStore.getAll(),
setAll: (cookiesToSet) => {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options));
},
},
},
);
}로그인 페이지
'use client';
import { createClient } from '@/lib/supabase/client';
export default function LoginPage() {
const supabase = createClient();
const signInWithGoogle = async () => {
await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: `${location.origin}/auth/callback`,
},
});
};
const signInWithMagicLink = async (email: string) => {
const { error } = await supabase.auth.signInWithOtp({
email,
options: {
emailRedirectTo: `${location.origin}/auth/callback`,
},
});
if (error) toast.error(error.message);
else toast.success('이메일 확인해주세요');
};
return (
<div className="space-y-4">
<button onClick={signInWithGoogle}>Google로 시작</button>
<button onClick={signInWithGitHub}>GitHub로 시작</button>
<MagicLinkForm onSubmit={signInWithMagicLink} />
</div>
);
}OAuth Callback
// app/auth/callback/route.ts
import { NextResponse } from 'next/server';
import { createClient } from '@/lib/supabase/server';
export async function GET(request: Request) {
const { searchParams, origin } = new URL(request.url);
const code = searchParams.get('code');
const next = searchParams.get('next') ?? '/dashboard';
if (code) {
const supabase = await createClient();
const { error } = await supabase.auth.exchangeCodeForSession(code);
if (!error) return NextResponse.redirect(`${origin}${next}`);
}
return NextResponse.redirect(`${origin}/auth/error`);
}미들웨어 — 인증 보호
// middleware.ts
import { createServerClient } from '@supabase/ssr';
import { NextResponse, NextRequest } from 'next/server';
export async function middleware(req: NextRequest) {
let res = NextResponse.next({ request: req });
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll: () => req.cookies.getAll(),
setAll: (cookiesToSet) => {
cookiesToSet.forEach(({ name, value, options }) =>
res.cookies.set(name, value, options));
},
},
},
);
const { data: { user } } = await supabase.auth.getUser();
// 보호 경로
if (!user && req.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', req.url));
}
return res;
}
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};RLS (Row Level Security) — 자동 격리
-- 모든 테이블에 RLS
ALTER TABLE chats ENABLE ROW LEVEL SECURITY;
-- 사용자는 자기 chat만
CREATE POLICY "users_own_chats"
ON chats FOR ALL
USING (user_id = auth.uid());
-- 자동: SELECT, INSERT, UPDATE, DELETE 모두 검증
-- → 백엔드에서 user_id 필터 안 해도 안전다음 챕터
CH.28 "AI 기능 구현: OpenAI/Claude API 연동".
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
무료
월 $0 — 검증·시작 단계
Supabase Auth을 무료 도구만으로 시작하는 방법을 알려줘.
소자본
월 $20~50 — MVP·초기 운영
월 $20~50 예산으로 Supabase Auth을 검증·MVP 단계까지 진행하는 전략은?
프로덕션
월 $200~500 — 성장 단계
Supabase Auth을 프로덕션 단계로 확장할 때 필요한 도구·운영 체계는?
스택
풀스택 — 도구 조합 분석
2026년 Supabase Auth 관련 도구 5개를 조합한 추천 스택을 알려줘.
⭐ 이것만 기억하세요
사용자 인증: Supabase Auth + 소셜 로그인은 이 3가지만 확실히 잡으세요
1.Supabase Auth = OAuth + Magic Link + RLS 통합 — 30분 셋업
2.미들웨어로 자동 인증 검증 — 보호 경로 명시
3.RLS로 DB 레벨 격리 — 백엔드 user_id 필터 불필요
공유하기
진행도 27 / 100