[Spring] 32. Cookie와 Session 차이
이전 글에서는 세션 기반 로그인 처리 흐름을 살펴봤습니다. 로그인 성공 시 서버의 HttpSession에 loginMember를 저장하고, 이후 요청에서 Interceptor가 세션을 확인해 로그인 여부를 판단했습니다.
이번 글에서는 세션 기반 로그인을 이해할 때 꼭 알아야 하는 Cookie와 Session의 차이를 정리하겠습니다. 로그인 상태가 어떻게 유지되는지 이해하려면 쿠키와 세션의 관계를 함께 봐야 합니다.
핵심은 간단합니다. 쿠키는 브라우저에 저장되고, 세션은 서버에 저장됩니다. 브라우저는 쿠키에 담긴 세션 ID를 서버로 보내고, 서버는 그 세션 ID를 이용해 사용자의 세션 정보를 찾습니다.
1. HTTP는 기본적으로 상태를 기억하지 않는다
웹에서 브라우저와 서버는 HTTP 요청과 응답으로 통신합니다. 그런데 HTTP는 기본적으로 이전 요청의 상태를 기억하지 않습니다. 이것을 무상태, 즉 Stateless라고 합니다.
첫 번째 요청
→ 로그인 요청
두 번째 요청
→ 마이페이지 요청
HTTP만 보면 서버는 두 요청이 같은 사용자인지 바로 알기 어렵다.
사용자가 로그인한 뒤 마이페이지에 접근하려면 서버가 “이 사용자는 이미 로그인했다”는 상태를 알아야 합니다. 이 상태를 유지하기 위해 쿠키와 세션을 사용합니다.
2. Cookie란?
Cookie는 브라우저에 저장되는 작은 데이터입니다. 서버가 응답할 때 쿠키를 내려주면, 브라우저는 그 쿠키를 저장해두었다가 이후 같은 사이트에 요청을 보낼 때 쿠키를 함께 보냅니다.
서버 응답
→ Set-Cookie로 쿠키 전달
브라우저
→ 쿠키 저장
다음 요청
→ Cookie를 함께 전송
쿠키는 브라우저에 저장되므로 사용자 쪽에 있는 정보입니다. 그래서 민감한 정보를 그대로 저장하는 것은 좋지 않습니다.
| 저장 위치 | 브라우저 |
| 주 사용 목적 | 세션 ID 저장, 자동 로그인 토큰, 사용자 설정값 저장 등 |
| 주의점 | 브라우저에 저장되므로 민감한 정보는 직접 저장하지 않는 것이 좋습니다. |
3. Session이란?
Session은 서버가 사용자별 상태 정보를 저장하는 공간입니다. 로그인 사용자 정보, 장바구니 임시 정보, 인증 상태 같은 값을 저장할 수 있습니다.
session.setAttribute("loginMember", loginMember);
위 코드는 로그인 성공 후 세션에 loginMember라는 이름으로 로그인 사용자 정보를 저장하는 예시입니다.
세션은 서버에 저장됩니다. 브라우저에는 세션 데이터 전체가 저장되는 것이 아니라, 서버가 세션을 찾기 위한 세션 ID가 쿠키로 저장됩니다.
서버 세션 저장소
├─ 세션 ID: A123
│ └─ loginMember = 건우
├─ 세션 ID: B456
│ └─ loginMember = 다른 사용자
4. Cookie와 Session의 관계
쿠키와 세션은 따로 떨어진 개념이 아닙니다. 세션 기반 로그인에서는 쿠키가 세션을 찾는 열쇠 역할을 합니다.
로그인 성공
→ 서버가 Session 생성
→ Session ID 발급
→ 브라우저에 JSESSIONID 쿠키 저장
→ 다음 요청부터 JSESSIONID 쿠키 전송
→ 서버가 Session ID로 세션 정보 조회
즉, 로그인 정보 자체는 서버 세션에 있고, 브라우저는 그 세션을 찾기 위한 ID만 쿠키로 가지고 있습니다.
| Cookie | 브라우저가 들고 있는 세션 ID 저장소 역할 |
| Session | 서버가 들고 있는 로그인 사용자 정보 저장소 역할 |
5. JSESSIONID란?
Spring MVC와 Servlet 기반 웹 애플리케이션에서 세션을 사용하면 브라우저에 JSESSIONID라는 쿠키가 저장될 수 있습니다.
Cookie: JSESSIONID=ABCDEF1234567890
JSESSIONID는 서버의 세션을 찾기 위한 ID입니다. 브라우저는 이후 요청마다 이 쿠키를 함께 보내고, 서버는 이 값을 보고 어떤 세션인지 찾습니다.
브라우저 요청
→ JSESSIONID 쿠키 포함
서버
→ JSESSIONID 값 확인
→ 해당 세션 찾기
→ loginMember 확인
그래서 세션 기반 로그인에서 쿠키를 삭제하면 로그인 상태가 풀릴 수 있습니다. 브라우저가 세션 ID를 더 이상 보내지 못하기 때문입니다.
6. 로그인 성공 시 흐름
로그인 성공 시 쿠키와 세션은 다음 흐름으로 연결됩니다.
1. 사용자가 아이디와 비밀번호를 입력한다.
2. 서버가 회원 정보를 확인한다.
3. 로그인 성공 시 HttpSession을 생성하거나 기존 세션을 사용한다.
4. 서버 세션에 loginMember를 저장한다.
5. 서버가 세션 ID를 브라우저 쿠키로 전달한다.
6. 브라우저는 JSESSIONID 쿠키를 저장한다.
7. 이후 요청마다 JSESSIONID 쿠키를 함께 보낸다.
8. 서버는 JSESSIONID로 세션을 찾아 로그인 상태를 확인한다.
Controller 코드로 보면 다음처럼 세션에 로그인 정보를 저장합니다.
@PostMapping("/login")
public String login(
MemberLoginDto memberLoginDto,
HttpSession session,
Model model
) {
LoginMember loginMember = memberService.login(memberLoginDto);
if (loginMember == null) {
model.addAttribute("loginError", "아이디 또는 비밀번호가 올바르지 않습니다.");
return "member/login";
}
session.setAttribute("loginMember", loginMember);
return "redirect:/";
}
이때 서버는 세션을 만들고, 브라우저는 세션 ID 쿠키를 받아 이후 요청에 사용합니다.
7. 이후 요청에서 로그인 상태 확인하기
로그인 이후 사용자가 마이페이지에 접근한다고 생각해보겠습니다. 브라우저는 요청을 보낼 때 JSESSIONID 쿠키를 함께 보냅니다.
GET /mypage
Cookie: JSESSIONID=ABCDEF1234567890
서버는 이 세션 ID로 세션을 찾고, 세션 안에 loginMember가 있는지 확인합니다.
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("loginMember") == null) {
response.sendRedirect("/member/login");
return false;
}
return true;
이 코드는 Interceptor에서 로그인 체크를 할 때 자주 사용하는 구조입니다.
JSESSIONID 있음
→ 서버가 세션 찾음
→ loginMember 있음
→ 로그인 상태
JSESSIONID 없음 또는 세션 없음
→ 로그인하지 않은 상태
8. Cookie와 Session 차이 한눈에 보기
| 구분 | Cookie | Session |
| 저장 위치 | 브라우저 | 서버 |
| 저장 데이터 | 작은 문자열 데이터 | 사용자별 상태 정보 |
| 로그인에서 역할 | 세션 ID를 저장합니다. | 로그인 사용자 정보를 저장합니다. |
| 보안 | 브라우저에 있으므로 민감 정보 직접 저장은 위험합니다. | 서버에 저장되어 상대적으로 안전하지만 관리가 필요합니다. |
| 예시 | JSESSIONID, 자동 로그인 토큰 |
loginMember, 사용자 권한 정보 |
9. 쿠키 직접 생성하기
Spring MVC에서는 직접 쿠키를 만들어 응답에 추가할 수도 있습니다. 예를 들어 사용자가 선택한 테마를 쿠키에 저장한다고 생각해보겠습니다.
@GetMapping("/theme/dark")
public String darkTheme(HttpServletResponse response) {
Cookie cookie = new Cookie("theme", "dark");
cookie.setMaxAge(60 * 60 * 24 * 7);
cookie.setPath("/");
response.addCookie(cookie);
return "redirect:/";
}
위 코드는 theme=dark라는 쿠키를 만들고, 7일 동안 유지되도록 설정합니다.
new Cookie("theme", "dark") |
쿠키 이름과 값을 설정합니다. |
setMaxAge() |
쿠키 유지 시간을 초 단위로 설정합니다. |
setPath("/") |
쿠키가 적용될 경로를 설정합니다. |
addCookie() |
응답에 쿠키를 추가합니다. |
10. 쿠키 읽기
요청에 포함된 쿠키를 읽으려면 @CookieValue를 사용할 수 있습니다.
@GetMapping("/theme")
@ResponseBody
public String theme(
@CookieValue(value = "theme", required = false) String theme
) {
return "현재 테마: " + theme;
}
브라우저가 theme=dark 쿠키를 보내면 theme 변수에 dark 값이 들어갑니다. 쿠키가 없을 수도 있으므로 required = false를 사용할 수 있습니다.
Cookie: theme=dark
→ @CookieValue("theme")
→ theme = "dark"
11. 쿠키 삭제하기
쿠키를 삭제하려면 같은 이름의 쿠키를 만들고 MaxAge를 0으로 설정한 뒤 응답에 추가합니다.
@GetMapping("/theme/delete")
public String deleteTheme(HttpServletResponse response) {
Cookie cookie = new Cookie("theme", null);
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
return "redirect:/";
}
쿠키는 브라우저에 저장되어 있기 때문에 서버가 삭제 명령을 응답으로 보내는 방식으로 제거합니다.
쿠키 삭제
→ 같은 이름
→ 같은 path
→ maxAge = 0
12. Session은 어떻게 삭제할까?
세션은 서버에 저장된 사용자 상태 정보입니다. 로그아웃할 때는 세션을 무효화해서 로그인 상태를 제거합니다.
@PostMapping("/logout")
public String logout(HttpSession session) {
session.invalidate();
return "redirect:/";
}
session.invalidate()를 호출하면 해당 세션이 무효화됩니다. 이후 같은 세션 ID로 요청해도 기존 로그인 정보는 사용할 수 없습니다.
로그아웃
→ session.invalidate()
→ 서버 세션 제거
→ loginMember 제거
→ 로그인 상태 해제
13. 쿠키에 로그인 정보를 직접 저장하면 안 되는 이유
쿠키는 브라우저에 저장됩니다. 그래서 로그인 사용자 정보를 쿠키에 그대로 저장하는 것은 위험합니다.
위험한 예시
Cookie: memberId=springUser
Cookie: memberPw=1234
Cookie: role=ADMIN
이런 정보는 사용자가 볼 수 있고, 조작될 위험도 있습니다. 따라서 쿠키에는 민감 정보를 직접 저장하지 않는 것이 좋습니다.
세션 기반 로그인에서는 브라우저 쿠키에 로그인 정보 자체를 저장하지 않고, 세션 ID만 저장합니다. 실제 로그인 정보는 서버 세션에 저장합니다.
브라우저 쿠키
→ JSESSIONID만 보관
서버 세션
→ loginMember 보관
14. 자동 로그인은 쿠키일까 세션일까?
자동 로그인 기능은 보통 쿠키를 활용합니다. 브라우저를 닫았다가 다시 열어도 로그인 상태를 유지하려면, 일정 기간 유지되는 식별 정보를 브라우저에 저장해야 하기 때문입니다.
하지만 자동 로그인 쿠키에 아이디와 비밀번호를 그대로 저장하면 안 됩니다. 보통은 무작위 토큰을 만들어 쿠키에 저장하고, 서버 DB에는 그 토큰과 사용자 정보를 연결해 저장합니다.
자동 로그인 흐름 예시
1. 로그인 성공
2. 자동 로그인 선택 확인
3. 서버가 랜덤 토큰 생성
4. 토큰을 DB에 저장
5. 브라우저 쿠키에도 토큰 저장
6. 다음 방문 시 쿠키 토큰을 서버로 전송
7. 서버가 DB에서 토큰 확인
8. 유효하면 로그인 처리
즉, 자동 로그인은 쿠키를 사용하지만, 쿠키에는 비밀번호가 아니라 검증 가능한 토큰을 저장하는 구조가 일반적입니다.
15. 자주 하는 실수
1) 쿠키에 비밀번호를 저장하는 경우
쿠키는 브라우저에 저장되므로 비밀번호 같은 민감한 값을 저장하면 안 됩니다.
쿠키에 저장하면 안 되는 값
→ 비밀번호
→ 주민번호
→ 카드번호
→ 권한을 그대로 믿어야 하는 값
2) 세션과 쿠키를 완전히 별개로 이해하는 경우
세션 기반 로그인에서 쿠키와 세션은 연결되어 있습니다. 브라우저의 쿠키에 담긴 세션 ID가 있어야 서버가 세션을 찾을 수 있습니다.
쿠키
→ 세션 ID 전달
세션
→ 서버에서 로그인 정보 저장
3) 로그아웃할 때 세션을 제거하지 않는 경우
로그아웃은 단순히 화면만 바꾸는 것이 아니라 서버의 로그인 상태를 제거해야 합니다.
session.invalidate();
4) 쿠키 삭제 시 path를 다르게 설정하는 경우
쿠키를 삭제할 때는 생성할 때와 같은 path를 사용하는 것이 중요합니다. path가 다르면 기존 쿠키가 삭제되지 않을 수 있습니다.
Cookie cookie = new Cookie("theme", null);
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
5) 세션에 너무 많은 정보를 저장하는 경우
세션은 서버 메모리나 저장소를 사용합니다. 불필요하게 많은 데이터를 세션에 저장하면 서버 부담이 커질 수 있습니다.
세션에는 필요한 최소 정보만 저장
예:
memberNo
memberId
memberName
role
16. 전체 흐름 정리
쿠키와 세션을 이용한 로그인 유지 흐름을 다시 정리하면 다음과 같습니다.
1. 사용자가 로그인 요청을 보낸다.
2. 서버가 아이디와 비밀번호를 확인한다.
3. 로그인 성공 시 서버에 Session을 생성한다.
4. Session 안에 loginMember를 저장한다.
5. 서버가 브라우저에 JSESSIONID 쿠키를 내려준다.
6. 브라우저는 JSESSIONID 쿠키를 저장한다.
7. 이후 요청마다 JSESSIONID 쿠키를 함께 보낸다.
8. 서버는 JSESSIONID로 세션을 찾는다.
9. 세션에 loginMember가 있으면 로그인 상태로 판단한다.
10. 로그아웃 시 session.invalidate()로 세션을 제거한다.
정리
Cookie는 브라우저에 저장되는 작은 데이터입니다. Session은 서버에 저장되는 사용자별 상태 정보입니다. 세션 기반 로그인에서는 브라우저 쿠키에 JSESSIONID가 저장되고, 서버는 이 세션 ID로 세션 저장소에서 로그인 사용자 정보를 찾습니다.
| Cookie | 브라우저에 저장됩니다. 세션 ID나 사용자 설정값 저장에 사용됩니다. |
| Session | 서버에 저장됩니다. 로그인 사용자 정보 같은 상태를 저장합니다. |
| JSESSIONID | 서버 세션을 찾기 위한 세션 ID 쿠키입니다. |
| HttpSession | 서버에서 세션 데이터를 다룰 때 사용하는 객체입니다. |
처음에는 다음 기준으로 기억하면 좋습니다.
Cookie
→ 브라우저 저장
→ 요청마다 서버로 전송
→ 세션 ID 저장에 사용
Session
→ 서버 저장
→ 사용자별 상태 정보 저장
→ loginMember 저장에 사용
로그인 유지
→ Cookie의 JSESSIONID로 서버 Session을 찾는다.
연습해보기
아래 상황에서 Cookie와 Session 중 어디에 저장하는 것이 적절한지 생각해보세요.
| 상황 | 추천 |
| 로그인 사용자 정보 | Session |
| 세션 ID | Cookie |
| 다크모드 설정 | Cookie 또는 DB |
| 비밀번호 | Cookie와 Session 모두 직접 저장하지 않는 것이 좋음 |
| 자동 로그인 토큰 | Cookie + 서버 DB 검증 |
다음 글에서는 세션 기반 로그인에서 한 단계 더 나아가 자동 로그인과 Remember-Me 구조를 정리하겠습니다. 쿠키를 이용해 브라우저를 닫았다가 다시 들어와도 로그인 상태를 복원하는 흐름입니다.

'Tech Stack > Spring Boot' 카테고리의 다른 글
| [Spring] 33. 자동 로그인과 Remember-Me 구조 (0) | 2026.07.26 |
|---|---|
| [Spring] 31. 세션 기반 로그인 처리 흐름 (0) | 2026.07.24 |
| [Spring] 30. Filter와 Interceptor 차이 (0) | 2026.07.23 |
| [Spring] 29. Interceptor란? (0) | 2026.07.22 |
| [Spring] 28. 업로드한 파일 조회와 다운로드 처리하기 (0) | 2026.07.21 |