HTTP 요청에는 상태가 없다.
이때 사용자의 브라우저에 응답을 보내면서, 브라우저에 특정 데이터를 저장하도록 전달할 수 있다. 이때 서버에서 작성해서 응답을 받은 브라우저가 저장하는 데이터를 쿠키라고 부른다.

서버는 응답을 보내면서 쿠키에 요청을 보낸 브라우저를 특정지을 값을 보내줄 수 있다. 이후 사용자가 요청을 보낼 때, 해당 값을 보내주면 서버에서 저장 해놓은 정보를 기반으로 브라우저에 로그인한 사용자가 누구인지를 구분할 수 있게 된다.
상태를 저장하지 않는 HTTP 통신을 사용하면서, 이전에 요청을 보낸 사용자를 기억하는 상태를 유지하는 것을 세션이라고 부른다.
Spring Boot를 사용하면, Spring Boot 프로젝트에 내장되어 있는 Tomcat 서버가 세션을 생성. 이때, 이 세션을 확인하고 싶다면, Chrome의 개발자 모드로 들어가, Application > Storage > Cookie를 확인
HttpSession 객체로 만든다. 그리고 Spring Boot의 컨트롤러 메서드에서 해당 HttpSession을 가져와 사용할 수 있다.@RestController
public class SessionController {
@GetMapping("/set")
public String set(
@RequestParam("q")
String q,
HttpSession session
) {
session.setAttribute("q", q);
return "Saved: " + q;
}
@GetMapping("/get")
public String get(
HttpSession session
) {
return String.valueOf(session.getAttribute("q"));
}
}
이런 식으로 사용되는 건 몇 번 해봐서 알긴 안다만
만약, 사용자가 늘어서 하나의 서버로는 사용자의 요청을 감당하기 어려워지면??
한 가지 대안은 똑같은 기능을 하는 Spring Boot 서버를 여러 개 사용하는 것(Scale-Out)
여러 서버가 동작한다면, 각 서버들에게 요청을 분산하여 부하를 줄일 수 있다. (Load Balancing)
💡한 pc에서 여러 개의 서버를 돌리는 법
원래 알던 건 module로 만들어서 수행하는 법이었다.
강의에서 제공하는 내용은 다음과 같다.
Edit Configurations를 찾을 수 있습니다.
구분하기 쉽게 이 설정의 이름을 바꾸고, 복제 버튼을 누릅니다.
그럼 두번째 설정이 나오게 되는데, 이름을 8081로 바꿉니다.
그다음 오른쪽의 Modify options를 누르고, Add VM options를 선택합니다.
그럼 JVM에 전달할 설정을 정할 수 있는데, 여기에 -Dserver.port=8081를 작성하고, Apply → OK
그럼 서로다른 포트에 두개의 Spring Boot 프로젝트를 실행할 수 있습니다!

여튼 포트 번호를 바꿔가면서 세션에 정보를 저장, 회수를 진행해 보면, 회수를 다른 포트의 서버에서 하려고 할때 데이터를 정상적으로 찾을 수 없다.
결국 여러 서버를 가동하게 되면, 세션의 정보를 서버 내부에서 관리하기 어려워지며 이에 따라 적당한 대안을 마련해야 한다.
특정 사람이 보낸 요청을 하나의 서버로 고정하는 방법
요청을 분산하는 로드밸런서를 통해 요청을 보낸 사용자를 기록, 해당 사용자가 다시 요청을 할 경우 최초로 요청이 전달된 서버로 요청을 전달하는 방식

sticky session의 문제점을 보완할 수 있는 방식
여러 서버들이 하나의 저장소를 공유하고, 해당 저장소에 세션에 대한 정보를 저장함으로서, 요청이 어느 서버로 전달이 되든 세션 정보가 유지
아무 사용자나 서버(의 로드밸런서)로 요청을 보낸다고 가정해했을 때 그러면 서버는 세션을 생성하되, 이 세션에 연결된 정보를 내부에 저장하는게 아닌 외부의 저장소에 저장

Sticky session의 문제를 완벽히 해결할 수 있다.
| Sticky Session | Session Clustering | |
|---|---|---|
| 장점 | 애플리케이션 입장에선 구현이 쉬움 | |
| 외부와 통신할 필요가 없음 | Load Balancer에서 균등하게 요청 분산 가능 | |
| 서버의 추가 제거가 비교적 자유로움 | ||
| 단점 | 요청이 분산되지 않아 과부하 가능성 존재 | |
| 한 서버가 다운되면 그 서버가 관리하는 세션도 삭제 | 외부 저장소라는 관리 포인트 추가 | |
| 외부와 통신하는 지연이 발생 |
Spring Boot와 Redis를 함께 사용하고 있다면, 매우 쉽게 Session Clustering을 적용 가능
'org.springframework.session:spring-session-data-redis'
Spring Session은 Spring의 하위 프로젝트 중 하나로, 사용자의 세션 정보를 다루는데 유용한 API를 제공하는데 그것에 Spring Session Data Redis를 추가하면, 내장 Tomcat의 세션 기능을 사용하지 않고 Redis에 별도로 세션을 저장할 수 있다.

더이상 Tomcat을 사용하지 않기 때문에 JSESSIONID 대신 SESSION이라는 새로운 쿠키를 사용하고 있는것을 확인

Default로는 자바 기반 직력화가 적용되고 있으며 만약 RedisTemplate을 사용할때 처럼 JSON을 비롯한 방식으로 직렬화를 하고 싶다면, springSessionDefaultRedisSerializer Bean을 등록
@Configuration
public class RedisConfig {
// ...
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
return RedisSerializer.json();
}
}

이렇게 되면 읽을 수 있는 형태로 Redis에 저장되기는 하지만, Spring Security의 일부인 SecurityContext와 같은 객체가 Redis에 저장될 경우, SecurityContext의 기본 생성자가 없기 때문에 오류가 발생
⇒ 굳이 redis에서 읽어야 하나 싶다. 그냥 Java에서 역직렬화 해서 읽도록 하자.
⚠️ `SecurityContext` 객체의 직렬화, 역직렬화의 경우 본 강의의 범주를 벗어나기 때문에, 지금 단계에서는 해당 오류가 발생할 수 있다는 점만 염두에 두도록 하겠습니다. 차후 공부를 통해 직접 `RedisSerializer`를 구성하거나, 직렬화가 쉽게 되는 `SecurityContext`를 만드는 것을 연구해 보세요!그렇다고 한다.