다중 서버 환경에서의 세션 관리: 스티키 세션과 그 대안들

2025. 5. 29. 01:06·Backend Development
반응형

클라우드 환경과 대규모 서비스의 발전으로 다중 서버 환경은 이제 선택이 아닌 필수가 되었습니다. 그러나 세션 기반 인증을 사용하는 애플리케이션에서는 다중 서버 환경이 새로운 도전 과제를 가져옵니다. 이번 글에서는 다중 서버 환경에서 세션을 관리하는 방법과 각 방식의 장단점을 알아보겠습니다.


다중 서버 환경에서의 세션 불일치 문제

웹 애플리케이션의 트래픽이 증가함에 따라 서버를 수평적으로 확장하는 것은 자연스러운 해결책입니다. 그러나 세션 기반 인증을 사용하는 경우, 서버마다 독립적인 메모리 공간을 가지므로 세션 불일치 문제가 발생합니다.

세션 불일치란?

세션 불일치는 다중 서버 환경에서 사용자의 세션 정보가 특정 서버에만 저장되어, 다른 서버로 요청이 라우팅될 경우 인증 상태가 유지되지 않는 문제를 말합니다.

세션 불일치 문제 발생 과정

예를 들어 두 대의 서버(A, B)가 로드 밸런서 뒤에 있다고 가정해보겠습니다:

  1. 사용자가 로그인 요청을 보내면 로드 밸런서는 서버 A로 요청 전달
  2. 서버 A는 인증 후 사용자의 세션을 서버 A의 메모리에 저장
  3. 사용자가 다시 요청을 보내면 로드 밸런서는 서버 B로 요청 전달
  4. 서버 B에는 해당 사용자의 세션 정보가 없어 인증되지 않은 사용자로 간주
사용자 → 로그인 요청 → 로드 밸런서 → 서버 A (세션 생성 및 저장)
                                    ↓
사용자 → 두 번째 요청 → 로드 밸런서 → 서버 B (세션 없음 → 인증 실패)

이 문제를 해결하기 위한 세 가지 주요 방식을 살펴보겠습니다.


1. 스티키 세션 (Sticky Session) 방식

스티키 세션은 사용자의 모든 요청이 항상 동일한 서버로 전달되도록 보장하는 방식입니다.

작동 방식

  1. 사용자가 처음 로그인하면 로드 밸런서는 해당 사용자와 특정 서버 간의 "고정(affinity)" 관계를 설정
  2. 이후 해당 사용자의 모든 요청은 동일한 서버로 라우팅
  3. 고정 관계는 사용자의 쿠키나 IP 주소를 기반으로 유지

구현 예시 (AWS ELB 설정)

# AWS ELB 스티키 세션 설정 예시 (CloudFormation)
Resources:
  MyLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      # ... 기타 설정 ...

  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      # ... 기타 설정 ...
      TargetGroupAttributes:
        - Key: stickiness.enabled
          Value: true
        - Key: stickiness.type
          Value: lb_cookie
        - Key: stickiness.lb_cookie.duration_seconds
          Value: 86400  # 쿠키 유효 기간 (1일)

장점

  • 구현이 간단함: 대부분의 로드 밸런서가 스티키 세션 기능을 제공
  • 성능 오버헤드가 적음: 외부 저장소나 동기화 작업이 필요 없음
  • 세션 데이터 변경 추적이 필요 없음: 항상 같은 서버에서 처리되므로

단점

  • 서버 장애 시 세션 유실: 특정 서버가 다운되면 해당 서버에 고정된 모든 사용자는 재로그인 필요
  • 로드 밸런싱 효율 저하: 특정 서버에 트래픽이 집중될 수 있음
  • 확장성 제한: 새 서버 추가 시 기존 사용자의 세션을 마이그레이션하기 어려움

2. 세션 클러스터링 (Session Clustering) 방식

세션 클러스터링은 한 서버에서 생성된 세션 정보를 다른 모든 서버에 복제하여 동기화하는 방식입니다.

작동 방식

  1. 사용자가 로그인하면 세션이 생성된 서버는 해당 세션 정보를 클러스터 내 다른 모든 서버에 복제
  2. 모든 서버가 동일한 세션 정보를 가지므로 어떤 서버로 요청이 가더라도 동일한 세션 상태 유지
  3. 세션 변경 시 모든 서버에 변경 사항 전파

구현 예시 (Tomcat 클러스터링 설정)

<!-- Tomcat server.xml 세션 클러스터링 설정 예시 -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
         channelSendOptions="8">
    <Manager className="org.apache.catalina.ha.session.DeltaManager"
             expireSessionsOnShutdown="false"
             notifyListenersOnReplication="true"/>
    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Membership className="org.apache.catalina.tribes.membership.McastService"
                   address="228.0.0.4"
                   port="45564"
                   frequency="500"
                   dropTime="3000"/>
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                 address="auto"
                 port="4000"
                 autoBind="100"
                 selectorTimeout="5000"
                 maxThreads="6"/>
        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
            <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
        </Sender>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpPingInterceptor"/>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
    </Channel>
    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
           filter=""/>
    <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
    <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
             tempDir="/tmp/war-temp/"
             deployDir="/tmp/war-deploy/"
             watchDir="/tmp/war-listen/"
             watchEnabled="false"/>
    <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

