Cookie, Session, Token, JWT

[verify$y]·2025년 8월 13일

CS핵심개념

목록 보기
24/35
  • 보통 서버가 클라이언트 인증을 확인하는 방식은 대표적으로 위 3가지 방식 있다
  • JWT 앞서 쿠키, 세션 통신방식을 이해하고 토큰 사용 목적을 이해해보자


  • Key-value의 문자열
  • 클라이언트가 어떤 웹사이트를 방문할 경우, 그 사이트가 사용하고 있는 서버를 통해 클라이언트의 브라우저에 설치된 작은 기록 정보 파일이다.
  • 각 사용자별로 브라우저에서 저장하고 사용자를 식별하는데 사용된다.

1. Cookie 인증방식 플로우

  1. 브라우저Client가 서버에 접속요청을 한다.
  2. 서버는 브라우저 요청에 대한 응답을 작성할떄, 클라이언트 측에 저장하고 싶은 정보를 응답헤더 Set-Cookie에 담는다.
  3. 이후 해당 클라이언트는 요청을 보낼떄마다 매번 저장된 쿠키를 요청 헤더의 Cookie에 담아 보낸다. 서버는 쿠키에 담긴 정보를 바탕으로 해당 요청의 클라이언트가 누군지 식별하거나 정보를 바탕으로 맞춤 서비스를 제공한다. (사용자 전용 광고)

2. Cookie방식의 단점

  • 보안에 취약하다. 왜냐면 요청시 쿠키 값을 그대로 보내기 떄문에 가로챌 수 있다.
  • 쿠키에는 용량제한이 있다.
  • 웹 브라우저마다 쿠키에 대한 지원형태가 다르므로 브라우저간 공유 불가
  • 쿠키사이즈가 커질수록 네트워크 부하 증가

3. Cookie사용예시

  • 방문한적이 있는 웹사이트가 개인정보를 가지고 있음
  • 개인정보가 클라이언트에 저장되므로 임의로 수정가능, 가로채기 쉬움
  • 최근 검색이력
  • 최근 둘러본 상품 리스트
  • 팝업 광고 일주일간 보지 않기 체크
  • 아이디 저장하기 및 로그인 상태 유지




Session

  • 도입배경 : 쿠키의 보안이슈를 보완하고자 탄생했다.

  • 특징 :

    • 세션은 비밀번호와 같이 사용자의 개인정보를 클라이언트(브라우저)가 아닌 서버측에 저장한다.
    • 서버 메모리에 저장하고 or 서버의 로컬 파일에 저장하거나 DB에 저장
    • 한마디로 개인정보를 모두 서버에서 직접 관리한다. 클라이언트가 관리하지 않는다.

1. Sesssion 저장형태

  • key-value이며 key에는 세션아이디, value에는 세션생성일자, 마지막 접근일시, User에 대한 정보가 들어간다.
  • value에는 Map형식으로 데이터가 저장된다.




2. Session플로우

  1. 사용자가 웹사이트접속한다.
  2. 서버는 접근한 클라이언트의 요청헤더의 쿠키필드값을 확인한다.클라이언트가 해당 세션아이디를 보냈는지 확인한다.
  3. 세션아이디가 없을경우, 서버는 새로운 새션 아이디를 발급하여 클라이언트에게 돌려준다.
  4. 서버는 클라이언트 로그인 요청에 대한 응답을 작성할때 인증정보는 서버에 저장하고, 클라이언트 식별자 JSESSIONID를 쿠키에 담는다. 쿠키는 클라이언트에서 저장하는 방식이다. 위에서 설명했다.
  5. 클라이언트는 세션아이디에 대해 쿠키를 사용해 저장하고, 정보를 가지고 있는다.
  6. 클라이언트는 서버에 요청시, 쿠키의 세션필드에 새션아이디를 넣어 요청과 함께 서버에 전달한다.
  7. 서버는 세션아이디를 읽어 세션아이디로 세션에 있는 사용자 정보를 가져와서 사용한다.
  8. 클라이언트 정보를 가지고 서버 요청을 처리해 클라이언트에 응답한다.

