1532 단어
8 분
쿠키, 세션, JWT
인증과 상태 유지: Cookie, Session, JWT 핵심 정리
1. 주제 소개
1.1 웹 애플리케이션의 인증과 상태 유지
웹은 기본적으로 Stateless(무상태) 프로토콜인 HTTP를 사용함. 따라서 사용자의 로그인 상태를 유지하거나 요청 간 정보를 공유하기 위해 별도의 기술이 필요
- 인증(Authentication): 사용자가 누구인지 확인하는 절차
- 상태 유지: 페이지를 이동해도 사용자의 로그인 상태가 끊기지 않도록 하는 기술
1.2 핵심 개념
- 쿠키(Cookie): 클라이언트(브라우저) 측 저장 방식
- 세션(Session): 서버 측 저장 방식
- JWT(JSON Web Token): 토큰 기반 인증 방식
2. 쿠키 (Cookie)
2.1 개념
- 클라이언트(브라우저)에 저장되는 작은 데이터 조각
- 서버가 응답할 때
Set-Cookie헤더를 통해 설정함 - 클라이언트는 이후 요청 시 자동으로 쿠키를 서버로 전송함
2.2 특징
- 키-값(key=value) 형태로 저장됨
- 만료 시간 설정 가능 (
expires또는max-age) - Secure: HTTPS에서만 전송 가능
- HttpOnly: 자바스크립트에서 접근 불가 (보안 강화)
- 도메인 및 경로 지정 가능
2.3 예제 (JavaScript)
// 쿠키 설정document.cookie = "username=John; expires=Fri, 31 Dec 2024 23:59:59 GMT; path=/"2.4 보안 문제
- XSS 공격: 자바스크립트로 쿠키를 탈취할 수 있음 → HttpOnly 설정으로 방지
- CSRF 공격: 인증된 쿠키를 악용해 원치 않는 요청을 보낼 수 있음 → CSRF 토큰 사용 필요
3. 세션 (Session)
3.1 개념
- 서버에서 사용자의 정보를 저장하고, 클라이언트에게는 세션 ID만 부여하는 방식
- 클라이언트는 요청 시 세션 ID를 보내고, 서버는 이를 통해 사용자 정보를 찾음
3.2 특징
- 데이터가 서버에 저장되므로 보안성이 높음
- 일정 시간이 지나면 세션이 만료됨
- 클라이언트는 의미 없는 세션 ID만 저장하므로 정보 유출 위험이 적음
3.3 동작 방식
- 사용자가 로그인하면 서버에서 세션 ID 생성
- 클라이언트의 쿠키에 세션 ID 저장
- 이후 요청마다 클라이언트는 세션 ID를 전송
- 서버는 세션 저장소에서 ID를 대조해 사용자 정보 조회
3.4 예제 (Express.js)
const session = require('express-session')
app.use(session({ secret: 'my_secret_key', resave: false, saveUninitialized: true, cookie: { secure: false }}))
app.get('/', (req, res) => { req.session.username = "John" // 세션에 데이터 저장 res.send("Session Set!")})3.5 단점 및 보안 문제
- 세션 탈취(Session Hijacking): 세션 ID를 탈취당하면 해커가 사용자 행세를 할 수 있음
- 서버 부담: 동시 접속자가 많으면 서버 메모리 사용량이 급증함 (확장성 문제)
4. JWT (JSON Web Token)
4.1 개념
- 토큰 기반 인증 방식
- 서버에 사용자 정보를 저장하지 않고, 토큰 자체에 암호화된 정보(Payload)를 포함
- 클라이언트가 토큰을 저장하고 요청할 때마다 헤더에 포함시켜 보냄
4.2 구조 (3부분)
aaaaa.bbbbb.ccccc 형태
- 헤더(Header): 토큰 타입과 암호화 알고리즘 (예: HS256)
- 페이로드(Payload): 실제 사용자 정보 (username, 만료 시간 등)
- 서명(Signature): 위변조 방지를 위한 서명 값
4.3 예제 (Node.js + jsonwebtoken)
const jwt = require('jsonwebtoken')
// JWT 생성 (발급)const token = jwt.sign({ username: "John" }, "my_secret_key", { expiresIn: "1h" })console.log(token)
// JWT 검증const decoded = jwt.verify(token, "my_secret_key")console.log(decoded)4.4 장점과 단점
- ✅ 장점
- Stateless: 서버에 세션 정보를 저장하지 않아 서버 부담이 적음
- 확장성: 마이크로서비스(MSA) 환경이나 다중 서버 환경에 적합
- 다중 플랫폼: 웹, 모바일 앱 등 다양한 클라이언트에서 사용 용이
- ❌ 단점
- 토큰 탈취: 한 번 발급된 토큰은 만료 전까지 제어하기 어려움
- 크기: 페이로드 정보가 많아지면 토큰 크기가 커져 네트워크 비용 증가
5. 세션 vs 쿠키 vs JWT 비교
| 구분 | 쿠키 (Cookie) | 세션 (Session) | JWT (Token) |
|---|---|---|---|
| 저장 위치 | 클라이언트 | 서버 (메모리/DB) | 클라이언트 |
| 보안성 | 낮음 (탈취/변조 용이) | 높음 (서버 관리) | 중간 (서명 포함, 탈취 주의) |
| 서버 부담 | 낮음 | 높음 (데이터 저장 필요) | 낮음 (Stateless) |
| 주 사용처 | 팝업 설정, 비로그인 장바구니 | 로그인, 민감한 정보 저장 | API 인증, 앱 인증, MSA |
6. 언제 무엇을 사용할까?
- 📌 쿠키
- “오늘 하루 보지 않기” 같은 팝업 설정
- 비로그인 상태의 장바구니 임시 저장
- 단순한 사용자 편의 기능
- 📌 세션
- 보안이 중요한 웹 애플리케이션의 로그인 관리
- 사용자가 적거나 단일 서버 환경인 경우
- 📌 JWT
- 모바일 앱 또는 SPA(React, Vue) 인증
- MSA(마이크로서비스) 환경에서 서비스 간 인증
- 소셜 로그인 (OAuth) 토큰 전달
7. 보안 이슈 & 해결 방법
- XSS (Cross-Site Scripting)
- 쿠키/토큰을 자바스크립트로 탈취하는 공격
- 해결: 쿠키 설정 시
HttpOnly옵션 사용
- CSRF (Cross-Site Request Forgery)
- 사용자의 의지와 무관하게 공격자가 의도한 행위(수정, 삭제 등)를 요청하게 함
- 해결: CSRF 토큰 사용, Referer 검증
- JWT 탈취 위험
- 토큰이 탈취되면 만료될 때까지 막을 수 없음
- 해결: Access Token 만료 시간을 짧게(30분) 설정하고, Refresh Token을 함께 사용
- 네트워크 도청
- 데이터가 전송 중에 가로채질 수 있음
- 해결: 모든 통신에 HTTPS 필수 적용
8. 실제 사례 분석
- 쿠키 기반 자동 로그인: 사용자의 편의를 위해 만료 기간이 긴 암호화된 쿠키 사용
- 세션 기반 로그인: 전통적인 은행 사이트, 관공서 사이트 등 높은 보안이 필요한 곳
- JWT 기반 API 인증: 카카오/구글 로그인(OAuth 2.0), 넷플릭스 등 멀티 디바이스 환경 서비스