장점

  • 서버 장애에 강함: 한 서버가 다운되어도 다른 서버에 세션 정보가 존재
  • 균등한 로드 밸런싱: 스티키 세션이 필요하지 않아 균등한 부하 분산 가능
  • 사용자 경험 향상: 서버 장애 시에도 사용자는 재로그인할 필요가 없음

단점

  • 메모리 사용량 증가: 모든 서버가 모든 세션 정보를 복제하므로 메모리 중복 사용
  • 네트워크 오버헤드: 세션 복제 과정에서 네트워크 트래픽 발생
  • 세션 복제 지연: 복제 과정에서 발생하는 지연으로 일시적인 세션 불일치 가능성
  • 구현 복잡성: 적절한 설정과 관리가 필요

3. 스토리지 분리 (External Session Storage) 방식

스토리지 분리 방식은 세션 정보를 모든 서버가 접근할 수 있는 외부 저장소(Redis, Memcached 등)에 저장하는 방식입니다.

작동 방식

  1. 사용자가 로그인하면 세션 정보를 서버 메모리가 아닌 외부 저장소에 저장
  2. 모든 서버는 동일한 외부 저장소에 접근하여 세션 정보를 조회/수정
  3. 세션 ID는 쿠키를 통해 클라이언트에 전달

외부 스토리지 세션 방식

구현 예시 (Spring Boot + Redis)

// Spring Boot에서 Redis 세션 저장소 구성 예시
@Configuration
@EnableRedisHttpSession
public class SessionConfig {

    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory(
            new RedisStandaloneConfiguration("redis-host", 6379));
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory());
        return template;
    }
}

장점

  • 효율적인 메모리 사용: 세션 정보가 한 곳에만 저장되어 중복 없음
  • 손쉬운 확장성: 새 서버 추가 시 외부 저장소에 연결만 하면 됨
  • 서버 장애에 강함: 서버가 다운되어도 세션 정보는 외부 저장소에 안전하게 보관
  • 균등한 로드 밸런싱: 어떤 서버로 요청이 가도 동일한 세션 접근 가능

단점

  • 외부 저장소 장애 위험: 저장소가 단일 장애 지점(SPOF)이 될 수 있음
  • 지연 시간 추가: 외부 저장소 접근에 따른 네트워크 지연 발생
  • 추가 인프라 관리: 외부 저장소 설정 및 유지보수 필요
  • 복제 지연 가능성: 저장소 클러스터링 시 복제 지연으로 인한 일시적 불일치 가능

세 가지 방식 비교

각 방식의 특징을 한눈에 비교해 보겠습니다.

비교 항목 스티키 세션 세션 클러스터링 스토리지 분리
구현 복잡성 낮음 높음 중간
메모리 효율성 중간 낮음 높음
서버 장애 대응 취약 강함 강함
확장성 제한적 중간 우수
성능 오버헤드 낮음 중간 중간
로드 밸런싱 효율 낮음 높음 높음
추가 인프라 필요 없음 적음 많음
적합한 상황 소규모 애플리케이션 중간 규모, 고가용성 필요 대규모, 클라우드 환경

실제 구현 시 고려사항

스티키 세션 구현 시 고려사항

  • 로드 밸런서 설정을 통해 간단히 구현할 수 있음
  • 장애 복구 계획 수립 필요 (서버 장애 시 세션 소실)
  • 서버 간 불균형 부하를 모니터링해야 함

세션 클러스터링 구현 시 고려사항

  • 애플리케이션 서버의 클러스터링 기능 활용 (Tomcat, JBoss 등)
  • 네트워크 대역폭과 세션 복제 주기 최적화
  • 서버 추가/제거 시 세션 재분배 전략 필요

스토리지 분리 구현 시 고려사항

  • 적절한 외부 저장소 선택 (Redis, Memcached, DB 등)
  • 저장소의 고가용성 구성 (클러스터링, 레플리케이션)
  • 세션 직렬화/역직렬화 성능 최적화
  • 세션 만료 정책 설정

JWT: 세션 관리의 대안

세션 기반 인증의 복잡성을 피하기 위해 JWT(JSON Web Token)와 같은 토큰 기반 인증을 고려할 수도 있습니다. JWT는 상태를 저장하지 않는(stateless) 인증 방식으로, 서버 간 세션 동기화 문제가 발생하지 않습니다.

// JWT 구조 예시
const header = {
  "alg": "HS256",  // 서명 알고리즘
  "typ": "JWT"     // 토큰 타입
};

