쿠키와 세션에 대한 설명
쿠키(Cookie)
쿠키는 사용자가 인터넷을 사용할 때 생성되는 작은 텍스트 파일이다. 웹사이트에서는 서버에서 쿠키를 생성하여 사용자의 웹 브라우저에 저장하게 된다. 이후, 같은 웹사이트를 방문할 때마다 브라우저는 이 쿠키를 서버에 전송하게 되며, 서버는 이를 통해 사용자의 정보를 인식하고 다양한 기능을 제공할 수 있다. 예를 들어, 로그인 정보나 쇼핑몰에서 장바구니에 담은 상품 등을 저장할 때 사용한다.
세션(Session)
웹사이트에서 세션이란, 사용자가 로그인을 하여 웹사이트와 상호작용하는 동안 유지되는 일시적인 상태 정보를 말한다. 즉, 사용자가 로그인을 하면 서버에서는 해당 사용자에 대한 세션을 생성하며, 이후에는 이 세션을 통해 사용자를 인증하고, 사용자의 정보를 저장하고 관리한다. 이때, 쿠키와 달리 브라우저에 저장되는 것이 아니라, 서버에서 관리되는 것이다. 세션은 보안성이 높아서, 로그인 정보나 사용자의 민감한 정보를 다룰 때 사용된다.
왜 세션을 사용하는것일까?
HTTP 프로토콜은 클라이언트와 서버 간의 연결을 유지하지 않습니다. 이를 "stateless"라고 합니다. 이는 클라이언트가 서버에 요청을 보낼 때마다 새로운 연결이 만들어지고, 응답을 받으면 연결이 끊어지기 때문에, 클라이언트와 서버 간에 상태 정보를 유지할 수 없습니다.
하지만 웹 애플리케이션은 종종 클라이언트와 서버 간의 상태 정보를 유지해야 하는 경우가 있습니다. 예를 들어 로그인한 사용자가 페이지를 이동하거나 다른 요청을 보낼 때, 이전에 로그인한 사용자인지를 확인하기 위해 상태 정보를 유지해야 합니다. 이때 사용되는 것이 세션(Session)입니다.
스프링부트 서버는 어떻게 사용자 정보를 유지하는 것일까?
@RestController
public class SessionController {
@RequestMapping("/addSessionAttribute")
public String addSessionAttribute(HttpSession session) {
session.setAttribute("sessionAttribute", "Hello, Session!"); // 세션에 속성 추가
return "Session Attribute Added Successfully!";
}
@RequestMapping("/getSessionAttribute")
public String getSessionAttribute(HttpSession session) {
String sessionAttribute = (String) session.getAttribute("sessionAttribute"); // 세션에서 속성 가져오기
return "Session Attribute: " + sessionAttribute;
}
}
위에 코드는 클라이언트의 요청을 받을 수 있는 컨트롤러 코드입니다.
HttpSession이라는 인터페이스를 통해 세션을 다룰 수 있습니다. 그러면 이 HttpSession은 어떻게 만들어질까요? 우선 HttpSession은 인터페이스 이므로 HttpSession을 구현하는 객체들을 찾아보겠습니다.
IntelliJ를 통해 HttpSession을 상속받는 객체를 찾아보면 구현체 StandardSession를 찾아볼 수 있습니다.
우리가 세션에서 속성을 갖고 올 때 사용하는 getAttrubute() 메서드가 실행되는 구현체 StandardSession를 살펴보면 세션의 식별자 id를 멤버 변수(Session Id)로 갖고 있고 getAttribute() 메서드를 통해 attributes Map에서 속성 name을 통해 값을 반환하는 걸 볼 수 있습니다.
/**
* The session identifier of this Session.
*/
protected String id = null;
//The collection of user data attributes associated with this Session.
protected ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>();
@Override
public Object getAttribute(String name) {
if (!isValidInternal()) {
throw new IllegalStateException
(sm.getString("standardSession.getAttribute.ise"));
}
if (name == null) {
return null;
}
return attributes.get(name);
}
그러면 우리는 클라이언트 요청이 들어오면 세션 ID를 생성하고 세션 ID와 속성 저장소를 갖는 StandardSession가 생성된다는 거 까지 찾아봤습니다.
그러면 서버에는 많은 클라이언트들의 요청이 들어오는데 저장소를 어떻게 세션 ID별로 보관하는 걸까요?
다시 IntelliJ를 통해 StandardSession이 많이 사용되는 StandardManager 클래스를 찾을 수 있었습니다.
StandardManager를 살펴보면 ManagerBase 추상 클래스를 다시 상속받고 있습니다.
public class StandardManager extends ManagerBase
public abstract class ManagerBase extends LifecycleMBeanBase implements Manager {
protected Map<String, Session> sessions = new ConcurrentHashMap<>();
@Override
public Session findSession(String id) throws IOException {
if (id == null) {
return null;
}
return sessions.get(id);
}
}
ManagerBase 클래스는 Session Id를 키 로하고 세션을 벨류로 하는 Map을 멤버 변수로 포함하고 있고 Session Id를 통해 Session을 반환하는 메서드를 갖고 있는 걸 확인할 수 있습니다.
정리
- 클라이언트가 서버에 요청을 보내면, 서버는 세션 ID를 생성합니다.
- 생성된 세션 ID를 변수로 갖는 새로운 StandardSession 객체를 생성합니다.
- 생성된 StandardSession 객체는 StandardManager 객체에 등록됩니다. 이때, StandardManager는 StandardSession 객체를 세션 ID와 매핑하여 Map 형태로 저장합니다.
- 생성된 StandardSession 객체는 클라이언트에게 반환되고, 클라이언트는 이후 요청에서 세션 ID를 쿠키나 URL 매개변수를 통해 전송합니다.
- 클라이언트의 다음 요청에서, 서버는 클라이언트가 전송한 세션 ID를 확인합니다.
- StandardManager는 해당 세션 ID에 매핑된 StandardSession 객체를 찾아서 반환합니다.
- 반환된 StandardSession 객체는 해당 요청의 컨트롤러에 전달되어 세션 데이터를 읽거나 쓰는 작업을 수행합니다.
기본적으로 세션은 서버 메모리를 사용하기 때문에 분산서버 환경에서는 문제가 발생할 수 있습니다. 이 문제에 대해서는 다음에 다뤄보겠습니다.
'BE > Spring' 카테고리의 다른 글
Spring Data Jpa 쿼리 메서드 살펴보기 (0) | 2023.04.27 |
---|---|
[JPA] 객체지향 쿼리 언어 (0) | 2023.03.20 |
@RequestBody와 @ModelAttribute (0) | 2023.01.26 |
- 스프링부트의 뷰 반환 과정을 알아보자 (0) | 2023.01.04 |
[Spring] Cause: error: invalid source release: 17 해결방법 (0) | 2022.10.24 |