세션 vs 토큰 vs 쿠키? 그리고 JWT

안현희·2일 전
0

React를 배워보자!

목록 보기
20/20

1. 세션(Session)

개념

  • 세션은 사용자가 웹 애플리케이션에 접속한 상태를 서버 측에서 유지하는 기술입니다.
  • 사용자가 로그인하거나 특정 작업을 수행하면 서버는 사용자를 식별하기 위해 세션 ID를 생성합니다.
  • 세션 ID는 클라이언트(브라우저)에 쿠키로 저장되거나 URL 매개변수로 전달됩니다.

작동 원리

  1. 클라이언트가 서버에 요청을 보냄.
  2. 서버가 세션 ID를 생성하고 서버의 메모리(또는 데이터베이스)에 세션 데이터를 저장.
  3. 세션 ID는 쿠키를 통해 클라이언트로 전달됨.
  4. 이후 클라이언트는 요청 시마다 세션 ID를 서버로 전송하여 자신의 상태를 확인.

특징

  • 상태 유지: 서버가 세션 데이터를 관리하므로 클라이언트의 상태를 기억할 수 있음.
  • 보안: 서버 측에서 데이터가 관리되므로 클라이언트의 변조 위험이 적음.
  • 유지 시간: 세션은 유효기간(예: 30분)이나 사용자의 로그아웃 등으로 만료됨.

2. 쿠키(Cookie)

개념

  • 쿠키는 클라이언트(웹 브라우저)에 저장되는 작은 데이터 조각으로, 서버가 클라이언트를 식별하거나 설정 데이터를 유지하기 위해 사용됩니다.
  • 주로 키-값 쌍으로 저장되며, 브라우저가 자동으로 서버로 쿠키를 전송합니다.

작동 원리

  1. 서버가 클라이언트에 응답할 때 쿠키를 설정(Set-Cookie 헤더 사용).
  2. 클라이언트는 브라우저에 쿠키를 저장.
  3. 이후 클라이언트가 같은 서버에 요청할 때 쿠키를 함께 전송.

특징

  • 저장 위치: 클라이언트(브라우저)에 저장됨.
  • 자동 전송: 쿠키는 요청 시마다 서버로 자동 전송되어 인증에 사용.
  • 보안 이슈: 민감 정보를 평문으로 저장할 경우 중간자 공격(Man-in-the-Middle)이나 XSS 공격에 취약.

종류

  1. 세션 쿠키: 브라우저가 닫히면 삭제됨.
  2. 영구 쿠키: 만료 시간 설정 가능, 브라우저를 닫아도 유지됨.

3. 토큰(Token)

개념

  • 토큰은 인증 및 권한 부여를 위한 작은 데이터 조각으로, 클라이언트와 서버 간에 안전하게 정보를 교환하는 데 사용됩니다.
  • 토큰은 자가 포함(Self-contained) 방식으로 필요한 정보를 내부에 포함할 수 있음.

작동 원리

  1. 클라이언트가 인증 정보를 서버에 보냄(예: 사용자명과 비밀번호).
  2. 서버는 사용자를 검증하고, 검증된 사용자에게 토큰을 발급.
  3. 클라이언트는 토큰을 저장(예: 로컬 스토리지 또는 세션 스토리지).
  4. 클라이언트는 요청마다 토큰을 헤더(Authorization: Bearer 토큰)로 전송하여 인증.

특징

  • Stateless: 토큰은 클라이언트에 저장되므로 서버는 사용자 상태를 유지하지 않음.
  • 보안 강화: 토큰 자체에 서명이 포함되므로 위조 방지가 가능.
  • 유효 기간: 토큰에 만료 시간이 포함되어 보안성을 향상.

4. JWT(Json Web Token)

개념

  • JWTJSON 형식으로 데이터를 인코딩한 토큰입니다.
  • 클라이언트와 서버 간 인증 및 정보 교환에 사용되며, URL-safe한 형식으로 인코딩되어 HTTP 요청의 헤더, URL, 또는 본문에서 안전하게 전송할 수 있습니다.

구조