const payload = {
  "sub": "1234567890",  // 사용자 식별자
  "name": "John Doe",   // 사용자 정보
  "iat": 1516239022,    // 발급 시간
  "exp": 1516242622     // 만료 시간
};

// header와 payload를 base64로 인코딩한 후 서명
const signature = HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret_key
);

// 최종 JWT
const jwt = base64UrlEncode(header) + "." + base64UrlEncode(payload) + "." + signature;

JWT의 장점

  • 서버 상태 저장 불필요: 토큰에 필요한 정보가 모두 포함되어 있음
  • 확장성 우수: 서버 간 공유 상태가 없어 수평적 확장이 용이
  • 교차 도메인 지원: 다양한 서비스 간에 인증 정보 공유 가능

JWT의 단점

  • 토큰 크기: 세션 ID에 비해 크기가 커 네트워크 오버헤드 발생
  • 토큰 폐기 어려움: 발급된 토큰은 만료 전까지 무효화하기 어려움
  • 민감 정보 저장 제한: 토큰이 클라이언트에 저장되므로 보안 위험 고려 필요

결론

다중 서버 환경에서의 세션 관리는 애플리케이션의 규모, 요구사항, 인프라 환경에 따라 최적의 방식이 달라집니다.

  • 스티키 세션: 구현이 간단하지만 서버 장애에 취약하므로 소규모 애플리케이션이나 빠른 구현이 필요한 경우에 적합
  • 세션 클러스터링: 서버 장애에 대한 복원력이 뛰어나지만 메모리 사용이 비효율적이므로 중간 규모의 미션 크리티컬한 애플리케이션에 적합
  • 스토리지 분리: 확장성과 메모리 효율성이 높지만 외부 의존성이 추가되므로 대규모 애플리케이션이나 클라우드 환경에 적합
  • JWT: 세션 관리의 복잡성을 피하고자 하는 경우 고려할 수 있는 대안적 접근법

어떤 방식을 선택하든, 사용자 경험, 시스템 성능, 장애 대응 능력 간의 균형을 고려하여 애플리케이션에 가장 적합한 전략을 선택하는 것이 중요합니다.


참고 자료

  • AWS ELB Sticky Sessions
  • Tomcat Session Clustering
  • Spring Session
  • Redis Documentation
  • JWT Introduction
  • Memcached Wiki
반응형
저작자표시 비영리 변경금지 (새창열림)

'Backend Development' 카테고리의 다른 글

동시성과 병렬성: 현대 백엔드 시스템의 핵심 개념 이해하기  (0) 2025.05.30
로드 밸런싱 완전 정복: 백엔드 개발자를 위한 핵심 가이드  (0) 2025.05.30
MySQL Replication 완벽 가이드: 고가용성과 데이터 안정성 확보  (2) 2025.05.29
Java Record 완벽 가이드: DTO와 VO 구현의 새로운 패러다임  (6) 2025.05.29
HTTP 메서드의 멱등성(Idempotency): 안전한 API 설계의 핵심  (2) 2025.05.29
'Backend Development' 카테고리의 다른 글
  • 동시성과 병렬성: 현대 백엔드 시스템의 핵심 개념 이해하기
  • 로드 밸런싱 완전 정복: 백엔드 개발자를 위한 핵심 가이드
  • MySQL Replication 완벽 가이드: 고가용성과 데이터 안정성 확보
  • Java Record 완벽 가이드: DTO와 VO 구현의 새로운 패러다임
Kun Woo Kim
Kun Woo Kim
안녕하세요, 김건우입니다! 웹과 앱 개발에 열정적인 전문가로, React, TypeScript, Next.js, Node.js, Express, Flutter 등을 활용한 프로젝트를 다룹니다. 제 블로그에서는 개발 여정, 기술 분석, 실용적 코딩 팁을 공유합니다. 창의적인 솔루션을 실제로 적용하는 과정의 통찰도 나눌 예정이니, 궁금한 점이나 상담은 언제든 환영합니다.
  • Kun Woo Kim
    WhiteMouseDev
    김건우
  • 깃허브
    포트폴리오
    velog
  • 전체
    오늘
    어제
  • 공지사항

    • [인사말] 이제 티스토리에서도 만나요! WhiteMouse⋯
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 분류 전체보기 (100) N
      • Frontend Development (39) N
      • Backend Development (21) N
      • Algorithm (33) N
        • 백준 (11) N
        • 프로그래머스 (17)
        • 알고리즘 (5)
      • Infra (1)
      • 자료구조 (3)
  • 링크

    • Github
    • Portfolio
    • Velog
  • 인기 글

  • 태그

    frontend development
    tailwindcss
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Kun Woo Kim
다중 서버 환경에서의 세션 관리: 스티키 세션과 그 대안들
상단으로

티스토리툴바