챕터 17 · L2
SaaS 로그인 인증 구축 매뉴얼 (Google · Kakao · Supabase)
Next.js + Supabase Auth + Google OAuth + Kakao OAuth, 초보자도 그대로 따라 할 수 있는 셋팅 가이드
Next.js 웹사이트에 Supabase 인증을 붙이고, Google·Kakao 소셜 로그인을 끝까지 설정할 수 있어요.
참고 문서
SaaS launch (Notion)
인증·SaaS
| **핵심 메시지** | "벽은 생각보다 낮다" — 시작, 인증, 결제 3가지 벽만 넘으면 누구나 서비스 런칭 가능 | · <!-- Notion Reference: 바이브코딩으로 SaaS 런칭하기 | 로그인·결제·배포 풀 튜토리얼 -->
배포 가이드
Supabase·Vercel
| 빌드 실패 `Module not found` | Root Directory가 `projects/skoolchef-tutorial`인지 확인, `pnpm install`이 해당 폴더에서 실행되는지 확인 | · Skoolchef Tutorial — 배
공개 문서
17. SaaS 로그인 인증 구축 매뉴얼 (Google · Kakao · Supabase)
아래는 content/courses/17-login-auth-google-kakao-supabase.mdx 와 동일한 원문입니다. Markdown과 HTML 변환 결과를 각각 복사할 수 있습니다.
공개 문서 원문 (Markdown)
# SaaS 로그인 인증 구축 매뉴얼
> **이 챕터를 마치면** Next.js 웹사이트에 Supabase 인증을 붙이고, Google·Kakao 소셜 로그인을 끝까지 설정할 수 있어요.
> 초보자도 복붙·따라 하기만 하면 되는 **완전 가이드** 형태로 정리했어요.
**대상:** Next.js로 SaaS(로그인·결제 포함)를 만들고 싶은 분
**필요한 것:** Node.js 설치, Supabase·Google·Kakao 계정
**레벨:** L2 (중급 — 실무 적용 매뉴얼)
---
## 1️⃣ 전체 인증 구조 이해
우리가 만드는 SaaS 로그인 구조는 아래와 같아요.
```
사용자
↓
Next.js 웹사이트
↓
Supabase Auth
↓
OAuth Provider
├ Google
└ Kakao
```
**로그인 흐름 요약**
1. 사용자가 "Google 로그인" 또는 "Kakao 로그인" 클릭
2. Next.js가 Supabase Auth를 통해 해당 OAuth(Google/Kakao)로 이동
3. 사용자가 OAuth 제공자에서 로그인·동의
4. Supabase가 콜백을 받아 **세션 생성** → 로그인 완료
즉, **Supabase가 인증 서버 역할**을 하고, Google·Kakao는 "누구인지 확인해 주는 쪽"이라고 보면 돼요.
---
## 2️⃣ Supabase 프로젝트 생성
Supabase에서 Auth 서버 역할을 할 프로젝트를 만듭니다.
1. **[Supabase 대시보드](https://supabase.com/dashboard)** 접속 후 로그인 (GitHub 계정 가능)
2. **New Project** 클릭
3. 다음을 입력:
- **Organization** 선택 (없으면 생성)
- **Project name**: 예) `saas-auth`
- **Database password** 생성 (복구·DB 접속용, 안전한 곳에 보관)
- **Region** 선택 (가까운 리전 권장)
4. **Create new project** 클릭 후 생성 완료될 때까지 대기
---
## 3️⃣ Supabase 기본 정보 확인
나중에 Next.js에서 쓰일 **두 가지 값**을 미리 확인합니다.
1. Supabase 대시보드에서 **Project Settings** (휴지통 아이콘 옆 톱니바퀴) 클릭
2. 왼쪽에서 **API** 선택
3. 아래 두 개를 복사해 두기:
- **Project URL** — 예: `https://xxxxxxxx.supabase.co`
- **anon public key** — 긴 JWT 문자열 (`eyJhbGciOiJIUzI1NiIs...` 형태)
> 💡 **anon key**는 "퍼블릭 키"라서 브라우저에 노출돼도 되지만, **service_role key**는 절대 클라이언트에 넣지 마세요.
---
## 4️⃣ Supabase Auth 설정
Supabase에서 OAuth 로그인을 쓰려면 **Provider**를 켜야 합니다.
1. 대시보드 왼쪽 **Authentication** → **Providers** 이동
2. **Google**, **Kakao** 항목이 보이는지 확인 (여기서 나중에 키를 입력합니다)
먼저 Google·Kakao 쪽에서 발급받은 키를 준비한 뒤, 아래 5️⃣·6️⃣에서 다시 이 화면으로 와서 입력하면 됩니다.
---
## 5️⃣ Google OAuth 설정
"우리 앱에서 구글 로그인을 쓸 거다"라고 Google에 등록하는 과정입니다.
### 5-1. Google Cloud Console 접속
1. **[Google Cloud Console](https://console.cloud.google.com/)** 접속
2. **Select Project** → **New Project** (예: 프로젝트 이름 `saas-google-auth`) → 생성
### 5-2. OAuth 동의 화면 설정
1. 왼쪽 메뉴 **APIs & Services** → **OAuth consent screen**
2. **User Type**: **External** 선택 (일반 사용자 로그인용) → **Create**
3. 필수 항목만 입력:
- **App name**: 예) `SkoolChef`
- **User support email**: 본인 이메일
- **Developer contact information**: 본인 이메일
4. **Save and Continue** → Scopes는 기본값으로 **Save and Continue** → 테스트 사용자(선택) 후 **Save and Continue**
> ⚠️ **"동의 화면을 구성해야 합니다"** 라고 나오면 위 OAuth 동의 화면을 먼저 완료해야 합니다. **테스트 모드**로 시작한 뒤, 나중에 프로덕션으로 전환하면 됩니다.
### 5-3. OAuth 클라이언트 ID 생성
1. **APIs & Services** → **Credentials**
2. **Create Credentials** → **OAuth client ID**
3. **Application type**: **Web application**
4. **Name**: 예) `SkoolChef Web`
5. **Authorized redirect URIs**에 **추가**:
- 형식: `https://[PROJECT_REF].supabase.co/auth/v1/callback`
- 예: `https://uyacajrkkylpbirktavh.supabase.co/auth/v1/callback`
(Supabase 대시보드 **Authentication** → **URL Configuration**에서도 같은 URL을 확인할 수 있어요. **프로젝트 ID**는 Supabase URL의 `https://xxxxx.supabase.co` 에서 `xxxxx` 부분입니다.)
6. **Create** 클릭 후 **Client ID**와 **Client secret** 복사
### 5-4. Supabase에 Google Provider 연결
1. **Supabase** → **Authentication** → **Providers** → **Google**
2. **Enable** 켜기
3. **Client ID** (Google에서 복사) 붙여넣기
4. **Client Secret** (Google에서 복사) 붙여넣기
5. **Save**
---
## 6️⃣ Kakao OAuth 설정
Kakao Developers에서 앱을 만들고, Supabase에서 Kakao Provider를 켭니다.
### 6-1. Kakao Developers 접속 및 앱 생성
1. **[Kakao Developers](https://developers.kakao.com/)** 접속 후 로그인
2. **내 애플리케이션** → **애플리케이션 추가하기**
3. **앱 이름** 예: `SkoolKorea` → 저장
### 6-2. 플랫폼 및 Redirect URI 설정
1. 방금 만든 앱 클릭 → **앱 키** 탭
2. **REST API 키** 확인 (나중에 Supabase에 입력)
3. **플랫폼** 탭 → **Web** 플랫폼 추가 (이미 있으면 수정)
4. **사이트 도메인**에 로컬 테스트용 `http://localhost:3000` 추가
5. **카카오 로그인** 메뉴 → **활성화** ON
6. **Redirect URI**에 다음 추가:
- `https://[PROJECT_REF].supabase.co/auth/v1/callback`
예: `https://uyacajrkkylpbirktavh.supabase.co/auth/v1/callback`
7. **저장**
### 6-3. Supabase에 Kakao Provider 연결
1. **Supabase** → **Authentication** → **Providers** → **Kakao**
2. **Enable** 켜기
3. **Kakao Client ID**에 위에서 확인한 **REST API 키** 입력
4. **Client Secret**은 Kakao에서 발급한 값이 있으면 입력, 없으면 비워둬도 동작하는 경우가 많습니다.
5. **Save**
---
## 7️⃣ Next.js 프로젝트 생성
로그인을 붙일 Next.js 앱이 없다면 새로 만듭니다.
```bash
npx create-next-app@latest saas-login-auth-checkout
```
- TypeScript, ESLint, Tailwind, `src/` 디렉터리, App Router 등은 원하는 대로 선택 (권장: Yes)
- 완료 후:
```bash
cd saas-login-auth-checkout
```
---
## 8️⃣ Supabase SDK 설치
Next.js 프로젝트 루트에서:
```bash
npm install @supabase/supabase-js
```
---
## 9️⃣ 환경 변수 설정
프로젝트 **루트**에 `.env.local` 파일을 만들고 아래를 넣습니다. (값은 본인 Supabase 프로젝트 것으로 교체)
```bash
NEXT_PUBLIC_SUPABASE_URL=https://[PROJECT_REF].supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=[anon public key]
```
- `[PROJECT_REF]`: Supabase Project URL의 `xxxxx` 부분
- `[anon public key]`: 3️⃣에서 복사한 anon public key
> ⚠️ `.env.local`은 Git에 올리지 마세요. `.gitignore`에 이미 포함되어 있는지 확인하세요.
---
## 🔟 Supabase Client 생성
브라우저에서 Supabase를 부르기 위한 클라이언트를 한 번만 만듭니다.
**파일:** `lib/supabaseClient.ts` (또는 `src/lib/supabaseClient.ts`)
```ts
import { createClient } from "@supabase/supabase-js"
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
export const supabase = createClient(supabaseUrl, supabaseKey)
```
---
## 1️⃣1️⃣ Google 로그인 코드
로그인 버튼에서 호출할 함수 예시입니다.
```ts
import { supabase } from "@/lib/supabaseClient"
export async function signInWithGoogle() {
await supabase.auth.signInWithOAuth({
provider: "google",
})
}
```
---
## 1️⃣2️⃣ Kakao 로그인 코드
```ts
import { supabase } from "@/lib/supabaseClient"
export async function signInWithKakao() {
await supabase.auth.signInWithOAuth({
provider: "kakao",
})
}
```
---
## 1️⃣3️⃣ 로그인 버튼 예시
페이지에서 버튼으로 호출하는 예시입니다.
```tsx
<button type="button" onClick={() => signInWithGoogle()}>
Google 로그인
</button>
<button type="button" onClick={() => signInWithKakao()}>
Kakao 로그인
</button>
```
(실제로는 `signInWithGoogle` / `signInWithKakao`를 해당 페이지 컴포넌트에서 import해서 사용하면 됩니다.)
---
## 1️⃣4️⃣ 로그인 테스트
1. 터미널에서:
```bash
npm run dev
```
2. 브라우저에서 `http://localhost:3000` 접속
3. Google 로그인 / Kakao 로그인 버튼을 눌러서:
- 각 OAuth 화면으로 이동하는지
- 로그인·동의 후 다시 우리 사이트로 돌아오는지
- Supabase **Authentication** → **Users**에 사용자가 생기는지 확인
---
## 1️⃣5️⃣ 로그인 성공 확인 (Supabase)
- Supabase 대시보드 → **Authentication** → **Users**
- 방금 로그인한 계정이 보이면 정상입니다.
- **Provider** 컬럼에 `google` / `kakao`로 표시됩니다.
---
## 1️⃣6️⃣ 현재까지 완성된 구조
지금까지 만든 구조는 다음과 같습니다.
- **Next.js** — 프론트 + API 라우트
- **Supabase Auth** — 세션·OAuth 콜백 처리
- **Google OAuth** — 구글 로그인
- **Kakao OAuth** — 카카오 로그인
- **User DB** — Supabase가 자동 관리하는 사용자
- **Session** — Supabase가 쿠키/로컬 스토리지로 관리
**다음 단계 (실제 SaaS에서 꼭 할 일)**
- **로그인 안 하면 접근 차단**: `/dashboard`, `/billing`, `/settings` 등은 로그인한 사용자만 접근하도록 하기
- **기술**: Next.js **Middleware**에서 Supabase 세션을 확인하고, 없으면 로그인 페이지로 리다이렉트
이 부분은 별도 챕터나 "보호된 라우트" 가이드에서 이어서 다루면 좋습니다.
---
## 9️⃣ 문제 해결 체크리스트
설정 후 로그인이 안 될 때 아래를 순서대로 확인하세요.
| # | 확인 항목 | 조치 |
|---|-----------|------|
| 1 | **Invalid API key** | `.env.local`의 `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY`가 맞는지, 앞뒤 공백이 없는지 확인 |
| 2 | **redirect_uri_mismatch** (Google) | Google Cloud Console **Authorized redirect URIs**에 `https://[PROJECT_REF].supabase.co/auth/v1/callback`가 **완전히 동일**하게 등록됐는지 확인 (프로젝트 ID 포함) |
| 3 | **Redirect URI** (Kakao) | Kakao Developers **카카오 로그인** → Redirect URI에 위와 같은 Supabase 콜백 URL이 등록됐는지 확인 |
| 4 | **동의 화면 구성** (Google) | "동의 화면을 구성해야 합니다" 오류 시 **OAuth consent screen**에서 앱 이름·이메일 등 필수 항목 저장 후 다시 시도 |
| 5 | **Provider 비활성** | Supabase **Authentication** → **Providers**에서 Google/Kakao가 **Enable** 되어 있는지 확인 |
| 6 | **도메인 변경 시** | 나중에 Vercel 등으로 배포하면 Supabase **URL Configuration**의 **Site URL**과 **Redirect URLs**에 배포 도메인 추가, Google/Kakao에도 해당 도메인·콜백 URL 추가 |
에러 메시지를 그대로 복사해서 AI 에이전트에게 붙여넣어도 원인 파악에 도움이 됩니다.
---
## (선택) Supabase MCP 연결
AI 코딩 도구(Cursor, Antigravity 등)에서 Supabase DB·스키마를 자연어로 조회하고 싶다면 **Supabase MCP**를 켜 두면 편합니다.
프로젝트 루트에 `.cursor/mcp.json` (또는 에디터별 MCP 설정 파일)을 두고:
```json
{
"mcpServers": {
"supabase": {
"url": "https://mcp.supabase.com/mcp"
}
}
}
```
에디터 재시작 후 Supabase 로그인으로 연결하면, "내 Supabase 테이블 목록 보여줘" 같은 요청을 할 수 있습니다.
인증 설정 자체에는 필수는 아니에요.
---
## 10장 보강 프로세스 적용: 인증 구축 품질 게이트
이 챕터는 구현량보다 **인증 안정성**이 핵심입니다.
기본샘플프로세스에 맞춰 실패 패턴을 먼저 차단하고 품질 게이트를 통과하도록 구성합니다.
### 인증 품질 게이트 (필수 5단계)
1. **Provider 설정 검증**
- Google/Kakao Redirect URI 정확 일치 확인
2. **환경변수 검증**
- `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY` 점검
3. **로그인 왕복 검증**
- OAuth 이동 → 콜백 복귀 → 세션 생성까지 확인
4. **보호 라우트 검증**
- 비로그인 상태에서 보호 페이지 접근 차단 확인
5. **에러 UX 검증**
- 실패 시 사용자 메시지/재시도 안내 확인
### 17챕터 실패 패턴 TOP 5
1. **Redirect URI 오타**
- 대응: 콘솔 값과 문자열 완전 일치 비교
2. **프로바이더 활성화 누락**
- 대응: Supabase Provider Enable 상태 점검
3. **로컬/배포 도메인 분리 누락**
- 대응: localhost + production 도메인 모두 등록
4. **세션은 생겼지만 라우팅 미처리**
- 대응: 로그인 후 목적지 리다이렉트 정책 명시
5. **시크릿 관리 취약**
- 대응: `.env.local`만 사용, Git 추적 차단 검증
### 17챕터 체크리스트 (DoD)
- [ ] Google 로그인 왕복 성공
- [ ] Kakao 로그인 왕복 성공
- [ ] Supabase Users에 provider 표시 확인
- [ ] 보호 라우트 접근 제어 동작 확인
- [ ] 배포 환경 도메인까지 설정 완료
> **다음 챕터 입력값:** 시각 결과물에 반영할 인증 상태(로그인/비로그인), 핵심 지표 카드, 데모 시나리오공개 문서 변환 코드 (HTML)
<h1>SaaS 로그인 인증 구축 매뉴얼</h1>
<blockquote>
<p><strong>이 챕터를 마치면</strong> Next.js 웹사이트에 Supabase 인증을 붙이고, Google·Kakao 소셜 로그인을 끝까지 설정할 수 있어요.<br>초보자도 복붙·따라 하기만 하면 되는 <strong>완전 가이드</strong> 형태로 정리했어요.</p>
</blockquote>
<p><strong>대상:</strong> Next.js로 SaaS(로그인·결제 포함)를 만들고 싶은 분<br><strong>필요한 것:</strong> Node.js 설치, Supabase·Google·Kakao 계정<br><strong>레벨:</strong> L2 (중급 — 실무 적용 매뉴얼)</p>
<hr>
<h2>1️⃣ 전체 인증 구조 이해</h2>
<p>우리가 만드는 SaaS 로그인 구조는 아래와 같아요.</p>
<pre><code>사용자
↓
Next.js 웹사이트
↓
Supabase Auth
↓
OAuth Provider
├ Google
└ Kakao
</code></pre>
<p><strong>로그인 흐름 요약</strong></p>
<ol>
<li>사용자가 "Google 로그인" 또는 "Kakao 로그인" 클릭</li>
<li>Next.js가 Supabase Auth를 통해 해당 OAuth(Google/Kakao)로 이동</li>
<li>사용자가 OAuth 제공자에서 로그인·동의</li>
<li>Supabase가 콜백을 받아 <strong>세션 생성</strong> → 로그인 완료</li>
</ol>
<p>즉, <strong>Supabase가 인증 서버 역할</strong>을 하고, Google·Kakao는 "누구인지 확인해 주는 쪽"이라고 보면 돼요.</p>
<hr>
<h2>2️⃣ Supabase 프로젝트 생성</h2>
<p>Supabase에서 Auth 서버 역할을 할 프로젝트를 만듭니다.</p>
<ol>
<li><strong><a href="https://supabase.com/dashboard">Supabase 대시보드</a></strong> 접속 후 로그인 (GitHub 계정 가능)</li>
<li><strong>New Project</strong> 클릭</li>
<li>다음을 입력:<ul>
<li><strong>Organization</strong> 선택 (없으면 생성)</li>
<li><strong>Project name</strong>: 예) <code>saas-auth</code></li>
<li><strong>Database password</strong> 생성 (복구·DB 접속용, 안전한 곳에 보관)</li>
<li><strong>Region</strong> 선택 (가까운 리전 권장)</li>
</ul>
</li>
<li><strong>Create new project</strong> 클릭 후 생성 완료될 때까지 대기</li>
</ol>
<hr>
<h2>3️⃣ Supabase 기본 정보 확인</h2>
<p>나중에 Next.js에서 쓰일 <strong>두 가지 값</strong>을 미리 확인합니다.</p>
<ol>
<li>Supabase 대시보드에서 <strong>Project Settings</strong> (휴지통 아이콘 옆 톱니바퀴) 클릭</li>
<li>왼쪽에서 <strong>API</strong> 선택</li>
<li>아래 두 개를 복사해 두기:<ul>
<li><strong>Project URL</strong> — 예: <code>https://xxxxxxxx.supabase.co</code></li>
<li><strong>anon public key</strong> — 긴 JWT 문자열 (<code>eyJhbGciOiJIUzI1NiIs...</code> 형태)</li>
</ul>
</li>
</ol>
<blockquote>
<p>💡 <strong>anon key</strong>는 "퍼블릭 키"라서 브라우저에 노출돼도 되지만, <strong>service_role key</strong>는 절대 클라이언트에 넣지 마세요.</p>
</blockquote>
<hr>
<h2>4️⃣ Supabase Auth 설정</h2>
<p>Supabase에서 OAuth 로그인을 쓰려면 <strong>Provider</strong>를 켜야 합니다.</p>
<ol>
<li>대시보드 왼쪽 <strong>Authentication</strong> → <strong>Providers</strong> 이동</li>
<li><strong>Google</strong>, <strong>Kakao</strong> 항목이 보이는지 확인 (여기서 나중에 키를 입력합니다)</li>
</ol>
<p>먼저 Google·Kakao 쪽에서 발급받은 키를 준비한 뒤, 아래 5️⃣·6️⃣에서 다시 이 화면으로 와서 입력하면 됩니다.</p>
<hr>
<h2>5️⃣ Google OAuth 설정</h2>
<p>"우리 앱에서 구글 로그인을 쓸 거다"라고 Google에 등록하는 과정입니다.</p>
<h3>5-1. Google Cloud Console 접속</h3>
<ol>
<li><strong><a href="https://console.cloud.google.com/">Google Cloud Console</a></strong> 접속</li>
<li><strong>Select Project</strong> → <strong>New Project</strong> (예: 프로젝트 이름 <code>saas-google-auth</code>) → 생성</li>
</ol>
<h3>5-2. OAuth 동의 화면 설정</h3>
<ol>
<li>왼쪽 메뉴 <strong>APIs & Services</strong> → <strong>OAuth consent screen</strong></li>
<li><strong>User Type</strong>: <strong>External</strong> 선택 (일반 사용자 로그인용) → <strong>Create</strong></li>
<li>필수 항목만 입력:<ul>
<li><strong>App name</strong>: 예) <code>SkoolChef</code></li>
<li><strong>User support email</strong>: 본인 이메일</li>
<li><strong>Developer contact information</strong>: 본인 이메일</li>
</ul>
</li>
<li><strong>Save and Continue</strong> → Scopes는 기본값으로 <strong>Save and Continue</strong> → 테스트 사용자(선택) 후 <strong>Save and Continue</strong></li>
</ol>
<blockquote>
<p>⚠️ <strong>"동의 화면을 구성해야 합니다"</strong> 라고 나오면 위 OAuth 동의 화면을 먼저 완료해야 합니다. <strong>테스트 모드</strong>로 시작한 뒤, 나중에 프로덕션으로 전환하면 됩니다.</p>
</blockquote>
<h3>5-3. OAuth 클라이언트 ID 생성</h3>
<ol>
<li><strong>APIs & Services</strong> → <strong>Credentials</strong></li>
<li><strong>Create Credentials</strong> → <strong>OAuth client ID</strong></li>
<li><strong>Application type</strong>: <strong>Web application</strong></li>
<li><strong>Name</strong>: 예) <code>SkoolChef Web</code></li>
<li><strong>Authorized redirect URIs</strong>에 <strong>추가</strong>:<ul>
<li>형식: <code>https://[PROJECT_REF].supabase.co/auth/v1/callback</code></li>
<li>예: <code>https://uyacajrkkylpbirktavh.supabase.co/auth/v1/callback</code><br>(Supabase 대시보드 <strong>Authentication</strong> → <strong>URL Configuration</strong>에서도 같은 URL을 확인할 수 있어요. <strong>프로젝트 ID</strong>는 Supabase URL의 <code>https://xxxxx.supabase.co</code> 에서 <code>xxxxx</code> 부분입니다.)</li>
</ul>
</li>
<li><strong>Create</strong> 클릭 후 <strong>Client ID</strong>와 <strong>Client secret</strong> 복사</li>
</ol>
<h3>5-4. Supabase에 Google Provider 연결</h3>
<ol>
<li><strong>Supabase</strong> → <strong>Authentication</strong> → <strong>Providers</strong> → <strong>Google</strong></li>
<li><strong>Enable</strong> 켜기</li>
<li><strong>Client ID</strong> (Google에서 복사) 붙여넣기</li>
<li><strong>Client Secret</strong> (Google에서 복사) 붙여넣기</li>
<li><strong>Save</strong></li>
</ol>
<hr>
<h2>6️⃣ Kakao OAuth 설정</h2>
<p>Kakao Developers에서 앱을 만들고, Supabase에서 Kakao Provider를 켭니다.</p>
<h3>6-1. Kakao Developers 접속 및 앱 생성</h3>
<ol>
<li><strong><a href="https://developers.kakao.com/">Kakao Developers</a></strong> 접속 후 로그인</li>
<li><strong>내 애플리케이션</strong> → <strong>애플리케이션 추가하기</strong></li>
<li><strong>앱 이름</strong> 예: <code>SkoolKorea</code> → 저장</li>
</ol>
<h3>6-2. 플랫폼 및 Redirect URI 설정</h3>
<ol>
<li>방금 만든 앱 클릭 → <strong>앱 키</strong> 탭</li>
<li><strong>REST API 키</strong> 확인 (나중에 Supabase에 입력)</li>
<li><strong>플랫폼</strong> 탭 → <strong>Web</strong> 플랫폼 추가 (이미 있으면 수정)</li>
<li><strong>사이트 도메인</strong>에 로컬 테스트용 <code>http://localhost:3000</code> 추가</li>
<li><strong>카카오 로그인</strong> 메뉴 → <strong>활성화</strong> ON</li>
<li><strong>Redirect URI</strong>에 다음 추가:<ul>
<li><code>https://[PROJECT_REF].supabase.co/auth/v1/callback</code><br>예: <code>https://uyacajrkkylpbirktavh.supabase.co/auth/v1/callback</code></li>
</ul>
</li>
<li><strong>저장</strong></li>
</ol>
<h3>6-3. Supabase에 Kakao Provider 연결</h3>
<ol>
<li><strong>Supabase</strong> → <strong>Authentication</strong> → <strong>Providers</strong> → <strong>Kakao</strong></li>
<li><strong>Enable</strong> 켜기</li>
<li><strong>Kakao Client ID</strong>에 위에서 확인한 <strong>REST API 키</strong> 입력</li>
<li><strong>Client Secret</strong>은 Kakao에서 발급한 값이 있으면 입력, 없으면 비워둬도 동작하는 경우가 많습니다.</li>
<li><strong>Save</strong></li>
</ol>
<hr>
<h2>7️⃣ Next.js 프로젝트 생성</h2>
<p>로그인을 붙일 Next.js 앱이 없다면 새로 만듭니다.</p>
<pre><code class="language-bash">npx create-next-app@latest saas-login-auth-checkout
</code></pre>
<ul>
<li>TypeScript, ESLint, Tailwind, <code>src/</code> 디렉터리, App Router 등은 원하는 대로 선택 (권장: Yes)</li>
<li>완료 후:</li>
</ul>
<pre><code class="language-bash">cd saas-login-auth-checkout
</code></pre>
<hr>
<h2>8️⃣ Supabase SDK 설치</h2>
<p>Next.js 프로젝트 루트에서:</p>
<pre><code class="language-bash">npm install @supabase/supabase-js
</code></pre>
<hr>
<h2>9️⃣ 환경 변수 설정</h2>
<p>프로젝트 <strong>루트</strong>에 <code>.env.local</code> 파일을 만들고 아래를 넣습니다. (값은 본인 Supabase 프로젝트 것으로 교체)</p>
<pre><code class="language-bash">NEXT_PUBLIC_SUPABASE_URL=https://[PROJECT_REF].supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=[anon public key]
</code></pre>
<ul>
<li><code>[PROJECT_REF]</code>: Supabase Project URL의 <code>xxxxx</code> 부분</li>
<li><code>[anon public key]</code>: 3️⃣에서 복사한 anon public key</li>
</ul>
<blockquote>
<p>⚠️ <code>.env.local</code>은 Git에 올리지 마세요. <code>.gitignore</code>에 이미 포함되어 있는지 확인하세요.</p>
</blockquote>
<hr>
<h2>🔟 Supabase Client 생성</h2>
<p>브라우저에서 Supabase를 부르기 위한 클라이언트를 한 번만 만듭니다.</p>
<p><strong>파일:</strong> <code>lib/supabaseClient.ts</code> (또는 <code>src/lib/supabaseClient.ts</code>)</p>
<pre><code class="language-ts">import { createClient } from "@supabase/supabase-js"
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
export const supabase = createClient(supabaseUrl, supabaseKey)
</code></pre>
<hr>
<h2>1️⃣1️⃣ Google 로그인 코드</h2>
<p>로그인 버튼에서 호출할 함수 예시입니다.</p>
<pre><code class="language-ts">import { supabase } from "@/lib/supabaseClient"
export async function signInWithGoogle() {
await supabase.auth.signInWithOAuth({
provider: "google",
})
}
</code></pre>
<hr>
<h2>1️⃣2️⃣ Kakao 로그인 코드</h2>
<pre><code class="language-ts">import { supabase } from "@/lib/supabaseClient"
export async function signInWithKakao() {
await supabase.auth.signInWithOAuth({
provider: "kakao",
})
}
</code></pre>
<hr>
<h2>1️⃣3️⃣ 로그인 버튼 예시</h2>
<p>페이지에서 버튼으로 호출하는 예시입니다.</p>
<pre><code class="language-tsx"><button type="button" onClick={() => signInWithGoogle()}>
Google 로그인
</button>
<button type="button" onClick={() => signInWithKakao()}>
Kakao 로그인
</button>
</code></pre>
<p>(실제로는 <code>signInWithGoogle</code> / <code>signInWithKakao</code>를 해당 페이지 컴포넌트에서 import해서 사용하면 됩니다.)</p>
<hr>
<h2>1️⃣4️⃣ 로그인 테스트</h2>
<ol>
<li><p>터미널에서:</p>
<pre><code class="language-bash">npm run dev
</code></pre>
</li>
<li><p>브라우저에서 <code>http://localhost:3000</code> 접속</p>
</li>
<li><p>Google 로그인 / Kakao 로그인 버튼을 눌러서:</p>
<ul>
<li>각 OAuth 화면으로 이동하는지</li>
<li>로그인·동의 후 다시 우리 사이트로 돌아오는지</li>
<li>Supabase <strong>Authentication</strong> → <strong>Users</strong>에 사용자가 생기는지 확인</li>
</ul>
</li>
</ol>
<hr>
<h2>1️⃣5️⃣ 로그인 성공 확인 (Supabase)</h2>
<ul>
<li>Supabase 대시보드 → <strong>Authentication</strong> → <strong>Users</strong></li>
<li>방금 로그인한 계정이 보이면 정상입니다. </li>
<li><strong>Provider</strong> 컬럼에 <code>google</code> / <code>kakao</code>로 표시됩니다.</li>
</ul>
<hr>
<h2>1️⃣6️⃣ 현재까지 완성된 구조</h2>
<p>지금까지 만든 구조는 다음과 같습니다.</p>
<ul>
<li><strong>Next.js</strong> — 프론트 + API 라우트</li>
<li><strong>Supabase Auth</strong> — 세션·OAuth 콜백 처리</li>
<li><strong>Google OAuth</strong> — 구글 로그인</li>
<li><strong>Kakao OAuth</strong> — 카카오 로그인</li>
<li><strong>User DB</strong> — Supabase가 자동 관리하는 사용자</li>
<li><strong>Session</strong> — Supabase가 쿠키/로컬 스토리지로 관리</li>
</ul>
<p><strong>다음 단계 (실제 SaaS에서 꼭 할 일)</strong></p>
<ul>
<li><strong>로그인 안 하면 접근 차단</strong>: <code>/dashboard</code>, <code>/billing</code>, <code>/settings</code> 등은 로그인한 사용자만 접근하도록 하기</li>
<li><strong>기술</strong>: Next.js <strong>Middleware</strong>에서 Supabase 세션을 확인하고, 없으면 로그인 페이지로 리다이렉트</li>
</ul>
<p>이 부분은 별도 챕터나 "보호된 라우트" 가이드에서 이어서 다루면 좋습니다.</p>
<hr>
<h2>9️⃣ 문제 해결 체크리스트</h2>
<p>설정 후 로그인이 안 될 때 아래를 순서대로 확인하세요.</p>
<table>
<thead>
<tr>
<th>#</th>
<th>확인 항목</th>
<th>조치</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td><strong>Invalid API key</strong></td>
<td><code>.env.local</code>의 <code>NEXT_PUBLIC_SUPABASE_URL</code>, <code>NEXT_PUBLIC_SUPABASE_ANON_KEY</code>가 맞는지, 앞뒤 공백이 없는지 확인</td>
</tr>
<tr>
<td>2</td>
<td><strong>redirect_uri_mismatch</strong> (Google)</td>
<td>Google Cloud Console <strong>Authorized redirect URIs</strong>에 <code>https://[PROJECT_REF].supabase.co/auth/v1/callback</code>가 <strong>완전히 동일</strong>하게 등록됐는지 확인 (프로젝트 ID 포함)</td>
</tr>
<tr>
<td>3</td>
<td><strong>Redirect URI</strong> (Kakao)</td>
<td>Kakao Developers <strong>카카오 로그인</strong> → Redirect URI에 위와 같은 Supabase 콜백 URL이 등록됐는지 확인</td>
</tr>
<tr>
<td>4</td>
<td><strong>동의 화면 구성</strong> (Google)</td>
<td>"동의 화면을 구성해야 합니다" 오류 시 <strong>OAuth consent screen</strong>에서 앱 이름·이메일 등 필수 항목 저장 후 다시 시도</td>
</tr>
<tr>
<td>5</td>
<td><strong>Provider 비활성</strong></td>
<td>Supabase <strong>Authentication</strong> → <strong>Providers</strong>에서 Google/Kakao가 <strong>Enable</strong> 되어 있는지 확인</td>
</tr>
<tr>
<td>6</td>
<td><strong>도메인 변경 시</strong></td>
<td>나중에 Vercel 등으로 배포하면 Supabase <strong>URL Configuration</strong>의 <strong>Site URL</strong>과 <strong>Redirect URLs</strong>에 배포 도메인 추가, Google/Kakao에도 해당 도메인·콜백 URL 추가</td>
</tr>
</tbody></table>
<p>에러 메시지를 그대로 복사해서 AI 에이전트에게 붙여넣어도 원인 파악에 도움이 됩니다.</p>
<hr>
<h2>(선택) Supabase MCP 연결</h2>
<p>AI 코딩 도구(Cursor, Antigravity 등)에서 Supabase DB·스키마를 자연어로 조회하고 싶다면 <strong>Supabase MCP</strong>를 켜 두면 편합니다.<br>프로젝트 루트에 <code>.cursor/mcp.json</code> (또는 에디터별 MCP 설정 파일)을 두고:</p>
<pre><code class="language-json">{
"mcpServers": {
"supabase": {
"url": "https://mcp.supabase.com/mcp"
}
}
}
</code></pre>
<p>에디터 재시작 후 Supabase 로그인으로 연결하면, "내 Supabase 테이블 목록 보여줘" 같은 요청을 할 수 있습니다.<br>인증 설정 자체에는 필수는 아니에요.</p>
<hr>
<h2>10장 보강 프로세스 적용: 인증 구축 품질 게이트</h2>
<p>이 챕터는 구현량보다 <strong>인증 안정성</strong>이 핵심입니다.<br>기본샘플프로세스에 맞춰 실패 패턴을 먼저 차단하고 품질 게이트를 통과하도록 구성합니다.</p>
<h3>인증 품질 게이트 (필수 5단계)</h3>
<ol>
<li><p><strong>Provider 설정 검증</strong></p>
<ul>
<li>Google/Kakao Redirect URI 정확 일치 확인</li>
</ul>
</li>
<li><p><strong>환경변수 검증</strong></p>
<ul>
<li><code>NEXT_PUBLIC_SUPABASE_URL</code>, <code>NEXT_PUBLIC_SUPABASE_ANON_KEY</code> 점검</li>
</ul>
</li>
<li><p><strong>로그인 왕복 검증</strong></p>
<ul>
<li>OAuth 이동 → 콜백 복귀 → 세션 생성까지 확인</li>
</ul>
</li>
<li><p><strong>보호 라우트 검증</strong></p>
<ul>
<li>비로그인 상태에서 보호 페이지 접근 차단 확인</li>
</ul>
</li>
<li><p><strong>에러 UX 검증</strong></p>
<ul>
<li>실패 시 사용자 메시지/재시도 안내 확인</li>
</ul>
</li>
</ol>
<h3>17챕터 실패 패턴 TOP 5</h3>
<ol>
<li><p><strong>Redirect URI 오타</strong></p>
<ul>
<li>대응: 콘솔 값과 문자열 완전 일치 비교</li>
</ul>
</li>
<li><p><strong>프로바이더 활성화 누락</strong></p>
<ul>
<li>대응: Supabase Provider Enable 상태 점검</li>
</ul>
</li>
<li><p><strong>로컬/배포 도메인 분리 누락</strong></p>
<ul>
<li>대응: localhost + production 도메인 모두 등록</li>
</ul>
</li>
<li><p><strong>세션은 생겼지만 라우팅 미처리</strong></p>
<ul>
<li>대응: 로그인 후 목적지 리다이렉트 정책 명시</li>
</ul>
</li>
<li><p><strong>시크릿 관리 취약</strong></p>
<ul>
<li>대응: <code>.env.local</code>만 사용, Git 추적 차단 검증</li>
</ul>
</li>
</ol>
<h3>17챕터 체크리스트 (DoD)</h3>
<ul>
<li><input disabled="" type="checkbox"> Google 로그인 왕복 성공</li>
<li><input disabled="" type="checkbox"> Kakao 로그인 왕복 성공</li>
<li><input disabled="" type="checkbox"> Supabase Users에 provider 표시 확인</li>
<li><input disabled="" type="checkbox"> 보호 라우트 접근 제어 동작 확인</li>
<li><input disabled="" type="checkbox"> 배포 환경 도메인까지 설정 완료</li>
</ul>
<blockquote>
<p><strong>다음 챕터 입력값:</strong> 시각 결과물에 반영할 인증 상태(로그인/비로그인), 핵심 지표 카드, 데모 시나리오</p>
</blockquote>