| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- 배열
- string
- 자바스크립트
- 테스트자동화
- 문자열
- list
- json
- vscode
- HashMap
- input
- 자바문법
- 단위테스트
- Java
- 정규식
- 이클립스
- Eclipse
- junit
- ArrayList
- Visual Studio Code
- IntelliJ
- math
- 자바
- javascript
- java테스트
- html
- 인텔리제이
- CSS
- junit5
- js
- Array
- Today
- Total
어제 오늘 내일
[Spring Security] 6편 - 세션(Session) vs 토큰(JWT), 도대체 뭐가 다를까? 본문
지금까지 우리는 "세션(Session) 기반"의 로그인을 구현했습니다.
사용자가 로그인하면 서버(Tomcat)의 메모리에 "이 사람 로그인했음!"이라고 적어두고,
브라우저에게는 JSESSIONID라는 입장권을 줬죠.
하지만 요즘 트렌드인 React, Vue, 모바일 앱(Android/iOS)과 통신하려면 세션 방식은 한계가 있습니다.
그래서 등장한 것이 JWT(JSON Web Token)입니다.
코드를 짜기 전에, "도대체 JWT가 뭐고, 세션이랑 뭐가 다른지" 명확히 짚고 넘어가는 이론편을 준비했습니다.
(이걸 모르면 코드를 짜도 이해가 안 됩니다!)
두 방식의 차이점을 '헬스장 이용'에 비유해서 아주 쉽게 설명해 드립니다.
1. 세션(Session) 인증 방식 (우리가 지금까지 한 것)
비유: "회원님 얼굴 기억해 둘게요." (헬스장 회원 장부)
- 로그인: 여러분이 헬스장 카운터에 가서 이름을 말합니다.
- 저장: 직원이 장부(서버 메모리)에 "홍길동 입장함"이라고 적어둡니다.
- 이용: 운동기구를 쓸 때마다 직원이 장부를 확인합니다. "아, 홍길동님 아까 왔었지. 쓰세요."
- 단점:
- 메모리 부족: 회원이 100만 명이면 장부가 엄청 두꺼워집니다. (서버 과부하)
- 분산 환경: 헬스장이 1호점, 2호점으로 늘어나면? 1호점 장부엔 내 이름이 있는데, 2호점엔 없습니다. (서버가 여러 대일 때 세션 공유 문제)
[기술적 특징]
- Stateful (상태 유지): 서버가 클라이언트의 로그인 상태를 기억하고 있어야 함.
- 쿠키(Cookie)에
JSESSIONID만 담아서 왔다 갔다 함.
2. 토큰(Token) 인증 방식 (JWT)
비유: "출입증 목걸이를 드립니다." (무인 헬스장)
- 로그인: 카운터에서 신원을 확인합니다.
- 발급: 직원이 여러분의 이름, 등급, 만료시간이 적힌 위조 불가능한 출입증(Token)을 발급해서 여러분에게 줍니다.
- 저장: 직원은 장부에 아무것도 안 적습니다. (서버는 기억 안 함)
- 이용: 운동기구를 쓸 때마다 출입증을 기계에 찍습니다. 기계는 출입증이 위조되었는지만 확인합니다.
- 장점:
- 서버가 가벼움: 서버는 아무것도 저장 안 하니 100만 명이 와도 상관없습니다.
- 확장성: 1호점에서 받은 출입증으로 2호점, 3호점 다 들어갈 수 있습니다. (서버를 막 늘려도 됨)
[기술적 특징]
- Stateless (무상태): 서버는 클라이언트의 상태를 저장하지 않음.
- 클라이언트가 토큰 자체(JWT)를 헤더에 담아서 보냄.
3. JWT(JSON Web Token)의 구조
그렇다면 그 '출입증'은 어떻게 생겼을까요? JWT는 점(.)으로 구분된 세 부분으로 이루어져 있습니다.
aaaaaa.bbbbbb.cccccc (Header . Payload . Signature)
- Header (헤더): "나 JWT야. HS256 알고리즘 썼어." (토큰 타입과 암호화 알고리즘 정보)
- Payload (내용): "내 이름은 홍길동, 유효기간은 1시간." (실제 데이터. 누구나 열어볼 수 있으니 비밀번호는 넣으면 안 됨!)
- Signature (서명): "이건 서버 사장님만 찍을 수 있는 도장이야." (위조 방지용 암호화 서명)
4. 한눈에 비교하기
| 특징 | 세션 (Session) | 토큰 (JWT) |
| 저장 위치 | 서버 메모리 (또는 DB) | 클라이언트 (사용자) |
| 보안성 | 비교적 높음 (탈취돼도 서버에서 지우면 끝) | 탈취되면 만료될 때까지 막기 힘듦 |
| 서버 부하 | 사용자 많으면 메모리 부족 | 서버 부하 거의 없음 (CPU만 씀) |
| 확장성 | 나쁨 (서버 늘리기 힘듦) | 매우 좋음 (MSA, 모바일 환경 적합) |
| 주 사용처 | 전통적인 웹사이트 (관공서, 은행) | 앱(App), 최신 웹(React), 마이크로서비스 |
5. 우리의 목표: 세션 버리고 JWT 적용하기
우리는 지금까지 세션 방식을 썼기 때문에, 브라우저가 아닌 '포스트맨'이나 '모바일 앱'에서 테스트할 때 불편했습니다.
다음 시간부터는 기존 프로젝트를 JWT 기반의 API 서버로 개조(Refactoring) 할 것입니다.
[앞으로 할 일]
build.gradle에 JWT 라이브러리 추가- 토큰을 만들어주는
JwtTokenProvider생성 - 로그인 시 세션 대신 토큰을 발급해주는 로직 구현
- 모든 요청마다 토큰을 검사하는
JwtFilter만들기
6. 잠깐! 우리가 만든 게 진짜 '세션 방식'인지 어떻게 알죠?
백문이 불여일견! 지금까지 만든 프로젝트를 실행하고 직접 눈으로 확인해 봅시다.
🕵️♂️ 검증 1. JSESSIONID 쿠키 확인하기
- 로그인: http://localhost:8080 접속 후 로그인을 완료합니다.
- 개발자 도구: 키보드의 [F12] 키를 눌러 크롬 개발자 도구를 엽니다.
- 쿠키 조회:
- 상단 탭 메뉴 중 [Application] 클릭 (안 보이면 >> 화살표 클릭)
- 왼쪽 메뉴에서 Storage -> Cookies -> http://localhost:8080 클릭
- 확인:
- 이름(Name)이 **JSESSIONID**인 항목이 보이나요?
- 값(Value)에 7F2A... 처럼 알 수 없는 긴 문자열이 들어있습니다.

