Supabase로 Next.js 인증을 구현하려다 보면 @supabase/auth-helpers-nextjs와 @supabase/ssr 사이에서 고민하게 됩니다. 결론부터 말하면 auth-helpers는 이미 deprecated(지원 중단)된 패키지예요. 이 글에서는 왜 @supabase/ssr로 갈아타야 하는지, 실제 삽질 경험을 바탕으로 설명합니다.
🤔 처음엔 auth-helpers-nextjs로 시작했다
Supabase 인증을 붙이려고 구글링을 하면 나오는 글 대부분이 @supabase/auth-helpers-nextjs 기준으로 작성되어 있어요. 자연스럽게 이걸 먼저 설치했고, 공식 문서도 예전엔 이걸 기본으로 소개했으니까요.
그런데 막상 써보니 뭔가 자꾸 구조가 꼬이는 느낌이었어요. App Router랑 잘 안 맞는 것 같고, middleware에서 세션 처리가 이상하게 동작하고… 결국 공식 문서를 다시 찾아보다가 충격적인 걸 발견했어요.
# npm 패키지 페이지에 이렇게 써있다
# Package Consolidation Notice:
# The @supabase/ssr package replaces the deprecated @supabase/auth-helpers-* packages.
💥 이미 deprecated였던 거예요. auth-helpers 계열 패키지 전체가 @supabase/ssr로 통합됐고, 더 이상 적극적으로 개선되지 않아요.
📦 두 패키지, 뭐가 다른 거야?
프론트엔드 입문자 입장에서 쉽게 설명하면 이래요.
예전에 Supabase는 프레임워크마다 별도 패키지를 만들어서 배포했어요.
- Next.js 쓰면 →
@supabase/auth-helpers-nextjs - React 쓰면 →
@supabase/auth-helpers-react - SvelteKit 쓰면 →
@supabase/auth-helpers-sveltekit
근데 이렇게 쪼개놓으니까 관리가 힘들고, 프레임워크마다 API가 미묘하게 달라서 혼란이 생겼어요. 그래서 “그냥 하나로 합치자”는 결론이 난 게 @supabase/ssr이에요.
| 항목 | auth-helpers-nextjs | @supabase/ssr |
|---|---|---|
| 현재 상태 | ⚠️ Deprecated (지원 중단) | ✅ 현재 공식 권장 |
| 구조 | Next.js 전용 | 프레임워크 독립적 |
| App Router 지원 | 제한적 | 완전 지원 |
| Server / Client 구분 | 모호함 | 명확하게 분리됨 |
| middleware 연동 | 불편함 | 공식 패턴으로 쉽게 가능 |
| 앞으로의 업데이트 | ❌ 없음 | ✅ 계속 개선 중 |
🔄 함수 이름도 다 바뀌었다
기존에 auth-helpers에서 쓰던 함수들이 @supabase/ssr에서는 이름이 바뀌었어요. 마이그레이션 할 때 헷갈리는 부분이라 정리해둘게요.
| auth-helpers-nextjs (구) | @supabase/ssr (신) | 어디서 쓰나 |
|---|---|---|
createMiddlewareClient | createServerClient | middleware.ts |
createClientComponentClient | createBrowserClient | 클라이언트 컴포넌트 |
createServerComponentClient | createServerClient | 서버 컴포넌트 |
createRouteHandlerClient | createServerClient | Route Handler (API) |
👉 서버 쪽에서 쓰던 것들은 이제 전부 createServerClient 하나로 통일됐어요. 훨씬 심플해졌죠?
⚙️ @supabase/ssr 실제 설치 & 기본 세팅
말이 길었는데 실제로 어떻게 쓰는지 보여드릴게요. 초보자도 따라할 수 있게 처음부터 설명할게요.
1단계: 패키지 설치
npm install @supabase/supabase-js @supabase/ssr
2단계: 환경변수 설정
프로젝트 루트에 .env.local 파일을 만들고 아래 내용을 채워요. Supabase 대시보드 → Settings → API에서 값을 복사하면 돼요.
NEXT_PUBLIC_SUPABASE_URL=https://xxxxxxxxxxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here
3단계: 클라이언트 유틸 파일 만들기
@supabase/ssr은 사용하는 환경에 따라 클라이언트를 다르게 만들어야 해요. 크게 두 가지예요.
브라우저(클라이언트 컴포넌트)용 — utils/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!
)
}
서버(서버 컴포넌트 / Route Handler)용 — utils/supabase/server.ts
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() {
return cookieStore.getAll()
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
)
} catch {
// 서버 컴포넌트에서 호출된 경우 쿠키 쓰기가 안 됨
// middleware가 대신 처리해줌 → 무시해도 OK
}
},
},
}
)
}
💡 왜 두 개를 따로 만드나요?
브라우저와 서버는 쿠키를 다루는 방식이 달라요. 브라우저는document.cookie로, 서버는next/headers의cookies()로 접근해요. 그래서 환경에 맞는 클라이언트를 각각 만들어줘야 Supabase 세션이 제대로 동작해요.
🙅 auth-helpers 계속 써도 되나요?
당장 에러가 나진 않아요. deprecated라는 게 “지금 당장 동작 안 함”이 아니라 “앞으로 업데이트 안 하겠다”는 선언이거든요.
근데 문제는 이래요.
- Next.js 버전이 올라가면서 호환성 문제가 생길 수 있어요
- 보안 패치도 더 이상 없어요
- 두 패키지를 동시에 쓰면 인증이 꼬이는 버그가 생겨요 (공식 문서에서도 같이 쓰지 말라고 경고해요)
신규 프로젝트라면 처음부터 @supabase/ssr만 쓰세요. 기존 프로젝트라면 마이그레이션을 서두르는 게 좋아요.
✅ 정리
@supabase/auth-helpers-nextjs는 이미 deprecated예요 → 새 프로젝트엔 쓰지 마세요@supabase/ssr이 공식 대체제이고, App Router에 맞게 설계되어 있어요- 브라우저용
createBrowserClient, 서버용createServerClient로 역할이 명확하게 분리돼요 - 두 패키지를 동시에 사용하면 인증이 꼬이니까 반드시 하나만 쓰세요
👉 다음 편에서는 서버 인증에서 절대 헷갈리면 안 되는 getSession vs getUser 차이를 파헤쳐볼게요!



