요즘 jwt를 공부중인데 그 전에 쿠키와 세션에 대해 어느 정도 체계를 잡고 넘어가고 싶어서 정리한다.
웹은 왜 기억을 못할까?
우리가 웹 사이트를 방문하면 거기서 다양한 활동들을 한다.
로그인을 하거나 장바구니에 상품을 담거나 하면서 로그인 되어있는 상태에서 각 활동을 수행한다.
근데 사실 웹 자체는 이런 걸 기억하지 못한다.
왜냐하면 웹 통신의 기본 프로토콜인 HTTP는 Stateless(무상태) 프로토콜이기 때문이다.
무상태란? -> 서버는 요청이 올 때마다 누군지, 뭘 했는지에 대한 기억이 없이 새로 처리한다는 의미이다.
매번 처음 보는 손님처럼 대한다고 생각하면 된다.
쿼리 파라미터를 계속 유지하면서 보내는 건 어렵고 번거로운 작업이기 때문에 쿠키와 세션을 사용하는 것이 좋다.
쿠키
쿠키는 서버가 사용자의 브라우저에 저장하는 작은 데이터 조각이다.
사용자가 다시 서버에 요청을 보낼 때, 브라우저는 저장된 쿠키를 자동으로 함께 전송한다.
쉽게 생각하면 웹 사이트가 나한테 주는 메모지라고 생각하자.
-> 메모지를 주면서 "다음에 올 때 이거 들고 와!" 하는 것.
쿠키의 특징
- 클라이언트에 저장된다(민감한 정보는 저장하지 말자. 사용자가 맘대로 조작할 수 있기 때문)
- 저장 공간이 4KB 정도로 작다.
- 사용자가 직접 쿠키를 볼 수 있고 수정하고 삭제도 가능하다.
- 만료 시간을 지정할 수 있다 (Expires, Max-Age).
- 보안에 취약할 수 있으므로 민감 정보는 저장하면 안된다.
쿠키의 흐름
1. 서버가 응답할 때, Set-Cookie 헤더에 쿠키 정보를 담아 보낸다.
2. 브라우저는 쿠키를 저장한다.
3. 다음 요청부터 쿠키를 자동으로 함께 전송한다.
->브라우저가 알아서 쿠키를 서버로 들고 가는 구조.
예시
Set-Cookie: userId=abc123; Max-Age=3600; Path=/; HttpOnly
- userId=abc123: 저장할 데이터
- Max-Age=3600: 1시간 후 만료
- Path=/: 전체 경로에 적용
- HttpOnly: 자바스크립트로 접근 못 하게 막음 (보안 강화)
쿠키를 사용하면 서버 부담 없이 상태 유지가 가능하고 사용이 간단하다는 장점이 있지만 클라이언트에 노출되어서 보안이 취약하고 저장 용량이 작다는 단점이 있다.
쿠키 예제
//쿠키에 시간 정보를 주지 않으면 세션 쿠키(브라우저 종료시 모두 종료)
Cookie idCookie = new Cookie("memberId", String.valueOf(loginMember.getId()));
response.addCookie(idCookie);
return "redirect:/";
Cookie idCookie = new Cookie("memberId", String.valueOf(loginMember.getId()));
response.addCookie(idCookie);
이건 생성 로직인데, 로그인에 성공하면 쿠키를 생성하고 HttpServlet에 담는다.
쿠키 이름은 memberId로 짓고 값은 회원의 id를 담아주면 된다.
이제 로그인 컨트롤러에서 로그인 서비스를 호출해서 로그인에 성공하면 로그인 성공 페이지로 이동하고 로그인에 실패하면 bindingResult.reject()를 사용해서 ObjectError를 생성하면 된다. 그리고 정보를 다시 입력하도록 로그인 폼으로 이동시킨다.
웹 브라우저는 종료 전까지 회원의 id를 서버에 계속 보내준다.
@GetMapping("/set-cookie")
public String setCookie(HttpServletResponse response) {
Cookie cookie = new Cookie("userName", "sungmin");
cookie.setMaxAge(3600); // 1시간
cookie.setHttpOnly(true); // JavaScript 접근 금지
cookie.setPath("/");
response.addCookie(cookie);
return "쿠키 저장 완료!";
}
이렇게 쿠키를 설정해서 1시간 동안 유지되도록 할 수 있다.
완전히 종료를 하려면 여러 멀티탭이 켜져있으면 안되고 탭 자체를 다 닫아줘야 한다.
세션
세션은 서버 쪽에서 사용자의 정보를 저장하는 방법이다.
클라이언트는 단지 내가 누군지 식별할 수 있는 세션 ID만 쿠키에 저장하면 된다.
비유를 들자면 에버랜드 자유이용권 팔찌를 생각해보자.
-> 입장할 때 팔찌를 차면 에버랜드 직원은 그 팔찌만 보고 "아 이 사람 입장했네"라고 알아차린다.
여기서의 팔찌는 세션 id라서 가볍지만 실제 중요한 정보(입장권, 탑승 기록 등)는 서버가 보관한다.
세션의 특징
- 서버에 저장되므로 보안이 강하다.
- 서버 메모리를 사용하므로 자원이 소모된다.
- 일정 시간 사용하지 않으면 자동으로 만료된다.
세션 흐름
1. 사용자가 서버에 최초 요청 → 서버가 새로운 세션 ID를 생성.
2. 서버는 세션 저장소에 사용자 정보를 저장하고, 클라이언트에게 세션 ID를 쿠키로 전달.
3. 클라이언트는 이후 요청마다 세션 ID를 같이 보냄.
4. 서버는 세션 ID로 사용자 정보를 찾아서 사용.
쿠키에 중요한 정보를 보관하는 방법은 보안 이슈가 있으므로 결국 중요한 정보를 모두 서버에 저장해야 한다.
그리고 클라이언트와 서버는 추정 불가능한 임의의 식별자 값으로 연결해야 한다.
이렇게 서버에 중요한 정보를 보관하고 연결을 유지하는 방법을 세션이라고 하는 것이다.
스프링은 세션을 편리하게 사용할 수 있도록 @SessionAttribute를 지원한다.
@SessionAttribute(name = "loginMember", required = false) Member loginMember
세션 예제 - @SessionAttribute를 통한 세션 조
@GetMapping("/")
public String homeLoginV3Spring(
@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember,
Model model) {
// 세션에 회원 데이터가 없으면 home
if (loginMember == null) {
return "home";
}
// 세션이 유지되면 로그인으로 이동
model.addAttribute("member", loginMember);
return "loginHome";
}
김영한 강사님의 코드이다.
세션을 찾고, 세션에 들어있는 데이터를 찾는 번거로운 과정을 스프링이 한 번에 편리하게 처리해준다.
HttpSession을 통한 세션 저장
@PostMapping("/set-session")
public String setSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute("loginUser", "sungmin123");
session.setMaxInactiveInterval(1800); // 30분 유지
return "세션 저장 완료!";
}
-> 서버에 sungmin123 사용자의 세션 정보가 30분 동안 저장된다.
주의 사항
쿠키와 세션은 서로 보완하는 관계이다.
쿠키를 이용해 자동 로그인 여부를 기억하고 세션을 이용해 현재 로그인 상태를 관리한다.
- 쿠키에는 절대 비밀번호나 민감 정보를 저장하지 말 것
- 쿠키 생성 시 반드시 HttpOnly, Secure 옵션 설정
- 세션은 오래 유지하지 않고 적절한 타임아웃 설정
- 항상 HTTPS를 사용해 쿠키와 세션ID를 안전하게 주고받을 것
다음엔 jwt를 더 공부해서 포스팅해보겠다.
'Backend > Spring Boot' 카테고리의 다른 글
API 예외처리: @ExceptionHandler (0) | 2025.05.21 |
---|---|
@RequestParam에서 400 BadRequest가 발생하는 이유 (1) | 2025.05.20 |
HTTP 응답 처리 방법의 발전 (0) | 2025.03.28 |
스프링 부트 계층형 아키텍처 (0) | 2025.03.27 |
빈이 존재하는 범위를 이해하자 (0) | 2025.02.19 |