
로그인을 할 때, 서버에서 로그인 중인지를 알기 위해서 대표적으로
Cookie,Session,Token3가지 방식을 사용한다.
HTTP은 Stateless(상태를 기억하지 않는) 프로토콜이기 때문이다.
=> 이는 각각의 요청이 서로 독립적이며 이전 요청과는 아무런 관련이 없다는 것을 의미!!
그러나 웹 애플리케이션은 사용자의 로그인 상태를 유지해야 한다.
이를 위해 Cookie, Session, Token과 같은 메커니즘이 사용된다.
로그인 인증을 위해서
Cookie와Session은 같이 사용된다. 그렇기 때문에Cookie와Session은 세트메뉴이다.

Client(Browser)에 저장되는 데이터
- 서버가
"이 사용자가 누구인지 기억해줘"하고 작은 데이터를 브라우저에게 전달하면, 브라우저는 다음 요청마다 그 쿠키를 서버에 자동으로 보낸다.- 보통 로그인 상태 유지, 자동 로그인, 다크모드 설정 등에 사용된다.

Server에 저장되는 사용자 정보
- 사용자가 로그인하면?
- 서버는 세션을 생성하고,
- 그 세션의 고유 ID(세션 ID) 를 브라우저의 쿠키에 담아 보관합니다.
- 사용자가 다음 요청을 보낼 때,
브라우저는 그 세션 ID 쿠키를 함께 전송하고- 서버는 그 ID를 보고
“아, 이건 로그인한 사용자구나!”하고 알아봅니다
사용자가 브라우저에서 ID/PW 입력
브라우저가 HTTP POST 요청으로 서버에 전송
POST /login
Content-Type: application/x-www-form-urlencoded
id=donghee&pwd=1234
서버가 DB에 ID/PW 확인
로그인 성공 시, 서버는 Session 생성
import secrets
import hashlib
import time
def generate_session_id(user_id=None):
~~~
return session_id
=> 해당 방식을 통해, Session ID 생성
세션 데이터를 서버 저장소에 저장
Redis, DB, Memory서버는 HTTP 응답 헤더에 Set-Cookie를 포함한다.
HTTP/1.1 200 OK
Set-Cookie: session=abc123xyz789; HttpOnly; Path=/;
브라우저는 Cookie를 저장
Cookie 이름: sessionCookie 값: abc123xyz789 (세션 ID, 서버에서 세션 데이터와 연결)이제 사용자가 다른 페이지로 이동하면 브라우저는 자동으로 쿠키를 전송합니다.
GET /mypage
Cookie: session=abc123xyz789
서버는 이제 이 Session ID를 보고 서버 Session 저장소에서 사용자 정보를 찾아낸다.
브라우저에서 로그아웃 요청
서버는 세션 삭제 또는 무효화
브라우저 쿠키 만료
Set-Cookie: session=; Max-Age=0
from flask import Flask, make_response
@app.route("/set_cookie")
def set_cookie():
resp = make_response("쿠키 저장 완료!")
resp.set_cookie("username", "donghee", max_age=60) # 60초 유지
return resp
데이터(donghee)가 그대로 브라우저 쿠키에 저장됩니다.
브라우저는 쿠키를 요청마다 서버로 전송합니다:
Cookie: username=donghee
=> 서버가 별도로 세션을 만들 필요 없음
장점: 단순, 서버 저장 공간 필요 없음
단점: 브라우저에서 조작 가능, 보안 낮음
즉, 쿠키에 값 자체를 넣는 방식입니다.

