Files
sam-react-prod/claudedocs/[IMPL-2025-11-07] authentication-implementation-guide.md
byeongcheolryu 2307b1f2c0 [docs]: 프로젝트 문서 추가
세부 항목:
- 인증 및 미들웨어 구현 가이드
- 품목 관리 마이그레이션 가이드
- API 분석 및 요구사항 문서
- 대시보드 통합 완료 문서
- 브라우저 호환성 및 쿠키 처리 가이드
- Next.js 15 마이그레이션 참고 문서

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 21:17:43 +09:00

6.9 KiB
Raw Blame History

인증 시스템 구현 가이드

📋 개요

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 (실제 키 값)

# 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 (템플릿)

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로 구현

🔒 보안 고려사항

환경 변수 보안

✅ NEXT_PUBLIC_*: 브라우저 노출 가능
❌ API_KEY: 절대 NEXT_PUBLIC_ 붙이지 말 것!
✅ .env.local은 .gitignore에 포함됨

인증 방식별 보안

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 로그인 (웹 사용자)

import { sanctumClient } from '@/lib/api/auth/sanctum-client';

const user = await sanctumClient.login({
  user_id: 'hamss',
  user_pwd: 'StrongPass!1234'
});

2. API Key 요청 (서버 사이드)

import { createApiKeyClient } from '@/lib/api/auth/api-key-client';

const client = createApiKeyClient();
const data = await client.fetchData('/api/external-data');

3. Bearer Token 로그인 (모바일)

import { bearerClient } from '@/lib/api/auth/bearer-client';

const user = await bearerClient.login({
  email: 'user@example.com',
  password: 'password'
});

⚠️ 주의사항

API Key 갱신

  • PHP 팀에서 주기적으로 새 키 발급
  • .env.localAPI_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 설정 확인

📚 참고 문서