3. Session단점

  • 쿠키를 포함한 요청이 외부에서 노출되더라고 세션아이디값만 존재하므로 유의미한 정보를 얻을 수 없지만, 새션아이디를 탈취하여 클라이언트인척 위장이 가능하다. 이는 아이피 주소를 통해 구별이 가능하며 약간의 설정이 필요한 작업이다.
  • 모바일 네트워크 특성상 휴대성이 높아 ip가 자주 바뀌는데, 이러한 상황에서 세션을 사용하면 세션은 ip로 관리하는 경우가 많아 상당히 불편하다.
  • 세션에 대한 용량 제한은 없으나 사용자가 많아지면 서버부하가 증가한다. 이는 쿠키와 마찬가지

4. Session 사용예시

  • 화면을 이동해도 로그인상태유지



Token

  • 토큰 기반 인증시스템은 클라이언트가 서버에 접속하면 서버에서 해당 클라이언트에게 인증되었다는 의미로 토크을 부여한다.
  • 이 토큰은 토큰을 발급받은 클라이언트는 또 다시 서버에 헤더에 토큰을 넣어 요청을 보낸다.
  • 서버는 클라이언트로부터 받은 토큰을 서버에게 제공한 토큰의 일치여부를 체크하는 인증과정을 수행한다.
  • 토큰은 세션인증과 달리, 클라이언트에 토큰이 저장된다. 따라서 메모리나 스토리지에 요청과부하를 피할 수 있다.
  • 토큰 자체에 데이터가 들어있기 때문에 클라이언트에서 받아 위조되었는지 판별만 하면된다.
  • 토큰은 앱과 서버가 통신 및 인증할때 가장 많이 사용되는 방식이다. 왜냐하면 웹에서 쿠키와 세션이 있지만 앱에서는 없다고 한다.
  • 쿠키,세션 서버기반 인증시스템과 달리, stateless하다.


Token인증플로우

  1. 사용자가 ID, PW로 로그인
  2. 서버에서는 클라이언트에게 Token을 발급한다. (기존 토큰이 없는경우에)
  3. 클라이언트는 서버에게 전달받은 토큰을 쿠키로 저장해두고 서버에 요청할때마다 토큰을 헤더에 넣어 전달한다.
  4. 서버는 전달받은 토큰을 검증하고 요청에 응답한다. 토큰에는 요청한 사람의 정보가 담겨있기에 서버는 DB를 조회하지 않고 사용자를 식별가능하다

Token단점

  • 토큰이 길면 요청 헤더 크기 증가 → 네트워크 부하 누적
  • 페이로드는 암호화되지 않는다.
  • JWT는 잘 설계하면 안전하고 확장성 높은 인증 방법이지만, 세션 기반보다 절대 안전한 건 아니고 오히려 관리가 허술하면 피해 범위가 커질 수 있습니다.


토큰의 보안 위험과 대응 방법

  • 토큰이 탈취되면, 공격자가 해당 토큰의 만료 시간까지 권한을 사용할 수 있어서 취약하다.
  • 하지만 대응책이 전혀 없는 것은 아니며, 다음과 같은 방법으로 무력화할 수 있다.
  1. 만료 시간(Expiration) 설정
  • 토큰은 일반적으로 짧은 유효 기간(exp Claim)을 설정해 두어, 탈취되더라도 일정 시간이 지나면 자동으로 무효화되도록 한다.
  • Access Token은 짧게(예: 15분~1시간), Refresh Token은 상대적으로 길게 설정하는 것이 일반적이다.
  1. 서버 측 블랙리스트(Blacklist)
  • 탈취가 확인된 토큰을 서버 측에 저장된 블랙리스트에 등록하여 더 이상 사용할 수 없게 한다.
  • Stateless 특성 때문에 기본적으로 서버에서 토큰을 기억하지 않지만, 보안이 중요한 서비스는 예외적으로 저장한다.
  1. Refresh Token 사용 및 재발급 전략
  • Access Token만 유출된 경우, Refresh Token 기반으로 새로운 Access Token을 발급받고 기존 토큰은 폐기한다.
  • Refresh Token 또한 탈취 위험이 있으므로 별도의 보안 정책(재발급 시 IP/기기 체크 등)을 적용한다.
  1. IP/디바이스 기반 토큰 무효화
  • 토큰 사용 시 발급 당시의 IP, User-Agent, 디바이스 ID 등을 기록해 두고, 이후 요청에서 불일치 시 인증을 거부한다.