JWT는 세 가지 부분으로 구성됩니다:

  1. Header: 토큰 타입(JWT)과 서명에 사용된 알고리즘 정보를 포함.

    
    {
      "alg": "HS256",
      "typ": "JWT"
    }
    

  1. Payload: 사용자 정보 또는 클레임(Claims)을 포함.

    
    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
    

  1. Signature: 토큰 변조를 방지하는 서명.

    
    HMACSHA256(
      base64UrlEncode(header) + "." + base64UrlEncode(payload),
      secret
    )
    

특징

  • 자가 포함(Self-contained): JWT는 필요한 정보를 자체적으로 포함.
  • Stateless: 서버가 상태를 저장할 필요가 없음.
  • URL-safe: Base64Url로 인코딩되어 URL에 안전하게 포함 가능.

보안 고려사항

  • JWT 자체는 암호화되지 않으므로, 민감한 정보는 포함하지 말아야 함.
  • 토큰 만료 시간(exp)을 설정하여 재사용 위험을 줄임.

5. 저장 위치

  • 세션(Session):
    • 데이터는 서버에 저장됩니다.
    • 클라이언트 측에는 세션 ID만 전달되며, 이는 쿠키 또는 URL 매개변수로 클라이언트와 서버 간에 주고받습니다.
    • 예: 서버의 메모리, 데이터베이스, 또는 파일 시스템에 저장.
  • 쿠키(Cookie):
    • 클라이언트의 브라우저에 저장됩니다.
    • 데이터 자체(예: 세션 ID, 사용자 설정 등)가 클라이언트의 쿠키에 보관되며, 요청 시마다 서버로 전송됩니다.
  • 토큰(Token):
    • 데이터는 클라이언트 측에 저장됩니다(주로 로컬 스토리지 또는 세션 스토리지).
    • 서버는 토큰을 저장하지 않고, 토큰 자체에 필요한 정보를 포함합니다(Stateless).

6. 인증과 상태 유지

  • 세션(Session):
    • 상태 기반 인증입니다.
    • 서버가 사용자의 상태를 관리하고, 세션 ID를 통해 사용자와 상태를 매핑합니다.
    • 서버 부하가 증가할 수 있으며, 확장성(Scalability)이 제한될 수 있음.
  • 쿠키(Cookie):
    • 상태 유지 도구입니다.
    • 인증 자체보다는 세션 ID나 사용자 기본 설정과 같은 데이터를 저장하고 전송하는 데 주로 사용됩니다.
    • 만료 시간을 설정하여 특정 기간 동안 유지 가능.
  • 토큰(Token):
    • 상태 비저장 인증입니다.
    • 클라이언트가 토큰을 서버로 전달하며, 서버는 토큰의 유효성을 검증하여 인증합니다.
    • 서버는 상태를 저장하지 않아 확장성이 좋음.

7. 보안

  • 세션(Session):
    • 상대적으로 안전합니다.
    • 민감한 데이터는 서버에 저장되며, 세션 ID만 클라이언트에 전달되므로 데이터 변조 위험이 적습니다.
    • 하지만, 세션 하이재킹(세션 ID 탈취) 공격에 취약할 수 있음.
  • 쿠키(Cookie):
    • 보안 설정이 중요합니다.
      • Secure 속성: HTTPS에서만 쿠키를 전송.
      • HttpOnly 속성: 자바스크립트를 통해 쿠키에 접근 불가능.
    • 설정이 부실하면, XSS(크로스 사이트 스크립팅) 공격이나 중간자 공격에 노출될 위험이 있음.
  • 토큰(Token):
    • 서명(Signature)을 통해 변조 방지가 가능.
    • 하지만, JWT처럼 서명이 있어도 데이터는 암호화되지 않으므로 민감한 정보를 포함하지 않아야 함.
    • 유효 기간(exp)을 설정하여 오래된 토큰 사용 방지.

8. 유효 기간과 만료

  • 세션(Session):
    • 서버에서 세션의 유효 기간을 관리합니다.
    • 기본적으로 세션은 브라우저를 닫으면 만료되지만, 만료 시간을 설정하여 브라우저가 열려 있어도 세션이 유지될 수 있음.
  • 쿠키(Cookie):
    • 쿠키의 만료 시간은 서버가 지정할 수 있습니다.
    • 세션 쿠키는 브라우저가 닫히면 삭제되고, 영구 쿠키는 지정된 만료 시간까지 유지됩니다.
  • 토큰(Token):
    • 토큰 자체에 만료 정보(exp 필드)가 포함됩니다.
    • 만료 시간이 지나면 토큰은 유효하지 않으며, 클라이언트는 새로운 토큰을 받아야 합니다.

