- Authors
- Name
- 시리즈 소개 — 왜 이 시리즈를 쓰는가
- 인증 흐름 전체 지도
- 브라우저 저장소별 접근 가능성
- 쿠키 보안 속성 빠른 참조
- JWT 구조와 핵심 클레임
- CORS와 Credential 전송
- 시리즈 목차
- 보안 체크리스트 (시리즈 공통)
- 흔한 버그와 오해
- 참고자료
시리즈 소개 — 왜 이 시리즈를 쓰는가
웹 인증은 단순하지 않습니다. "로그인 기능 하나 만들면 되지"라고 생각하기 쉽지만, 실전에서는 다음과 같은 질문이 꼬리를 물고 나타납니다.
- 토큰을 쿠키에 넣을까, localStorage에 넣을까?
- JWT와 세션 중 무엇을 선택해야 할까?
- HttpOnly Cookie와 CSRF 토큰을 어떻게 조합할까?
- SSO(Single Sign-On) 환경에서 여러 서비스 간 인증 상태를 어떻게 공유할까?
- Access Token 갱신은 프론트엔드에서 하나, 백엔드에서 하나?
- CORS와 credentials 설정은 왜 항상 삽질을 유발할까?
이 질문들의 정답은 프레임워크마다 다릅니다. Spring Boot의 SecurityFilterChain과 Django의 SessionMiddleware는 기본 전략부터 다르고, React SPA와 Next.js SSR은 쿠키를 다루는 방식 자체가 다릅니다. 공식 문서만으로는 전체 그림을 그리기 어렵습니다.
이 시리즈는 인증 시스템의 전체 지도를 먼저 펼친 뒤, 프레임워크별로 실전 코드를 구현하는 구성입니다.
시리즈가 다루는 범위:
- SSO / OAuth 2.0 / OIDC 프로토콜의 동작 원리
- 쿠키 기반 인증과 JWT 기반 인증의 차이, 장단점, 하이브리드 전략
- 브라우저 저장소(Cookie, localStorage, sessionStorage, Memory)별 보안 특성
- CORS + Credential 전송의 정확한 설정법
- Spring Boot, Django, React, Next.js 각 프레임워크에서의 실전 구현
- 여러 프레임워크를 조합한 하이브리드 아키텍처 설계
인증 흐름 전체 지도
인증 시스템의 전체 흐름을 한눈에 파악하겠습니다. 아래는 SSO/OIDC 기반 로그인부터 토큰 갱신, 로그아웃까지의 전체 과정입니다.
로그인 흐름 (Login Flow)
┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────┐
│ Browser │ │ Frontend │ │ Backend │ │ IdP │
│ (사용자) │ │ (React/Next) │ │ (Spring/ │ │ (Keycloak│
│ │ │ │ │ Django) │ │ Okta) │
└────┬─────┘ └──────┬───────┘ └──────┬───────┘ └────┬─────┘
│ 1. 로그인 클릭 │ │ │
│─────────────────▶│ │ │
│ │ 2. /auth/login │ │
│ │───────────────────▶│ │
│ │ │ 3. Redirect URL │
│ │ │─────────────────▶│
│ 4. IdP 로그인 페이지 │ │
│◀──────────────────────────────────────────────────────────│
│ 5. 사용자 인증 (ID/PW, MFA) │ │
│──────────────────────────────────────────────────────────▶│
│ │ │ 6. Auth Code │
│ │ │◀─────────────────│
│ │ 7. Code → Token │ │
│ │◀───────────────────│ │
│ │ │ (id_token + │
│ │ │ access_token + │
│ │ │ refresh_token) │
│ 8. Set-Cookie: │ │ │
│ access_token │ │ │
│ (HttpOnly) │ │ │
│◀─────────────────│ │ │
│ 9. 인증 완료, │ │ │
│ 대시보드 이동 │ │ │
│◀─────────────────│ │ │
인증된 요청 흐름 (Authenticated Request Flow)
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ Browser │ │ Frontend │ │ Backend │
└────┬─────┘ └──────┬───────┘ └──────┬───────┘
│ API 요청 │ │
│─────────────────▶│ │
│ │ Cookie 자동 전송 │
│ │ (access_token) │
│ │───────────────────▶│
│ │ │ JWT 검증
│ │ │ (서명, 만료, 클레임)
│ │ 200 + 데이터 │
│ │◀───────────────────│
│ 렌더링 │ │
│◀─────────────────│ │
토큰 갱신 흐름 (Token Refresh Flow)
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ Browser │ │ Frontend │ │ Backend │
└────┬─────┘ └──────┬───────┘ └──────┬───────┘
│ API 요청 │ │
│─────────────────▶│ │
│ │ Cookie 전송 │
│ │───────────────────▶│
│ │ 401 Unauthorized │
│ │◀───────────────────│
│ │ │
│ │ POST /auth/refresh│
│ │ (refresh_token │
│ │ Cookie 전송) │
│ │───────────────────▶│
│ │ 새 access_token │
│ │ Set-Cookie │
│ │◀───────────────────│
│ │ │
│ │ 원래 요청 재시도 │
│ │───────────────────▶│
│ │ 200 + 데이터 │
│ │◀───────────────────│
│ 렌더링 │ │
│◀─────────────────│ │
로그아웃 흐름 (Logout Flow)
┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────┐
│ Browser │ │ Frontend │ │ Backend │ │ IdP │
└────┬─────┘ └──────┬───────┘ └──────┬───────┘ └────┬─────┘
│ 로그아웃 클릭 │ │ │
│─────────────────▶│ │ │
│ │ POST /auth/logout │ │
│ │───────────────────▶│ │
│ │ │ Revoke Token │
│ │ │─────────────────▶│
│ │ Set-Cookie: │ │
│ │ access_token="" │ │
│ │ Max-Age=0 │ │
│ │◀───────────────────│ │
│ 쿠키 삭제, │ │ │
│ 로그인 페이지 │ │ │
│◀─────────────────│ │ │
핵심 포인트: 백엔드가 HttpOnly Cookie로 토큰을 관리하면 프론트엔드 JavaScript는 토큰에 직접 접근할 수 없습니다. 이것이 XSS 공격을 방어하는 가장 효과적인 전략입니다.
브라우저 저장소별 접근 가능성
토큰을 어디에 저장할지는 보안과 편의성의 트레이드오프입니다. 각 저장소의 특성을 정확히 이해해야 올바른 선택을 할 수 있습니다.
| 저장소 | JS 접근 | 서버 자동 전송 | XSS 취약 | CSRF 취약 |
|---|---|---|---|---|
| HttpOnly Cookie | ❌ | ✅ | ❌ | ✅ |
| Non-HttpOnly Cookie | ✅ | ✅ | ✅ | ✅ |
| localStorage | ✅ | ❌ | ✅ | ❌ |
| sessionStorage | ✅ | ❌ | ✅ | ❌ |
| Memory (JS 변수) | ✅ | ❌ | △ | ❌ |
각 저장소 심층 분석:
- HttpOnly Cookie: JavaScript에서 접근 불가능하므로 XSS에 안전합니다. 단, 브라우저가 모든 요청에 자동으로 쿠키를 첨부하므로 CSRF 공격에 취약합니다. SameSite 속성과 CSRF 토큰을 반드시 병행해야 합니다.
- Non-HttpOnly Cookie:
document.cookie로 접근 가능하므로 XSS와 CSRF 모두에 취약합니다. 가능하면 사용하지 마세요. - localStorage: 탭을 닫아도 데이터가 유지됩니다. 서버에 자동 전송되지 않아 CSRF에는 안전하지만, XSS 공격으로 토큰이 탈취될 수 있습니다.
- sessionStorage: 탭 단위로 격리되고 탭을 닫으면 삭제됩니다. 보안 특성은 localStorage와 동일합니다.
- Memory (JS 변수): 페이지 새로고침 시 소멸합니다. XSS에 완전히 안전하지는 않지만(실행 중인 스크립트가 접근 가능), 공격 난이도가 높습니다. Silent Refresh와 조합하면 좋은 전략입니다.
실전 권장: Access Token은 HttpOnly Cookie, CSRF 방어는 SameSite=Lax + CSRF Token 이중 적용. Refresh Token도 HttpOnly Cookie에 저장하되 Path를
/auth/refresh로 제한하세요.
쿠키 보안 속성 빠른 참조
쿠키는 단순한 key=value가 아닙니다. 보안 속성 하나를 빠뜨리면 인증 시스템 전체가 무너질 수 있습니다.
속성별 상세 설명
| 속성 | 값 | 설명 |
|---|---|---|
HttpOnly | true | JavaScript에서 접근 차단. XSS 방어의 핵심 |
Secure | true | HTTPS 연결에서만 쿠키 전송 |
SameSite | Strict | 모든 크로스사이트 요청에서 쿠키 미전송. 가장 안전하지만 외부 링크 클릭 시 로그인 풀림 |
SameSite | Lax | GET 네비게이션은 허용, POST 등은 차단. 대부분의 경우 권장 |
SameSite | None | 크로스사이트 요청에서도 쿠키 전송. 반드시 Secure와 함께 사용. SSO에서 필수 |
Domain | .example.com | 서브도메인 간 쿠키 공유. SSO에서 중요 |
Path | /auth | 해당 경로 하위에서만 쿠키 전송 |
Max-Age | 3600 | 초 단위 만료 시간. 0이면 즉시 삭제 |
Expires | 날짜 문자열 | 절대 만료 시각. Max-Age가 우선 |
실전 설정 예시
Set-Cookie: access_token=eyJhbGciOi...;
HttpOnly;
Secure;
SameSite=Lax;
Path=/;
Max-Age=900;
Domain=.myservice.com
Set-Cookie: refresh_token=dGhpcyBpcyBh...;
HttpOnly;
Secure;
SameSite=Strict;
Path=/api/auth/refresh;
Max-Age=604800;
Domain=.myservice.com
Set-Cookie: csrf_token=abc123def456;
Secure;
SameSite=Lax;
Path=/;
Max-Age=900;
Domain=.myservice.com
주의:
csrf_token은 HttpOnly가 아닙니다. 프론트엔드가 이 값을 읽어서 요청 헤더(X-CSRF-Token)에 포함해야 하므로 JavaScript 접근이 필요합니다.
SameSite 전략 결정 트리:
SSO(크로스 도메인) 필요?
├── Yes → SameSite=None; Secure (+ CSRF Token 필수)
└── No
├── 외부 링크에서 유입 시 로그인 유지 필요?
│ ├── Yes → SameSite=Lax
│ └── No → SameSite=Strict
└── API 전용 쿠키?
└── SameSite=Strict (가장 안전)
JWT 구조와 핵심 클레임
JWT(JSON Web Token)는 .으로 구분된 세 부분으로 구성됩니다.
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9. ← Header (Base64URL)
eyJzdWIiOiJ1c2VyMTIzIiwicm9sZXMiOlsiQU... ← Payload (Base64URL)
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQ... ← Signature
Header
{
"alg": "RS256", // 서명 알고리즘 (RS256, HS256, ES256 등)
"typ": "JWT", // 토큰 타입
"kid": "key-id-001" // Key ID (JWK Set에서 공개키 식별용)
}
Payload (Claims)
{
"sub": "user123", // Subject — 사용자 고유 식별자
"iss": "https://idp.myservice.com", // Issuer — 토큰 발급자
"aud": "https://api.myservice.com", // Audience — 토큰 수신 대상
"exp": 1741420800, // Expiration — 만료 시각 (Unix timestamp)
"iat": 1741417200, // Issued At — 발급 시각
"nbf": 1741417200, // Not Before — 이 시각 이전에는 무효
"jti": "unique-token-id-789", // JWT ID — 토큰 고유 ID (재사용 방지)
"roles": ["ADMIN", "USER"], // Custom — 사용자 권한
"tenant_id": "tenant-abc", // Custom — 멀티테넌트 식별
"email": "user@example.com" // Custom — 사용자 이메일
}
Signature 검증
RSASHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
publicKey
)
JWT 파싱 예시 (의사 코드)
import base64, json
def parse_jwt(token):
header_b64, payload_b64, signature = token.split(".")
# Base64URL 디코딩 (패딩 보정)
header = json.loads(
base64.urlsafe_b64decode(header_b64 + "==")
)
payload = json.loads(
base64.urlsafe_b64decode(payload_b64 + "==")
)
# 만료 검증
import time
if payload["exp"] < time.time():
raise Exception("토큰이 만료되었습니다")
# 발급자 검증
if payload["iss"] != "https://idp.myservice.com":
raise Exception("신뢰할 수 없는 발급자입니다")
return header, payload
주의: 실제 운영 환경에서는 반드시 서명을 검증해야 합니다. 위 코드는 구조 이해를 위한 예시이며,
PyJWT,jose,jsonwebtoken등 검증된 라이브러리를 사용하세요.
JWT vs 세션(Session) 비교:
| 항목 | JWT (Stateless) | 세션 (Stateful) |
|---|---|---|
| 서버 저장소 | 불필요 | 필요 (Redis, DB) |
| 수평 확장 | 용이 | 세션 스토어 공유 필요 |
| 즉시 무효화 | 어려움 (Blocklist 필요) | 쉬움 (세션 삭제) |
| 토큰 크기 | 큼 (클레임 포함) | 작음 (세션 ID만) |
| 적합 시나리오 | MSA, API Gateway | 모놀리식, 단일 서버 |
CORS와 Credential 전송
쿠키 기반 인증에서 가장 많은 개발자가 삽질하는 구간이 CORS(Cross-Origin Resource Sharing) 설정입니다. 프론트엔드와 백엔드의 도메인이 다를 때 쿠키 전송이 차단되는 문제는 거의 모든 프로젝트에서 한 번쯤 겪습니다.
올바른 설정
프론트엔드 (fetch API):
// credentials: 'include'가 핵심
const response = await fetch('https://api.myservice.com/users/me', {
method: 'GET',
credentials: 'include', // 쿠키를 포함하여 전송
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': getCsrfToken(), // CSRF 토큰 헤더
},
})
프론트엔드 (Axios):
const api = axios.create({
baseURL: 'https://api.myservice.com',
withCredentials: true, // 쿠키를 포함하여 전송
})
// 인터셉터로 CSRF 토큰 자동 첨부
api.interceptors.request.use((config) => {
const csrfToken = getCookieValue('csrf_token')
if (csrfToken) {
config.headers['X-CSRF-Token'] = csrfToken
}
return config
})
백엔드 응답 헤더:
Access-Control-Allow-Origin: https://app.myservice.com ← 정확한 Origin
Access-Control-Allow-Credentials: true ← 필수
Access-Control-Allow-Headers: Content-Type, X-CSRF-Token ← 커스텀 헤더 허용
Access-Control-Allow-Methods: GET, POST, PUT, DELETE ← 허용 메서드
Access-Control-Expose-Headers: X-Request-Id ← 프론트에서 읽을 헤더
흔한 실수와 해결법
실수 1: Access-Control-Allow-Origin: * 와 credentials 동시 사용
# 이렇게 하면 브라우저가 차단합니다
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
# → 에러: credentials 모드에서는 와일드카드 Origin 불가
해결: Origin을 정확하게 지정하세요. 여러 Origin을 지원해야 한다면 요청의 Origin 헤더를 확인하고 화이트리스트에 있는 경우 동적으로 설정합니다.
# Django 예시
ALLOWED_ORIGINS = [
'https://app.myservice.com',
'https://admin.myservice.com',
]
# django-cors-headers 설정
CORS_ALLOWED_ORIGINS = ALLOWED_ORIGINS
CORS_ALLOW_CREDENTIALS = True
실수 2: Preflight 요청(OPTIONS)에서 쿠키 전송 기대
# Preflight(OPTIONS) 요청에는 쿠키가 포함되지 않습니다!
# OPTIONS 응답에서 인증을 요구하면 안 됩니다.
# → Backend의 인증 필터에서 OPTIONS 메서드를 제외하세요.
실수 3: SameSite=Strict 쿠키가 크로스오리진 요청에서 전송되지 않음
# 프론트: https://app.myservice.com
# 백엔드: https://api.myservice.com
# → 서로 다른 Origin이므로 SameSite=Strict 쿠키는 전송되지 않습니다
# → SameSite=None; Secure 또는 같은 상위 도메인 사용
실수 4: 로컬 개발 환경에서 localhost vs 127.0.0.1
# localhost:3000 → localhost:8080 : 같은 사이트 (쿠키 전송됨)
# localhost:3000 → 127.0.0.1:8080 : 다른 사이트! (쿠키 전송 안됨)
# → 개발 환경에서도 동일한 호스트명을 사용하세요
시리즈 목차
이 시리즈는 총 5편으로 구성되어 있습니다. 이 인덱스 페이지에서 공통 개념을 익힌 후, 각 프레임워크별 실전 구현으로 이동하세요.
| 편 | 제목 | 핵심 내용 |
|---|---|---|
| 0편 | 현재 글 (인덱스) | 인증 흐름 전체 지도, 공통 개념 정리 |
| 1편 | Spring Boot | SecurityFilterChain, JWT 필터, CORS 설정, CSRF 방어 |
| 2편 | Django | DRF + SimpleJWT, SessionMiddleware, django-cors-headers |
| 3편 | React | Axios 인터셉터, Silent Refresh, Protected Route |
| 4편 | Next.js | Middleware, Server Actions, SSR 쿠키 전달, next-auth |
| 5편 | 통합 실전편 — SSO/OIDC + 하이브리드 아키텍처 | Keycloak/Okta 연동, BFF 패턴, 멀티 서비스 SSO |
읽는 순서 권장:
- 이 인덱스 글에서 전체 흐름을 파악합니다.
- 자신이 사용하는 백엔드 프레임워크 편(1편 또는 2편)을 읽습니다.
- 프론트엔드 편(3편 또는 4편)을 읽습니다.
- 5편에서 전체를 통합하는 아키텍처를 학습합니다.
보안 체크리스트 (시리즈 공통)
프레임워크에 관계없이 모든 인증 시스템에 적용해야 하는 보안 항목입니다. 배포 전 반드시 확인하세요.
쿠키 설정
- Access Token 쿠키에
HttpOnly속성이 설정되어 있는가? - 모든 인증 쿠키에
Secure속성이 설정되어 있는가? -
SameSite속성이 서비스 아키텍처에 맞게 설정되어 있는가? - Refresh Token 쿠키의
Path가 갱신 엔드포인트로 제한되어 있는가? - 쿠키의
Max-Age가 적절한 시간으로 설정되어 있는가? - 쿠키의
Domain이 필요한 범위로만 제한되어 있는가?
토큰 관리
- Access Token의 만료 시간이 충분히 짧은가? (권장: 5~15분)
- Refresh Token의 만료 시간이 설정되어 있는가? (권장: 7~30일)
- Refresh Token Rotation이 구현되어 있는가?
- 탈취된 Refresh Token을 무효화할 수 있는 메커니즘이 있는가?
- JWT 서명에 RS256 또는 ES256 비대칭 알고리즘을 사용하고 있는가?
- JWT의
iss,aud,exp클레임을 모두 검증하고 있는가?
CSRF 방어
- 상태 변경 요청(POST, PUT, DELETE)에 CSRF 토큰을 검증하고 있는가?
- CSRF 토큰이 요청마다 또는 세션마다 갱신되는가?
-
SameSite쿠키 속성과 CSRF 토큰을 이중으로 적용했는가?
CORS 설정
-
Access-Control-Allow-Origin에 와일드카드(*)를 사용하지 않는가? -
Access-Control-Allow-Credentials: true가 설정되어 있는가? - 허용할 Origin 목록이 화이트리스트로 관리되고 있는가?
- Preflight 요청(OPTIONS)이 인증 없이 통과하도록 설정되어 있는가?
전송 보안
- 모든 통신이 HTTPS를 통해 이루어지는가?
- HSTS(HTTP Strict Transport Security) 헤더가 설정되어 있는가?
- TLS 1.2 이상을 사용하고 있는가?
로그아웃
- 로그아웃 시 서버 측 세션/토큰이 무효화되는가?
- 로그아웃 시 모든 인증 쿠키가 삭제되는가?
- SSO 환경에서 Single Logout(SLO)이 구현되어 있는가?
흔한 버그와 오해
오해 1: "JWT는 암호화되어 있다"
JWT는 서명(Signed)되어 있을 뿐 암호화(Encrypted)되어 있지 않습니다. Base64URL 인코딩은 암호화가 아닙니다. 누구나 Payload를 디코딩하여 내용을 읽을 수 있습니다.
# JWT Payload 디코딩 (누구나 가능)
echo "eyJzdWIiOiJ1c2VyMTIzIn0" | base64 -d
# 출력: {"sub":"user123"}
민감한 정보(비밀번호, 주민번호 등)를 JWT Payload에 절대 넣지 마세요. 정말 암호화가 필요하다면 JWE(JSON Web Encryption)를 사용하세요.
오해 2: "localStorage에 JWT를 저장해도 괜찮다"
SPA 프레임워크의 많은 튜토리얼이 localStorage에 JWT를 저장하는 예제를 보여줍니다. 이는 XSS 공격에 취약합니다. 서드파티 라이브러리 하나의 취약점만으로 토큰이 탈취될 수 있습니다.
// 위험한 패턴
localStorage.setItem('token', jwt)
// 안전한 패턴: HttpOnly Cookie 사용 (서버에서 설정)
// 프론트엔드는 토큰을 직접 다루지 않음
오해 3: "SameSite=Lax이면 CSRF 공격이 완전히 방어된다"
SameSite=Lax는 대부분의 CSRF를 방어하지만 완전하지 않습니다. 크로스사이트 GET 요청에는 쿠키가 전송됩니다. 만약 GET 요청으로 상태를 변경하는 API가 있다면 여전히 취약합니다.
# GET /api/users/delete?id=123 ← 이런 API는 SameSite=Lax로도 방어 불가!
# → 상태 변경은 반드시 POST/PUT/DELETE로 설계하세요
오해 4: "Refresh Token은 Access Token보다 안전하다"
Refresh Token은 장기간 유효하므로 탈취되면 Access Token보다 더 위험합니다. Refresh Token이 탈취되면 공격자가 무한정 새로운 Access Token을 발급받을 수 있습니다.
방어 전략:
- Refresh Token Rotation: 갱신 시 이전 토큰 즉시 무효화
- Token Family 추적: 이미 사용된 Refresh Token이 다시 사용되면 해당 Family 전체 무효화
- Refresh Token을 HttpOnly Cookie에 저장하고 Path 제한
오해 5: "CORS가 서버를 보호해준다"
CORS는 브라우저의 정책입니다. curl, Postman, 서버 간 통신에서는 CORS가 적용되지 않습니다. CORS는 악성 웹사이트가 사용자의 브라우저를 이용해 API를 호출하는 것을 방지할 뿐, API 자체를 보호하지 않습니다.
# CORS와 무관하게 동작
curl -X POST https://api.myservice.com/data \
-H "Cookie: access_token=stolen_token"
# → 서버 측 토큰 검증이 반드시 필요합니다
흔한 버그: 토큰 갱신 레이스 컨디션
여러 API 요청이 동시에 401을 받으면 Refresh 요청도 여러 번 발생합니다. Refresh Token Rotation을 사용하는 경우 첫 번째 요청만 성공하고 나머지는 실패합니다.
// 해결: 갱신 요청을 하나로 모으는 패턴
let refreshPromise = null
async function refreshToken() {
if (refreshPromise) return refreshPromise // 이미 갱신 중이면 대기
refreshPromise = axios.post('/auth/refresh').finally(() => {
refreshPromise = null
})
return refreshPromise
}
참고자료
이 시리즈를 작성하면서 참고한 공식 문서와 표준 명세입니다. 인증 시스템을 설계할 때 반드시 원문을 확인하세요.
표준 명세 (RFC)
- RFC 7519 — JSON Web Token (JWT) — JWT 표준 명세. 클레임, 서명, 검증 절차 정의
- RFC 6749 — OAuth 2.0 Authorization Framework — OAuth 2.0 핵심 프레임워크. Grant Type별 흐름 정의
- RFC 6750 — OAuth 2.0 Bearer Token Usage — Bearer Token 전송 방법 (Authorization 헤더, 쿼리 파라미터 등)
- RFC 7517 — JSON Web Key (JWK) — 공개키 배포를 위한 JWK Set 표준
- RFC 6265 — HTTP State Management Mechanism (Cookie) — HTTP 쿠키 표준 명세
OpenID Connect
- OpenID Connect Core 1.0 — OAuth 2.0 위에 인증(Authentication) 레이어를 추가한 표준
보안 가이드라인
- OWASP — Session Management Cheat Sheet — 세션 관리 보안 모범 사례
- OWASP — JSON Web Token Cheat Sheet — JWT 사용 시 보안 체크리스트
- OWASP — Cross-Site Request Forgery Prevention — CSRF 방어 전략
프레임워크 공식 문서
- MDN — HTTP Cookies — 쿠키 속성(SameSite, HttpOnly, Secure 등) 상세 설명
- Spring Security — OAuth 2.0 Resource Server — Spring Boot JWT 인증 공식 가이드
- Django REST Framework — Authentication — DRF 인증 메커니즘 공식 문서
- Next.js — Authentication — Next.js App Router 기반 인증 구현 가이드
- MDN — CORS — Cross-Origin Resource Sharing 완전 가이드