JWT

JWT 구조

  • JWT는 세 부분으로 나뉘며, 각각 점(.)으로 구분됩니다.
    • xxxxx.yyyyy.zzzzz
    • (header).(payload).(signature)으로 구성되어 있다.
  • Header, Payload, Signature
    • Header : 토큰의 메타정보 (타입, 서명 알고리즘) / alg, typ / Base64 URL-safe 인코딩
    • Payload : 사용자 식별자(Claim) / sub, name, role, exp / 암호화없음
    • Signature : 헤더+페이로드를 비밀키로 서명한 값 / - / 서버가 위변조 여부 확인

JWT구성예시

  • Signature는 Header, Payload를 인코딩하고 비밀키로 암호화한다.

  • (header).(payload).(signature)으로 만들면 JWT

    HEADER:     {
        "alg": "HS256",
        "typ": "JWT"
    }
    
    PAYLOAD:    {
        "sub": "user123",
        "name": "홍길동",
        "role": "admin",
        "exp": 1712345678
    }
    
    SIGNATURE:  HMACSHA256(
          base64UrlEncode(header) + "." +
          base64UrlEncode(payload),
          secretKey
    )
  • 조합후

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    .
    eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6Iu2PrOyggeycoCIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxMjM0NTY3OH0
    .
    SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c



JWT 헷갈리는 부분

  • Payload에 담기는 건 일부 식별 정보일 뿐, 사용자의 전체 데이터베이스 내용이 아님.

  • Payload는 암호화되지 않아서 누구든 디코딩 가능 → 민감 정보 저장 안함

  • Signature 덕분에 내용이 위변조되었는지 서버가 검증 가능.

  • 그래서 JWT는 "사용자 정보 그 자체"가 아니라, "사용자 신원을 증명하는 서명된 데이터".




쿠키

  1. 로그인 시 서버가 쿠키 발급 → 브라우저 저장
  2. 브라우저 요청마다 쿠키 자동 전송
  3. 서버는 쿠키 값으로 사용자 식별

세션

  1. 로그인 시 서버가 세션ID 생성 → 브라우저 쿠키 저장
  2. 요청 시 세션ID를 쿠키로 전송
  3. 서버가 세션 저장소에서 사용자 정보 조회

토큰(JWT)

  1. 로그인 시 서버가 JWT 발급 (Header + Payload + Signature)
  2. 브라우저 로컬스토리지/쿠키에 저장
  3. 요청 시 Authorization 헤더로 전송
  4. 서버가 서명 검증 후 요청 처리 (DB 조회 없이 사용자 식별 가능)

구분저장 위치서버 상태 유지 여부인증 데이터 형태장점단점
쿠키브라우저Statelesskey=value구현 간단데이터 위변조·탈취 위험, 브라우저 의존
세션서버(메모리/DB)Stateful세션ID(쿠키로 전달)보안성↑, 데이터 서버 보관사용자 많으면 서버 부하↑
토큰(JWT)브라우저(로컬스토리지/쿠키)Stateless서명된 JSON 문자열확장성↑, 서버 부하↓만료 전까지 탈취 시 위험, 길이↑
profile
welcome

0개의 댓글