9. 사용 사례

항목세션(Session)쿠키(Cookie)토큰(Token)
사용 예로그인 상태 유지, 장바구니 관리사용자 환경 설정, 세션 ID 저장RESTful API 인증, OAuth 2.0
적합 환경전통적인 웹 애플리케이션간단한 상태 저장모바일/SPA 환경, Stateless 서버

10. 성능과 확장성

  • 세션(Session):
    • 서버가 상태를 유지해야 하므로 서버 부하가 증가할 수 있습니다.
    • 서버를 확장(예: 여러 대의 서버로 분산)하려면 세션 데이터를 공유하는 별도 저장소(예: Redis)가 필요합니다.
  • 쿠키(Cookie):
    • 서버 부하가 없지만, 클라이언트에 저장된 쿠키 데이터가 많아지면 브라우저와 서버 간 통신에 영향을 줄 수 있습니다.
  • 토큰(Token):
    • 서버는 상태를 유지하지 않아 확장성이 높습니다.
    • 단, 토큰의 크기가 크면 네트워크 트래픽에 영향을 줄 수 있습니다.

JWT (Json Web Token) 상세 설명

JWT는 클라이언트와 서버 간 인증 및 데이터 교환을 위해 널리 사용되는 토큰 형식입니다. JWT는 안전하고 간단한 구조로 다양한 웹 애플리케이션에서 사용됩니다.

1. JWT의 구조

JWT는 Header, Payload, Signature 세 부분으로 구성되며, Header.Payload.Signature 형태의 문자열로 나타납니다.

1-1. Header

  • JWT의 메타데이터를 포함합니다.
  • 두 가지 주요 정보:
    • alg: 서명에 사용된 알고리즘 (예: HS256, RS256 등).
    • typ: 토큰 타입 (JWT로 고정).
{
  "alg": "HS256",
  "typ": "JWT"
}
  • Base64Url로 인코딩되어 JWT의 첫 번째 부분을 구성합니다.

1-2. Payload

  • JWT의 데이터 부분으로, 사용자 정보나 클레임(Claims)을 포함합니다.
  • 주요 정보:
    • Registered Claims (사전 정의된 클레임):
      • iss (Issuer): 토큰 발급자.
      • sub (Subject): 토큰 주제(예: 사용자 ID).
      • aud (Audience): 토큰 대상.
      • exp (Expiration Time): 만료 시간.
      • iat (Issued At): 발급 시간.
      • nbf (Not Before): 특정 시간 이후에만 유효.
    • Custom Claims (사용자 정의 클레임):
      • 사용자 애플리케이션에서 필요한 정보(예: 사용자 이름, 권한 등).
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "iat": 1516239022
}
  • Base64Url로 인코딩되어 JWT의 두 번째 부분을 구성합니다.

1-3. Signature

  • 토큰의 무결성을 보장하는 서명(Signature) 부분입니다.
  • 생성 방식:
    HMACSHA256(
        Base64UrlEncode(Header) + "." + Base64UrlEncode(Payload),
        secret
    )
    
    • HeaderPayload를 연결한 후 서명 알고리즘과 비밀 키(secret key)로 서명합니다.
    • Signature를 통해 토큰이 변조되지 않았는지 확인할 수 있습니다.

2. JWT의 작동 원리

  1. 클라이언트 인증 요청:
    • 클라이언트가 사용자명과 비밀번호를 서버로 보냅니다.
  2. 서버 인증 후 JWT 생성:
    • 서버는 사용자를 인증하고, 사용자 정보를 포함한 JWT를 생성하여 클라이언트로 반환합니다.
  3. 클라이언트 저장:
    • 클라이언트는 JWT를 로컬 스토리지 또는 세션 스토리지에 저장합니다.
  4. 요청 시 JWT 전송:
    • 클라이언트는 이후 요청마다 HTTP 헤더(예: Authorization: Bearer )에 JWT를 포함하여 서버로 전송합니다.
  5. 서버 검증:
    • 서버는 JWT의 서명을 확인하고, Payload 정보를 기반으로 요청을 처리합니다.

