# 인증 시스템 구현 가이드 ## 📋 개요 Laravel PHP 백엔드와 Next.js 15 프론트엔드 간의 3가지 인증 방식을 지원하는 통합 인증 시스템 --- ## 🔐 지원 인증 방식 ### 1️⃣ Sanctum Session (웹 사용자) - **대상**: 웹 브라우저 사용자 - **방식**: HTTP-only 쿠키 기반 세션 - **보안**: XSS 방어 + CSRF 토큰 - **Stateful**: Yes ### 2️⃣ Bearer Token (모바일/SPA) - **대상**: 모바일 앱, 외부 SPA - **방식**: Authorization: Bearer {token} - **보안**: 토큰 만료 시간 관리 - **Stateful**: No ### 3️⃣ API Key (시스템 간 통신) - **대상**: 서버 간 통신, 백그라운드 작업 - **방식**: X-API-KEY: {key} - **보안**: 서버 사이드 전용 (환경 변수) - **Stateful**: No --- ## 📁 파일 구조 ``` src/ ├─ lib/api/ │ ├─ client.ts # 통합 HTTP Client (3가지 인증 방식) │ │ │ └─ auth/ │ ├─ types.ts # 인증 타입 정의 │ ├─ auth-config.ts # 인증 설정 (라우트, URL) │ │ │ ├─ sanctum-client.ts # Sanctum 전용 클라이언트 │ ├─ bearer-client.ts # Bearer 토큰 클라이언트 │ ├─ api-key-client.ts # API Key 클라이언트 │ │ │ ├─ token-storage.ts # Bearer 토큰 저장 관리 │ ├─ api-key-validator.ts # API Key 검증 유틸 │ └─ server-auth.ts # 서버 컴포넌트 인증 유틸 │ ├─ contexts/ │ └─ AuthContext.tsx # 클라이언트 인증 상태 관리 │ ├─ middleware.ts # 통합 미들웨어 (Bot + Auth + i18n) │ └─ app/[locale]/ ├─ (auth)/ │ └─ login/page.tsx # 로그인 페이지 │ └─ (protected)/ └─ dashboard/page.tsx # 보호된 페이지 ``` --- ## 🔧 환경 변수 설정 ### .env.local (실제 키 값) ```env # API Configuration NEXT_PUBLIC_API_URL=https://api.5130.co.kr NEXT_PUBLIC_FRONTEND_URL=http://localhost:3000 # Authentication Mode NEXT_PUBLIC_AUTH_MODE=sanctum # API Key (서버 사이드 전용 - 절대 공개 금지!) API_KEY=42Jfwc6EaRQ04GNRmLR5kzJp5UudSOzGGqjmdk1a ``` ### .env.example (템플릿) ```env NEXT_PUBLIC_API_URL=https://api.5130.co.kr NEXT_PUBLIC_FRONTEND_URL=http://localhost:3000 NEXT_PUBLIC_AUTH_MODE=sanctum API_KEY=your-secret-api-key-here ``` --- ## 🎯 구현 단계 ### Phase 1: 핵심 인프라 (필수) 1. `lib/api/auth/types.ts` - 타입 정의 2. `lib/api/auth/auth-config.ts` - 인증 설정 3. `lib/api/client.ts` - 통합 HTTP 클라이언트 4. `lib/api/auth/sanctum-client.ts` - Sanctum 클라이언트 ### Phase 2: Middleware 통합 1. `middleware.ts` 확장 - 인증 체크 로직 추가 2. 라우트 보호 구현 (protected/guest-only) ### Phase 3: 로그인 페이지 1. `app/[locale]/(auth)/login/page.tsx` 2. 기존 validation schema 활용 ### Phase 4: 보호된 페이지 1. `app/[locale]/(protected)/dashboard/page.tsx` 2. Server Component로 구현 --- ## 🔒 보안 고려사항 ### 환경 변수 보안 ```yaml ✅ NEXT_PUBLIC_*: 브라우저 노출 가능 ❌ API_KEY: 절대 NEXT_PUBLIC_ 붙이지 말 것! ✅ .env.local은 .gitignore에 포함됨 ``` ### 인증 방식별 보안 ```yaml Sanctum: ✅ HTTP-only 쿠키 (XSS 방어) ✅ CSRF 토큰 자동 처리 ✅ Same-Site: Lax Bearer Token: ⚠️ localStorage 사용 (XSS 취약) ✅ 토큰 만료 시간 체크 ✅ Refresh token 권장 API Key: ⚠️ 서버 사이드 전용 ✅ 환경 변수 관리 ✅ 주기적 갱신 대비 ``` --- ## 📊 Middleware 인증 플로우 ``` Request ↓ 1. Bot Detection (기존) ├─ Bot → 403 Forbidden └─ Human → Continue ↓ 2. Static Files Check ├─ Static → Skip Auth └─ Dynamic → Continue ↓ 3. Public Routes Check ├─ Public → Skip Auth └─ Protected → Continue ↓ 4. Authentication Check ├─ Sanctum Session Cookie ├─ Bearer Token (Authorization header) └─ API Key (X-API-KEY header) ↓ 5. Protected Routes Guard ├─ Authenticated → Allow └─ Not Authenticated → Redirect /login ↓ 6. Guest Only Routes ├─ Authenticated → Redirect /dashboard └─ Not Authenticated → Allow ↓ 7. i18n Routing ↓ Response ``` --- ## 🚀 API 엔드포인트 ### 로그인 ``` POST /api/v1/login Content-Type: application/json Request: { "user_id": "hamss", "user_pwd": "StrongPass!1234" } Response (성공): { "user": { "id": 1, "name": "홍길동", "email": "hamss@example.com" }, "message": "로그인 성공" } Cookie: laravel_session=xxx; HttpOnly; SameSite=Lax ``` ### 로그아웃 ``` POST /api/v1/logout Response: { "message": "로그아웃 성공" } ``` ### 현재 사용자 정보 ``` GET /api/user Cookie: laravel_session=xxx Response: { "id": 1, "name": "홍길동", "email": "hamss@example.com" } ``` --- ## 📝 사용 예시 ### 1. Sanctum 로그인 (웹 사용자) ```typescript import { sanctumClient } from '@/lib/api/auth/sanctum-client'; const user = await sanctumClient.login({ user_id: 'hamss', user_pwd: 'StrongPass!1234' }); ``` ### 2. API Key 요청 (서버 사이드) ```typescript import { createApiKeyClient } from '@/lib/api/auth/api-key-client'; const client = createApiKeyClient(); const data = await client.fetchData('/api/external-data'); ``` ### 3. Bearer Token 로그인 (모바일) ```typescript import { bearerClient } from '@/lib/api/auth/bearer-client'; const user = await bearerClient.login({ email: 'user@example.com', password: 'password' }); ``` --- ## ⚠️ 주의사항 ### API Key 갱신 - PHP 팀에서 주기적으로 새 키 발급 - `.env.local`의 `API_KEY` 값만 변경 - 코드 수정 불필요, 서버 재시작만 필요 ### Git 보안 - `.env.local`은 절대 커밋 금지 - `.env.example`만 템플릿으로 커밋 - `.gitignore`에 `.env.local` 포함 확인 ### 개발 환경 - 개발 서버 시작 시 API Key 자동 검증 - 콘솔에 검증 상태 출력 - 에러 발생 시 명확한 가이드 제공 --- ## 🔍 트러블슈팅 ### API Key 에러 ``` ❌ API_KEY is not configured! 📝 Please check: 1. .env.local file exists 2. API_KEY is set correctly 3. Restart development server (npm run dev) 💡 Contact backend team if you need a new API key. ``` ### CORS 에러 - Laravel `config/cors.php` 확인 - `supports_credentials: true` 설정 - `allowed_origins`에 Next.js URL 포함 ### 세션 쿠키 안받아짐 - Laravel `SANCTUM_STATEFUL_DOMAINS` 확인 - `localhost:3000` 포함 확인 - `SESSION_DOMAIN` 설정 확인 --- ## 📚 참고 문서 - [Laravel Sanctum 공식 문서](https://laravel.com/docs/sanctum) - [Next.js Middleware 문서](https://nextjs.org/docs/app/building-your-application/routing/middleware) - [claudedocs/authentication-design.md](./authentication-design.md) - [claudedocs/api-requirements.md](./api-requirements.md)