1. 쿠키 (Cookie)
쿠키란?
쿠키는 사용자의 브라우저에 저장되는 데이터입니다. 웹사이트는 쿠키를 사용해 사용자가 이전에 방문했을 때의 정보를 유지할 수 있습니다.
장단점
- 장점
- 상태 유지: 사용자가 웹 사이트를 다시 방문할 때 이전 상태를 유지할 수 있습니다.
- 간편한 구현: 브라우저에서 쿠키를 관리하기 때문에 서버 측에서 쿠키를 지정하기만 하면 되어 간단합니다.
- 클라이언트에 저장: 서버 자원을 절약할 수 있습니다.
- 단점
- 보안: 쿠키는 클라이언트 측에 저장되므로 민감한 정보를 암호화하지 않으면 보안 취약점이 생길 수 있습니다.
- 저장 용량 제한: 각 쿠키의 크기는 4KB로 제한되며, 브라우저 당 저장 가능한 쿠키 수에도 제한이 있습니다.
- 브라우저 종속적: 브라우저 설정에 따라 쿠키 사용이 제한될 수 있습니다.
사용방법
서버에서 브라우저로 응답하는 HTTP 메시지 헤더에 Set-Cookie를 지정하면, 브라우저는 다음 요청부터 자동으로 HTTP 메시지 헤더에 쿠키를 포함시킵니다.
Spring MVC에서 쿠키를 지정하려면 HttpServletResponse의 addCookie()를 호출하면 됩니다.
@GetMapping("/set-cookie")
public String setCookie(HttpServletResponse response) {
Cookie cookie = new Cookie("username", "JohnDoe");
cookie.setMaxAge(3600);
cookie.setHttpOnly(true);
cookie.setPath("/");
response.addCookie(cookie); // 서버 응답 Response에 쿠키를 추가한다.
return "Cookie set";
}
클라이언트가 요청 헤더에 담은 쿠키를 읽으려면 HttpServletRequest의 getCookies()를 호출하면 됩니다.
@GetMapping("/get-cookie")
public String getCookie(HttpServletRequest request) {
Cookie[] cookies = request.getCookies(); // 클라이언트 요청 Request에서 쿠키를 읽는다.
if(cookies != null)
for(Cookie cookie : cookies)
if(cookie.getName().equals("username"))
return "Username: " + cookie.getValue();
return "No cookie found";
}
2. 세션 (Session)
세션이란?
세션은 서버 측에서 관리되는 사용자의 데이터입니다. 사용자가 웹 사이트에 접속하면 서버는 고유한 세션 ID를 생성하고, 이를 통해 해당 사용자의 데이터를 관리합니다. 세션 ID는 보통 쿠키에 담겨 클라이언트에 전달됩니다.
장단점
- 장점
- 상태 유지: 서버는 사용자 상태 저장을 통해 사용자가 웹 사이트를 다시 방문할 때 데이터를 유지할 수 있습니다.
- 보안: 예측 불가능한 임의의 세션 ID를 주고 받기 때문에, 세션 ID 자체로부터 정보 유출이 없습니다. 중요한 정보는 서버에 저장되므로, 클라이언트는 민감 정보에 접근할 수 없습니다.
- 단점
- 다음과 같은 문제들이 발생할 수 있습니다.
- 세션 하이재킹: 공격자가 사용자의 세션 ID를 도용해 사용자로 가장할 수 있음.
- 세션 고정: 공격자가 특정 세션 ID를 고정해 해당 세션 ID를 계속해서 사용할 수 있음.
- 세션 만료: 사용자가 작업 중 세션이 만료되면 불편을 겪을 수 있음.
- 서버 자원소모: 많은 사용자가 접속하면 서버 메모리 사용량이 증가할 수 있음.
- 확장성 문제: 서버가 여러 대인 경우 세션을 특정 서버에만 저장하면 로드 밸런싱, 확장이 어려워 질 수 있음.
- CSRF: 공격자가 사용자의 세션을 이용해 사용자 몰래 악의적인 요청을 전송할 수 있음.
- 다음과 같은 문제들이 발생할 수 있습니다.
사용방법
서버에서 브라우저로 응답하는 HTTP 메시지 헤더에 Set-Cookie로 세션 아이디를 담아 응답합니다.
Spring MVC에서 세션을 지정하려면 HttpSession 또는 HttpServletRequest의 getSession()을 호출하면 됩니다.
@GetMapping("/set-session")
public String setSession(HttpSession session) {
session.setAttribute("username", "JohnDoe");
return "Session set";
}
@GetMapping("/set-session")
public String setSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute("username", "JohnDoe");
return "Session set";
}
세션을 읽을 때도 마찬가지로 HttpSession을 컨트롤러 핸들러 메서드의 매개변수로 주입 받거나, HttpServletRequest의 getSession()을 호출하면 됩니다.
@GetMapping("/get-session")
public String getSession(HttpSession session) {
String username = (String) session.getAttribute("username");
if(username != null)
return "Username: " + username;
return "No session found";
}
@GetMapping("/get-session")
public String getSession(HttpServletRequest request) {
HttpSession session = request.getSession(false);
String username = (String) session.getAttribute("username");
if(username != null)
return "Username: " + username;
return "No session found";
}
HttpSession과 HttpServletRequest의 getSession() 또는 getSession(true)는 JSESSIONID에 해당하는 세션이 없을 경우, 새롭게 세션을 생성해 반환합니다.
반면 HttpServletRequest의 getSession(false)는 JSESSIONID에 해당하는 세션이 없을 경우, null을 반환합니다.
이렇듯 HttpServletRequest를 사용하면 HttpSession 보다 좀 더 세밀한 세션 관리를 할 수 있습니다.