세션 클러스터링(Session Clustering)

이진일·2026년 5월 11일
post-thumbnail

서비스 규모가 커지면 서버를 여러 대 두는 Scale-Out이 필수적입니다. 하지만 Scale-Out 시 발생하는 문제가 세션 불일치입니다. 이 문제와 해결 방안에 대해 알아보겠습니다.


1. HttpSession과 쿠키의 관계

HTTP는 상태가 없는(Stateless) 프로토콜입니다. 따라서 서버는 사용자를 식별하기 위해 브라우저에 JSESSIONID라는 쿠키를 발급하고, 서버 메모리에 해당 ID와 연결된 세션 객체를 생성합니다.

  • 동작 원리: 브라우저 요청 → 서버 세션 생성 & ID 발급 → 브라우저 쿠키 저장 → 이후 요청마다 쿠키 동봉 → 서버에서 사용자 식별

2. 서버가 여러 대라면? (Scale-Out의 함정)

만약 서버 A에서 로그인을 해서 세션을 생성했는데, 다음 요청이 로드밸런서에 의해 서버 B로 전달된다면 어떻게 될까요?

  • 결과: 서버 B에는 사용자의 세션 정보가 없으므로 다시 로그인 페이지로 튕기거나 에러가 발생합니다.

💡 해결책 1: Sticky Session

특정 사용자의 요청을 처음 연결된 서버로만 고정하는 방식입니다.

  • 장점: 구현이 단순함.
  • 단점: 특정 서버에 부하가 쏠릴 수 있고(부하 불균형), 해당 서버가 다운되면 세션 데이터가 모두 증발함.

💡 해결책 2: Session Clustering (추천!)

여러 서버가 공용 저장소(Redis 등)를 공유하여 세션을 관리하는 방식입니다.

  • 장점: 어느 서버로 요청이 가도 세션이 유지됨. 서버의 추가/제거가 자유로움.
  • 단점: 외부 저장소(Redis)와의 통신 지연이 발생하며 관리 포인트가 늘어남.

3. Spring Boot에 Session Clustering 적용하기

Spring Boot와 Redis가 있다면 의존성 추가만으로도 세션 클러스터링을 구현할 수 있습니다.

🔹 의존성 추가 (build.gradle)

내장 Tomcat의 세션 관리 대신 Redis를 사용하도록 설정합니다.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'
    implementation 'org.springframework.session:spring-session-data-redis' // 핵심!
}

🔹 실습 확인하기

서버를 8080포트와 8081포트 두 대를 띄우고 테스트해 봅니다.

  1. 8080/set?q=data 접속 → 세션 저장

  2. 8081/get 접속 → 데이터 조회 성공!

이때 브라우저를 확인해 보면 기존의 JSESSIONID 대신 SESSION이라는 이름의 새로운 쿠키가 생성된 것을 볼 수 있습니다.


4. Redis 저장 데이터 직렬화 설정

기본적으로 Java 직렬화를 사용하면 Redis 내 데이터를 읽기 어렵습니다.

사람이 읽을 수 있는 JSON 형태로 저장하려면 아래 설정을 추가합니다.
RedisConfig.java

@Configuration
public class RedisConfig {
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        // 세션 데이터를 JSON 형태로 직렬화하여 저장
        return RedisSerializer.json();
    }
}

⚠️ 주의사항: SecurityContext와 같이 기본 생성자가 없는 객체를 세션에 담을 경우, JSON 직렬화/역직렬화 과정에서 오류가 발생할 수 있습니다. 이 경우 커스텀 Serializer를 구성하거나 Java 기본 직렬화를 유지해야 할 수도 있으니 유의하세요!


💡 마무리하며

서버가 1대일 때는 체감하기 어렵지만, 실무 환경에서는 Session Clustering이 필수입니다. 특히 Redis는 인메모리 DB로서 지연 시간이 매우 짧아 세션 저장소로 가장 많이 선호됩니다.

0개의 댓글