C
네트워크/인증/Lesson 06

인증 — 쿠키·세션·JWT·OAuth

45분·theory

인증 — 쿠키·세션·JWT·OAuth

🎯 이 lesson 을 읽고 나면

이 lesson 을 다 읽고 나면 아래 3가지를 자신 있게 할 수 있습니다.

  • ✅ Cookie · Session · JWT 의 차이
  • ✅ OAuth 2.0 Authorization Code Flow + PKCE
  • ✅ Access Token vs Refresh Token 운영

학습 목표를 체크리스트로 두고 다 답할 수 있게 되면 lesson 을 닫으세요.

쿠키 + 세션

쿠키 = 브라우저에 작은 데이터. 서버가 Set-Cookie 헤더로 발급.

쿠키 속성:

code
Set-Cookie: session=abc123;
  HttpOnly;          # JS 에서 접근 X (XSS 방어)
  Secure;            # HTTPS 에서만 전송
  SameSite=Lax;      # CSRF 방어 (외부 사이트에서 차단)
  Max-Age=86400;     # 1일
  Path=/;
  Domain=.example.com;

SameSite 옵션:

  • Strict — 외부 사이트에서 모두 차단 (가장 안전, UX 영향)
  • Lax — GET 등 안전 메서드만 허용 (기본 권장)
  • None — 모두 허용 (Secure 필수)

세션 인증 (서버 사이드 저장):

code
1. POST /login (이메일+비번)
2. 서버: 검증 → sessionId 생성 → Redis 에 저장
   { "sess:abc123": { userId: 42, exp: ... } }
3. 응답: Set-Cookie: session=abc123 (HttpOnly)
4. 이후 요청: 브라우저가 자동 첨부
5. 서버: sessionId → Redis 조회 → user
6. 로그아웃: Redis 삭제 → 즉시 무효

장점:

  • 즉시 무효화 가능
  • 작은 쿠키 (sessionId 만)
  • HttpOnly 로 XSS 안전

단점:

  • 서버 저장소 필요 (Redis 추천)
  • 멀티 서버 시 sticky session 또는 공유 저장소
  • 모바일·SPA 다루기 까다로움

JWT — 자체 검증 토큰

JWT (JSON Web Token)Stateless 인증:

구조 (3 파트, . 구분):

code
xxxx.yyyy.zzzz
└┬─┘ └┬─┘ └┬─┘
Header  │   Signature
     Payload

Base64 디코드 시:

json
// Header
{ "alg": "HS256", "typ": "JWT" }

// Payload (claims)
{
  "sub": "42",                  // subject (user id)
  "exp": 1735689600,            // 만료
  "iat": 1735603200,            // 발급 시각
  "role": "admin"               // 커스텀
}

// Signature = HMAC-SHA256(header.payload, secret)

서버 검증:
1. 토큰 분해 → header.payload.sig
2. HMAC-SHA256(header.payload, secret) 다시 계산
3. 받은 sig 와 일치? → 조작 안 됨
4. exp 미만? → 유효
5. payload 의 user 정보 신뢰

장점:

  • 서버 저장소 X (stateless)
  • 멀티 서버·MSA 친화
  • 모바일·SPA 깔끔 (Authorization 헤더)

단점:

  • 무효화 어려움 — exp 까지 유효 (블랙리스트 Redis 필요)
  • 토큰 크기 (~200-500 byte)
  • 비밀키 노출 시 전체 위협
  • LocalStorage 저장 = XSS 위험 → httpOnly 쿠키 권장

액세스 + 리프레시 패턴 (가장 흔함):

  • Access Token: 15분, 자주 사용
  • Refresh Token: 7일, 갱신 전용 (httpOnly + Secure)
  • Access 만료 시 → Refresh 로 새 Access 발급
  • Refresh 도 만료 → 재로그인

OAuth 2.0 + OIDC

OAuth 2.0 = 다른 사이트의 인증 위임. "구글로 로그인" 의 표준.

Authorization Code Flow (가장 안전, 서버 앱):

code
1. 사용자: "Google로 로그인" 클릭
2. 우리 앱 → Google: 로그인 페이지 redirect
   https://accounts.google.com/o/oauth2/auth?
     client_id=xxx&redirect_uri=https://us/cb&response_type=code&scope=email

3. 사용자 Google 로그인 + 동의
4. Google → 우리 콜백: code=ABC

5. 우리 서버 → Google: code 교환 (server-to-server)
   POST /oauth/token
   { code: 'ABC', client_id, client_secret }

6. Google → 우리 서버: access_token + refresh_token

7. 우리 서버: token 으로 Google API 호출
   GET /userinfo (이름·이메일)

8. 우리 DB 에 사용자 매핑·로그인

PKCE (Proof Key for Code Exchange):

  • 모바일·SPA 처럼 client_secret 못 숨길 때
  • 클라이언트가 code_verifier 생성
  • 1단계: code_challenge = SHA256(code_verifier) 전달
  • 5단계: code_verifier 전달 → Google 이 검증
  • 2025 표준 — 서버 앱도 권장

OAuth Scopes — 권한 범위:

  • email — 이메일 주소
  • profile — 이름·사진
  • read:repos — GitHub 저장소 읽기
  • 최소 권한 원칙 (필요한 것만 요청)

OIDC (OpenID Connect) = OAuth 2.0 + 인증 표준:

  • OAuth = 인가 (authorization)
  • OIDC = OAuth + 인증 (authentication)
  • id_token (JWT) 추가 — 사용자 신원 정보 포함
  • Google·Naver·Kakao·Apple Sign-In 모두 OIDC

대표 라이브러리:

  • NextAuth.js (Next.js)
  • Spring Security OAuth2 Client
  • Passport.js (Express)
  • Auth0·Clerk·Supabase Auth (관리형)

🤖 AI 에게 이렇게 요청해보세요

이 lesson 의 개념을 알면 AI 에게 구체적으로 지시할 수 있습니다. 막연한 "고쳐줘" 가 아니라 어휘를 가진 요청 — 그게 토큰 절약의 출발점입니다.

  • "이 세션 인증을 JWT 로 마이그레이션해줘"
  • "이 OAuth2 흐름에 PKCE 추가해줘"

왜 이게 토큰을 줄이나

개념을 모를 땐 AI 답변을 받고도 "그게 뭐예요?" 를 다시 물어야 합니다. 그 "다시 물음" 이 토큰을 잡아먹습니다. 개념 한 번 익혀두면 대화가 한 번에 끝납니다.

인증 — 쿠키·세션·JWT·OAuth - 네트워크