3. JWT의 특징

3-1. 장점

  1. Stateless:
    • 서버가 사용자 상태를 저장할 필요가 없습니다.
    • 서버 부하를 줄이고 확장성이 뛰어납니다.
  2. 자가 포함(Self-contained):
    • JWT에 필요한 정보를 모두 포함하므로 추가적인 데이터베이스 조회 없이 요청을 처리할 수 있습니다.
  3. URL-safe:
    • Base64Url 인코딩 방식을 사용하여 URL, 헤더, 본문 등에 안전하게 포함될 수 있습니다.
  4. 빠른 검증:
    • 서버는 서명을 확인하여 데이터의 무결성을 검증할 수 있으므로 빠르고 효율적입니다.

3-2. 단점

  1. 크기 증가:
    • JWT는 헤더와 페이로드, 서명까지 포함하기 때문에 세션 ID보다 크기가 큽니다.
    • 네트워크 트래픽에 영향을 줄 수 있습니다.
  2. 보안 문제:
    • JWT는 서명(Signature)을 통해 변조 방지는 가능하지만, 암호화되지 않으므로 페이로드에 포함된 정보는 누구나 볼 수 있습니다.
    • 민감한 정보는 JWT에 포함하지 말아야 합니다.
  3. 토큰 만료:
    • 토큰이 만료되기 전까지 유효하므로, 만료된 토큰을 갱신하거나 철회하는 데 관리가 필요합니다(예: 로그아웃 시).

4. JWT의 사용 사례

  1. 사용자 인증:
    • 사용자가 로그인하면 서버가 JWT를 발급하여 클라이언트가 이후 요청에서 인증을 수행할 수 있도록 합니다.
  2. 권한 부여:
    • JWT의 Payload에 사용자의 권한(Role)을 포함하여, 서버가 사용자의 액세스 권한을 결정합니다.
  3. 다중 플랫폼 지원:
    • 모바일, 웹 등 다양한 클라이언트에서 동일한 JWT를 사용할 수 있습니다.
  4. API 인증:
    • RESTful API 또는 GraphQL API에서 클라이언트-서버 간 통신을 인증하는 데 사용됩니다.

5. JWT의 보안 고려 사항

  1. 비밀 키 관리:
    • 서명에 사용되는 비밀 키(secret key)는 철저히 보호되어야 합니다.
  2. 만료 시간 설정:
    • exp(Expiration Time) 클레임을 사용하여 토큰의 유효 기간을 명시적으로 설정합니다.
  3. HTTPS 사용:
    • 토큰 전송 시 HTTPS를 사용하여 데이터의 중간자 공격을 방지합니다.
  4. 정보 최소화:
    • Payload에는 최소한의 정보만 포함하고, 민감한 데이터는 절대 포함하지 않습니다.
  5. 토큰 철회(Revoke):
    • 로그아웃 등 특정 시점에서 토큰을 철회하거나, 서버에서 "블랙리스트"를 관리하여 특정 토큰을 차단합니다.

6. JWT의 실제 예제 (JavaScript 기반)

JWT 생성

const jwt = require('jsonwebtoken');

// 사용자 정보와 비밀 키로 JWT 생성
const payload = {
    sub: '1234567890',
    name: 'John Doe',
    admin: true
};
const secretKey = 'your_secret_key';
const token = jwt.sign(payload, secretKey, { expiresIn: '1h' });

console.log(token);

JWT 검증

try {
    const decoded = jwt.verify(token, secretKey);
    console.log(decoded); // Payload 정보 출력
} catch (err) {
    console.error('Invalid token');
}  

회고

  • 뉴스피드 프로젝트가 내일 종료된다.
    모두의 고생이 담긴 결과물이 마무리까지 잘 끝났으면 좋겠다.
  • 챌린지반 과제로 위 주제에 대해 공부했는데, 개념은 역시나 너무 어렵다.
    본 수업때 들으면서 이해해봐야겠다.
  • 발표 마치는날까지 화이팅!!!

그럼이만

0개의 댓글