이게 바로 '입장권'입니다! 서버(Tomcat)는 내 메모리 몇 번지에 여러분의 정보를 저장했는지 기억하고, 그 주소를 찾을 수 있는 **'참조 키(JSESSIONID)'**만 브라우저에게 알려준 것입니다.
🕵️♂️ 검증 2. 쿠키 삭제 테스트
- 개발자 도구에서 JSESSIONID를 우클릭하고 **[Delete]**를 눌러 지워보세요.
- 브라우저를 새로고침(F5) 하세요.
- 로그아웃 되어버렸죠?
- 서버는 멀쩡히 기억하고 있는데, 여러분이 '입장권'을 잃어버려서 서버가 "누구세요?" 하고 쫓아낸 것입니다. 이것이 세션 기반 인증의 증거입니다.
마무리
"세션은 구식이고 JWT가 무조건 좋다?" 아닙니다.
보안이 최우선인 은행 같은 곳은 여전히 세션을 선호하고, 트래픽이 많은 서비스는 JWT를 선호합니다.
하지만 개발자라면 두 방식을 모두 구현할 줄 알아야 합니다.
다음 7편에서는 본격적으로 JWT 라이브러리를 설치하고 유틸리티 클래스를 만들어 보겠습니다.
준비되셨나요? 🚀
'IT > SpringBoot' 카테고리의 다른 글
| [Spring Security] 8편 - SecurityConfig 대수술 (FormLogin 삭제 & JWT 필터 적용) (0) | 2026.02.20 |
|---|---|
| [Spring Security] 7편 - JWT 로그인을 위한 준비 & TokenProvider 만들기 (0) | 2026.02.19 |
| [Spring Security] 5편 - 회원가입 & 비밀번호 암호화 (BCrypt) (0) | 2026.02.18 |
| [Spring Security] 4편 - 로그인 페이지 커스텀 & 로그아웃 처리 (0) | 2026.02.18 |
| [Spring Security] 3편 - 내 DB 정보로 로그인하기 (UserDetailsService) (0) | 2026.02.17 |