=> 해당 세션은 암호화되어 있어서 직접적인 세션 ID는 아니라고 함.
공격자가 Session ID를 탈취하면?
=> Server는 그 사용자를 정상 사용자로 인식한다.
탈취 Session을 무효화하려면?
=> Server에서 Session Storage를 전부 초기화해야 한다.
문제점 : 정상 사용자까지 모두 재로그인해야 한다는 점이다.
=> 결과적으로, 서버가 stateful 해진다.
"로그인 안 됨" 상태가 됨.세션 클러스터링
여러 서버가 세션을 서로 공유하도록 하는 방법입니다.
세션 클러스터링에는 방법이 여러 가지다.
스티키 세션
같은 사용자의 요청은 항상 같은 서버로 보내는 방식.
세션 스토리지 분리
세션을 외부의 DB나 인메모리 저장소에 따로 저장.
세션을 저장할 때는 대표적인 Key-Value DB인 Redis와 Memcached 를 사용
원래는
JWT/Token은 들어봤다만... 이번에 업무 관련으로 코드 분석하다보니Cookie와Session을 친구에게 물어보다보니
Session은 올드하다는 이런 사연으로 인해JWT와Token을 공부하고자 한다.
해당
Session+Cookie의 문제점과 한계로 인해 등장했다.
서버가 상태를 저장하지 않고 stateless하게 인증 가능.
토큰 자체에 사용자 정보(Claim)와 유효기간, 권한 정보가 들어있어
→ 서버는 토큰만으로 누구인지 확인 가능.여러 서버, MSA, 모바일/SPA 환경에서도 동일한 방식으로 인증 처리 가능.
세션 공유, 클러스터링, sticky session 같은 복잡한 인프라를 피할 수 있음.
탈취 시 토큰 만료 시간으로 제한 가능, 서버 재설정 불필요.
토큰(Token)은 말 그대로 인증을 위한 표식이다.
서버가 "이 사용자는 인증된 사용자" 라고 증명하기 위해 클라이언트에게 발급해주는 임시 열쇠이다.
사용자가 로그인하면?
→ 서버가 로그인 정보 확인 후 “토큰”을 발급합니다.이후 사용자는 요청할 때마다
→ 이 “토큰”을 HTTP 헤더에 포함시켜 보냅니다.서버는 토큰만 보고도 “누군지” 알 수 있습니다.
ex)
8f2b9af9c4f8413d91a15d0f6aabfcd0
토큰은 단순히 문자열일 뿐입니다.
서버가 “이 토큰은 user_id=123의 로그인 인증용”이라고 내부적으로 알고 있으면, 이 문자열만으로 인증이 가능합니다.
하지만 이런 임의 문자열 기반의 토큰에는 한계가 있습니다.
결국 기존의 단순한 “문자열 토큰” 방식도 서버 상태에 의존하거나, 관리 포인트가 늘어난다는 문제가 있었어요.
그래서 등장한 것이
JWT (JSON Web Token)“토큰 안에 인증 정보를 직접 담자!”
→ 서버에 따로 저장하지 않고도 인증이 가능하게 하자.
사용자의 인증 정보(예: user_id, 권한, 만료시간 등)를 JSON 형식으로 인코딩한 토큰입니다.
즉, 토큰 안에 누군지 / 언제까지 유효한지 / 어떤 권한을 가졌는지 모든 정보가 들어 있습니다.
이 덕분에 서버는 별도 저장소 없이, JWT의 서명(Signature)만 검증하면 사용자를 신뢰할 수 있습니다.
xxxxx.yyyyy.zzzzz
xxxxx : Header
토큰의 타입(JWT) 과 서명 알고리즘(HS256 등)
yyyyy : Payload
실제 데이터 (user_id, exp, role)
zzzzz : Signature
위 두 부분을 비밀키로 서명한 값 (변조 방지용)
JWT : JWT는 Base64로 인코딩된 문자열 형태입니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VySWQiOjEyMywicm9sZSI6InVzZXIiLCJleHAiOjE3MzAyMjgwMDB9.
ZqS8ChSgq5hM-5VuPZTzoB8JzKAjlHn4hC9pY0-3m1Q
JWT를 디코딩하면 다음과 같은 JSON 정보가 나옴.
Header : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9{
"alg": "HS256",
"typ": "JWT"
}
Payload : eyJ1c2VyIjoiZG9uZ2hlZSIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTczMDQ5NjAwMH0{
"user": "donghee",
"role": "admin",
"exp": 1730496000
}
Signature : ZqS8ChSgq5hM-5VuPZTzoB8JzKAjlHn4hC9pY0-3m1QHMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret_key
)Header.Payload.Signature
클라이언트가 로그인 → 서버가 JWT 발급
이후 요청마다 JWT를 HTTP HEADER에 포함 (Authorization: Bearer <JWT>)
Bearer Token : 클라이언트가 특정 리소스에 접근할 수 있는 권한을 증명하기 위해 서버에 전달하는 토큰
서버는 저장소 조회 없이 JWT의 Signature만 검증
→ 유효하면 요청 처리
간단하게 ChatGpt 로 구현해보았다.
로그인 창
js로
jwt를local storage로 저장하게 했지만 아직 없는 것을 확인할 수 있다.
로그인 후,
local storage에 jwt가 있는 것을 확인 가능하다.
토큰 허용 시간 설정
다음과 같이 설정
로그인 하자마자 Token으로 데이터 요청
해당 코드 처럼 decode가 되어 user를 뽑아서 "Welcome,
admin!" 이 출력된 것을 볼 수 있다.
1분 후, 다시 만료된 Token으로 데이터 요청
=> 다음과 같이 정상적인 데이터와 비정상적인 데이터가 따로 조회되는 것을 확인 가능!
https://token.dev/
JWT 검증 사이트인데 해당 사이트 이용하면 JWT 구조 이해에 더 도움될듯해요.