세션 인증 방식

  1. 로그인 요청 (ID/PassWord 전송)
  2. 사용자 확인 후 세션 생성 및 메모리/DB에 저장
  3. 생성된 Session ID(SESSIONID)를 쿠키(Set-Cookie)에 담아 응답
  4. 인증이 필요한 API 요청 시, 쿠키의 Session ID를 자동 포함하여 전송
  5. 전달받은 Session ID가 저장소에 있는지 조회 및 검증 후 데이터 응답

단점

서버 메모리를 사용하다보니 서버 확장(Scale-Out)이 어려움

프론트엔드와 API 서버 도메인이 다르면 쿠키 전송 자체에 별도 설정이 필요(CORS 정책 이슈)

토큰 인증 방식

  1. 로그인 요청(ID/Password 전송)
  2. Store에서 사용자 정보 조회 및 인증
  3. 사용자 확인 후, 비밀키를 사용하여 서명된 JWT 생성 (저장소에 토큰/세션 저장 안 함)
  4. 생성된 JWT를 응답(클라이언트가 로컬에 저장)
  5. API 요청 시 HTTP 헤더(Authorization: Bearer <token>)에 JWT를 포함하여 전송
  6. 서버의 비밀키로 토큰의 서명(Signature)을 검증하고 유효성(만료일 등) 확인 후 데이터 응답

세션 vs 토큰 인증

세션 인증토큰 인증
상태 저장서버(메모리/DB)에 세션을 보관서버에 저장하지 않음
전달쿠키(Set-Cookie)로 자동 전송Authorization 헤더(Bearer)에 직접 실어 전송
검증매 요청마다 저장소를 조회해야 함서명만 확인, 저장소 조회 없음
확장(Scale-out)세션 공유 설정이 필요해 까다로움어느 서버로 가도 확장이 자유로움

JWT(JSON Web Token)

JWT는 사용자의 인증/인가 정보를 JSON 형태로 안전하게 전송하기 위한 웹 표준(RFC7519)

디지털 서명이 되어 있으므로 신뢰할 수 있음 (암호화 알고리즘 사용)

JSON 기반이므로 대부분의 언어, 플랫폼에서 독립적으로 사용 가능

JWT 자체가 필요한 모든 정보를 갖고 있기 때문에 검증하기 위해 다른 검증 수단이 필요하지 않음

권한을 부여하거나, 정보를 교환할 때 등의 상황에서 사용 가능

서버는 토큰을 저장하지 않음

JWT 구조

JWT는 .(dot)을 이용하여 3가지의 영역으로 구성된다.

  1. header(헤더) - 토큰의 메타정보
  2. payload(내용) - 실제 담고자 하는 정보 (Claim, 정보의 key-value쌍)
  3. signature(서명) - 위변조 탐지용 서명

헤더는 일반적으로 두 부분으로 구성

  • 토큰의 유형 -> “JWT” (보통 “JWT”로 고정)
  • 암호화 알고리즘 (HMAC SHA256 or RSA 등)

해당 정보를 Base64URL 방식으로 인코딩하여 헤더 부분을 완성함

Payload

Claim(토큰의 정보)들의 집합

Registered claims(표준 클레임)

  • JWT 스펙에서 미리 정해 놓은 클레임
  • iss(Issuer)
  • sub(Subject - 토큰의 주체, 사용자 ID 등)
  • lat(발급시각), exp(만료시각) 등

Public claims(공용 클레임)

  • 자유롭게 정의하여 넣는 클레임(충돌 방지 필요)

Private claims

  • 발급자와 사용자 간에 약속한 값

해당 정보를 Base64URL 방식으로 인코딩하여 페이로드 부분을 완성함

Signature

헤더 + 페이로드를 비밀키로 서명(암호화)한 결과

해당 토큰이 조작되었거나 변경되지 않음을 확인하는 용도로 사용

JWT 동작 흐름(로그인)

  1. 로그인 요청
  2. 서버에서 ID/PW 검증
  3. 서버가 JWT 발급(Access Token)
  4. 클라이언트가 발급 받은 토큰 저장 (localStorage 등)
  5. Axios 요청 시 JWT를 헤더에 넣어 요청
  6. 서버에서 JWT 검증 -> 이상 없으면 요청 수행

JWT 장점 & 단점

장점

  • 서버가 상태를 저장할 필요 없음(세션 관리 부담 감소)
  • DB 호출을 하지 않고 서명이 유효한지 검증만 하기 때문에 속도가 빠르다
  • SPA에서 주로 사용
  • 다양한 서비스 간 공유가 쉽다

단점

  • 토큰이 유효기간 내에는 무효화가 불가능하다(탈취되면 위험)
  • 토큰이 길다
  • XSS에 노출되어 JS 공격을 받을 수 있다
  • JWT를 디코딩하면 내용이 보이기 때문에 민감한 개인정보를 작성하면 안된다.

따라서 Access Token + Refresh Token 방식을 많이 사용한다.

Access Token

로그인 성공하면 발급 받ㅇ서 클라이언트에 저장

누구인지, 권한은 어떻게 되는지, 언제까지 유효한지 등의 정보가 포함되어 있다.

탈취 시 피해를 줄이기 위해서 유효 기간을 짧게(보통 5분~1시간 내외) 설정한다.

LocalStorage(혹은 메모리에 임시 저장)에 주로 저장한다.

  • 설계의 유연함(CORS)과 CSRF 공격을 방어하기 위해 자바스크립트 코드로 명시적 전송
  • 쿠키로 설정하게 되면 자동 전송 성질에 따라서 URL(+Path)만 맞으면 전송해버리므로 위험

Refresh Token

Access Token이 만료되었을 때, 새 Access Token을 발급

유효 기간은 길게(보통 7일~30일)로 설정한다.

HttpOnly Cookie에 주로 저장한다.(JS 접근 불가능) (갱신 시에만 사용하도록 Path를 한정 권장한다. Path=/api/auth/refresh)

서버(DB/Redis)에 저장해서 관리하는 경우가 많다.