CNF 블로그

CNF 블로그에서 최신 정보와 유용한 팁을 만나보세요. 다양한 콘텐츠와 전문 지식을 통해 더 나은 경험을 제공합니다.

세션 클러스터링 때문에 밤샜다면?-Tomcat 세션 클러스터링의 진실

톰캣 세션 클러스터링 때문에 고생하고 계신가요? 멀티캐스트 문제, 네트워크 폭풍, JVM 메모리 부족 등 현실적 문제점과 데이터 그리드 기반 해결책까지 톰캣 세션 클러스터링의 진실을 파헤쳐 드립니다.

2025년 09월 30일

세션 클러스터링 때문에 밤샜다면?-Tomcat 세션 클러스터링의 진실

Apache Tomcat 세션 클러스터링, 그 불편한 진실과 해법

많은 분들이 한 번쯤 겪어보셨을 고통, 바로 Apache Tomcat의 세션 클러스터링 문제에 대해 깊이 있게 이야기해보고자 합니다.

“우리 서비스는 절대 중단되면 안 돼!”라는 목표 아래 고가용성(High Availability) 아키텍처를 구성할 때, Tomcat 클러스터링은 당연한 수순처럼 여겨집니다. 하지만 이론과 현실은 다르죠. 막상 클러스터링을 적용하고 나면 예상치 못한 성능 저하, 세션 유실, 운영의 어려움에 부딪히는 경우가 허다합니다.

이 글에서는 Tomcat이 제공하는 내장 세션 클러스터링 방식이 왜 현대적인 클라우드 환경에서 한계를 보이는지, 그리고 많은 엔지니어들이 어떤 문제들로 밤을 새우고 있는지 구체적인 사례를 통해 알아보겠습니다. 그리고 그에 대한 명쾌한 해답으로 OPENMARU Cluster와 같은 데이터 그리드 기반 솔루션이 왜 필수적인지 설명해 드리겠습니다.

1. Apache Tomcat 세션 클러스터링의 문제점들, 왜 잘 안될까요?

Tomcat이 제공하는 세션 클러스터링은 이론적으로는 훌륭해 보입니다. 여러 Tomcat 인스턴스가 세션 정보를 서로 복제하여 하나의 서버에 장애가 발생해도 다른 서버가 세션을 이어받아 서비스를 계속할 수 있다는 개념이죠. 하지만 이 ‘복제’ 과정에 악마는 숨어 있습니다.

Tomcat의 클러스터링은 크게 DeltaManager(All-to-All 방식)와 BackupManager(Primary-Backup 방식)로 나뉩니다. 두 방식 모두 현대적인 대규모 서비스 환경에서는 명확한 한계를 가집니다.

걸림돌 1: 멀티캐스트(Multicast) 통신에 대한 의존성

Tomcat 클러스터는 기본적으로 멀티캐스트를 사용하여 클러스터에 속한 다른 멤버(Tomcat 인스턴스)들을 찾아내고 상태를 공유합니다. 하지만 멀티캐스트는 클라우드 환경의 가장 큰 적 중 하나입니다. AWS, GCP, Azure와 같은 대부분의 퍼블릭 클라우드 환경에서는 보안과 네트워크 복잡성 문제로 멀티캐스트를 지원하지 않거나 설정이 매우 까다롭습니다.

컨테이너와 오케스트레이션의 표준이 된 쿠버네티스(Kubernetes) 환경에서도 마찬가지입니다. 복잡한 오버레이 네트워크 위에서 멀티캐스트가 안정적으로 동작하리라 기대하기는 어렵습니다. 결국, 클러스터링을 시도하는 첫 단계인 ‘서버 간의 연결’부터 막히게 되는 것입니다. 물론 Static Membership(정적 멤버 설정)으로 이 문제를 우회할 수는 있지만, 이는 클라우드의 핵심 가치인 ‘유연한 확장성(Elastic Scaling)’을 포기하는 것을 의미합니다.

걸림돌 2: All-to-All 복제 방식의 네트워크 폭풍 (Network Storm)

DeltaManager를 사용할 때, 하나의 Tomcat 인스턴스에서 세션 데이터에 변경이 생기면 그 변경 사항을 클러스터 내의 모든 다른 인스턴스에 전파합니다. 3~4대의 소규모 환경에서는 문제가 없어 보일 수 있습니다. 하지만 서버가 10대, 20대로 늘어나는 순간 재앙이 시작됩니다.

사용자 요청 하나로 인해 발생하는 세션 변경이 (N-1)개의 서버로 복제됩니다. 만약 20대의 서버가 있다면, 세션 변경 한 번에 19번의 네트워크 통신과 데이터 직렬화(Serialization) 작업이 발생합니다. 트래픽이 몰리는 피크 타임에는 이 복제 트래픽이 실제 서비스 트래픽을 압도하여 네트워크 대역폭을 모두 소진시키는 ‘네트워크 폭풍’ 현상을 일으킵니다. 결국, 서버를 늘릴수록 오히려 전체 시스템의 성능이 급격히 저하되는, 확장성의 역설에 직면하게 됩니다.

걸림돌 3: 세션 데이터 저장을 위한 과도한 JVM Heap 메모리

Tomcat 클러스터링은 각 인스턴스의 JVM Heap 메모리 안에 세션 데이터를 저장하고 복제합니다. 이는 필연적으로 각 Tomcat의 Heap 메모리 사용량을 증가시킵니다. 동시 접속자 수가 많은 서비스일수록, 세션에 저장하는 데이터가 클수록 이 문제는 심각해집니다.

메모리 사용량이 늘어나면 어떤 일이 벌어질까요? 바로 Full GC (Garbage Collection)의 공포가 시작됩니다. Full GC가 발생하는 동안에는 ‘Stop-the-world’ 현상으로 인해 해당 Tomcat 인스턴스는 모든 작업을 멈추고 응답 불능 상태에 빠집니다. 수 초, 길게는 수십 초간 서버가 멈추는 현상이 빈번해지고, 이는 곧 서비스 장애로 이어집니다. 장애를 막기 위해 도입한 클러스터링이 오히려 장애의 원인이 되는 아이러니한 상황입니다.

걸림돌 4: 경직된 구조와 배포의 어려움

Tomcat 내장 클러스터링은 모든 멤버가 동일한 애플리케이션을 배포하고 있어야 한다는 강력한 전제를 가집니다. 이는 MSA(Microservice Architecture) 환경과는 맞지 않습니다. 서로 다른 역할을 하는 애플리케이션 간에 로그인 상태(세션)를 공유하고 싶어도 Tomcat 클러스터링으로는 불가능합니다.

또한, 롤링 업데이트(Rolling Update)와 같은 무중단 배포 전략을 실행하기도 매우 어렵습니다. 새로운 버전의 애플리케이션을 배포하기 위해 서버를 하나씩 재시작할 때마다 클러스터 멤버십이 변경되고, 재시작된 서버가 다른 서버들로부터 모든 세션 데이터를 동기화하려는 시도 때문에 시스템 전체에 큰 부하를 유발할 수 있습니다.

결론적으로, Tomcat의 내장 세션 클러스터링은 애플리케이션 서버(WAS)가 자신의 본질적인 역할인 ‘비즈니스 로직 처리’를 넘어 ‘분산 데이터 관리’라는 어려운 역할까지 떠맡으려다 발생하는 구조적인 문제입니다.

Apache Tomcat이란?

Apache Tomcat 에서 세션 클러스터링의 문제점들, 왜 안되는 걸까?

omcat의 세션 클러스터링은 이론보다 현장에서 더 어렵습니다. 문서만 보면 DeltaManager(전체 노드에 복제)와 BackupManager(주-보조 방식) 중 하나를 선택해 설정하면 끝처럼 보입니다. 하지만 DeltaManager는 노드가 늘수록 모든 노드가 모든 세션을 받아 메모리·네트워크 비용이 기하급수적으로 커지고, BackupManager는 스티키 세션(세션 고정)과 짝을 이루지 않으면 예기치 않은 세션 손실을 낳습니다. Tomcat 공식 문서도 “작은 클러스터가 아니면 all-to-all 복제는 비효율적이며, 큰 클러스터에는 주-보조 전략을 쓰라”고 분명히 권고합니다.

운영 환경으로 내려오면 난이도는 더 올라갑니다. 첫째, “세션 속성은 전부 java.io.Serializable을 구현해야 복제된다”는 원칙을 한 번만 어겨도 복제 실패나 NotSerializableException이 터지고, 일부 속성이 직렬화되지 않으면 조용히(혹은 경고만 남기고) 복제에서 제외되기도 합니다. 이 문제는 프레임워크가 주입한 객체나 캐시 핸들러처럼 우리가 직접 만든 적 없는 타입에서도 자주 발생합니다. 관련 사례는 포럼과 Q&A에 넘쳐납니다.

둘째, 로드 밸런서와 프록시의 세부 설정이 세션을 흔듭니다. URL 리라이트나 리버스 프록시 경로가 애플리케이션 컨텍스트와 달라 쿠키 Path가 어긋나면 요청마다 JSESSIONID가 새로 생기고, 결국 “로그인하면 곧바로 풀리는” 증상으로 보입니다. 이때는 proxy_cookie_path 같은 지시자를 정확히 맞춰야 합니다. 또한 ELB/ALB 등 L4/L7의 “스티키 세션”이 꺼져 있거나 쿠키-기반·기간 설정이 부적절하면 BackupManager에서도 세션 흔들림이 반복됩니다.

셋째, 네트워크 토폴로지의 제약입니다. 레거시 가이드의 멀티캐스트 기반 멤버십은 컨테이너/클라우드에서 차단되는 경우가 많고, 멀티캐스트를 켜더라도 대역폭과 패킷 손실에 민감합니다. Kubernetes 같은 현대적 배포 환경에서는 정적 멤버십이나 외부 디스커버리, 혹은 아예 외부 세션 저장소(예: 데이터 그리드/Redis/Hazelcast 등)로 전환하는 것이 현실적인 선택입니다.

넷째, JVM 힙과 GC 문제입니다. “세션이 많아지면 노드를 더 늘리면 된다”는 통념은 in-JVM 복제에서는 잘 통하지 않습니다. 각 노드 힙에 세션이 중복 상주하기 때문에 힙을 키울수록 Full GC 리스크가 커지고 지연이 폭증합니다. 이런 구조적 제약 때문에 대규모 트래픽, 대형 세션, 롤링 배포, 멀티 도메인/서브도메인 SSO 같은 요구가 겹치는 순간, 내장형 복제만으로는 안정성과 확장성을 동시에 잡기 어렵습니다. Tomcat 문서와 현장 가이드는 이러한 제약을 반복해서 상기시킵니다. login.iahp.org

결국 핵심은 “세션 상태를 애플리케이션 JVM 밖으로 분리(externalize)해 독립 확장 가능한 저장소로 옮길 것인가”입니다. 데이터 그리드·분산 캐시·전용 세션 스토어로 세션을 이동시키면, WAS는 비즈니스 처리에 집중하고 세션은 별도의 그리드가 수평 확장과 고가용성을 맡습니다. 컨테이너·MSA·Kubernetes 시대에는 이 분리가 사실상 필수 아키텍처 패턴으로 자리 잡았습니다.

Apache Tomcat 설치의 모든 것 – 이것만 알면 설치는 끝

2. “세션이 자꾸 끊겨요!” – 현장에서 마주하는 실제 문제 사례들

이론적인 설명만으로는 감이 잘 오지 않을 수 있습니다. 그렇다면 실제 현장의 엔지니어들은 Tomcat 클러스터링 때문에 어떤 문제들로 웹사이트를 검색하며 고통받고 있을까요?

사례 1: 클라우드로 이전 후 먹통이 된 클러스터

온프레미스(On-premise) 환경에서 잘 동작하던 Tomcat 클러스터링 기반의 서비스를 AWS로 마이그레이션한 A사. 이전 후 테스트를 해보니 클러스터가 전혀 구성되지 않고 각 서버가 따로 노는 현상을 발견했습니다. 원인은 바로 VPC 환경에서 막힌 멀티캐스트였습니다. 개발팀은 며칠 밤낮으로 AWS의 네트워크 보안 그룹(Security Group)과 NACL 설정을 붙잡고 씨름했지만 해결하지 못했고, 결국 클러스터링을 포기하고 특정 서버에 장애가 나면 해당 서버에 접속했던 모든 사용자가 로그아웃되는 것을 감수해야 했습니다.

사례 2: 대규모 이벤트 중 발생한 연쇄 장애

B 쇼핑몰은 블랙 프라이데이 이벤트를 위해 Tomcat 서버를 20대까지 증설했습니다. 이벤트 시작과 함께 트래픽이 몰리자, 갑자기 모든 서버의 CPU 사용률이 100%에 도달하며 웹사이트 전체가 마비되었습니다. 원인 분석 결과, 급증한 사용자의 장바구니 정보(세션 데이터)를 모든 서버가 서로에게 복제하느라 발생한 네트워크 부하와 CPU 과부하 때문이었습니다. 서버를 늘린 것이 오히려 독이 된 것입니다. 결국 이벤트는 중단되었고, 회사는 막대한 매출 손실과 고객 신뢰도 하락이라는 최악의 결과를 맞았습니다.

사례 3: “자꾸 로그아웃돼요” 고객 불만 폭주

C사는 로드밸런서의 ‘스티키 세션(Sticky Session)’ 기능과 Tomcat의 Primary-Backup 클러스터링을 함께 사용하고 있었습니다. 평소에는 문제가 없었지만, 특정 서버에 부하가 몰려 응답이 느려지거나 장애로 재시작되는 경우가 발생하면 문제가 터졌습니다. 로드밸런서는 장애가 난 서버를 피해 다른 서버로 사용자의 요청을 보냈지만, 그 서버에는 아직 세션 정보가 복제되지 않았거나 유실된 상태였습니다. 결국 사용자는 로그인이 풀리고, 작성 중이던 게시물이나 장바구니 상품이 모두 사라지는 끔찍한 경험을 하게 되었습니다. 고객센터는 관련 불만 전화로 마비되었습니다.

사례 4: MSA 전환의 발목을 잡는 세션 사일로(Silo)

D사는 기존의 거대한 모놀리식(Monolithic) 시스템을 여러 개의 마이크로서비스로 전환하는 프로젝트를 진행 중입니다. 상품 서비스는 Tomcat 8.5로, 주문 서비스는 Tomcat 9.0으로, 인증 서비스는 Spring Boot 기반으로 구성했습니다. 그런데 사용자가 로그인한 후 여러 서비스를 오갈 때 로그인 상태를 유지할 방법이 없었습니다. 각 서비스 그룹이 자신만의 세션 클러스터를 가지고 있어 데이터가 공유되지 않는 ‘세션 사일로’ 문제가 발생한 것입니다. MSA의 유연함을 누리기도 전에 기본적인 사용자 경험조차 제공할 수 없는 난관에 부딪혔습니다.

이 모든 사례들의 근본적인 원인은 동일합니다. 세션 데이터를 애플리케이션 서버(WAS) 내부에 두려는 시도 때문입니다.

해결의 열쇠: 세션 스토리지의 분리

그렇다면 이 지긋지긋한 문제를 어떻게 해결해야 할까요? 해답은 의외로 간단한 원칙에 있습니다.

“애플리케이션 서버는 비즈니스 로직 처리에만 집중하게 하고, 세션 데이터는 외부의 전문화된 분산 데이터 스토리지에 맡겨라.”

바로 이 원칙을 가장 효과적으로 구현한 것이 OPENMARU Cluster와 같은 데이터 그리드(Data Grid) 기반의 세션 클러스터링 솔루션입니다.

OPENMARU Cluster는 세션 데이터를 Tomcat의 JVM Heap이 아닌, 별도로 구성된 고성능 인메모리 데이터 그리드 클러스터에 저장합니다. Tomcat 인스턴스들은 이 데이터 그리드에 클라이언트로 접속하여 세션 데이터를 읽고 쓰기만 하면 됩니다.

이렇게 아키텍처를 변경하면 앞서 언급된 모든 문제들이 눈 녹듯이 해결됩니다.

  • 클라우드 친화적

멀티캐스트 대신 표준 TCP/IP 통신을 사용하므로 어떤 클라우드, 쿠버네티스 환경에서도 완벽하게 동작합니다.

  • 완벽한 확장성

Tomcat 서버가 100대로 늘어나도 세션 복제에 따른 부하가 전혀 없습니다. 각 Tomcat은 데이터 그리드와 1:1 통신만 할 뿐입니다. 부하가 늘면 Tomcat과 데이터 그리드 노드를 각각 독립적으로 확장(Scale-out)하면 됩니다.

  • Full GC 문제 해결

Tomcat의 Heap 메모리는 오직 비즈니스 로직 처리를 위한 객체들만 관리하게 되므로 크기를 작고 효율적으로 유지할 수 있습니다. Full GC 발생 빈도와 시간이 극적으로 줄어들어 서비스 안정성이 비약적으로 향상됩니다.

  • MSA와 무중단 배포 지원

세션 데이터가 외부에 존재하므로, 기종이 다른 WAS(Tomcat, JBoss 등)나 다른 버전의 애플리케이션, 심지어 다른 언어로 개발된 애플리케이션 간에도 세션 공유가 가능해져 진정한 SSO(Single Sign-On)와 유연한 MSA 구성이 가능해집니다. 또한, Tomcat 서버를 재시작해도 세션 데이터는 안전하게 보존되므로 무중단 배포가 훨씬 자유로워집니다.

결론: 현대적 아키텍처를 위한 현명한 선택

이제 Tomcat의 내장 클러스터링만으로 대규모의 안정적인 서비스를 구축하려는 시도는 낡은 방식이 되었습니다. 특히 MSA, 쿠버네티스, 클라우드 네이티브가 표준이 된 지금, 세션 관리 방식을 근본적으로 바꾸는 것은 더 이상 선택이 아닌 필수입니다.

만약 여러분이 세션 문제로 반복되는 장애와 고객 불만에 시달리고 있다면, 혹은 클라우드와 MSA로의 성공적인 전환을 계획하고 있다면, 이제는 세션 데이터를 WAS의 족쇄에서 풀어줄 때입니다. OPENMARU Cluster와 같은 검증된 외부 세션 스토리지 솔루션을 통해 개발자는 핵심 비즈니스 로직에만 집중하고, 인프라는 최고의 안정성과 확장성을 확보하는 현명한 선택을 하시길 바랍니다.

References & Related Links

이제 나도 MSA 전문가: 개념부터 실무까지 - 기초편

이제 나도 MSA 전문가:

개념부터 실무까지

이제 나도 클라우드 네이티브 전문가: 쿠버네티스 구축부터 운영 완전 정복

쿠버네티스 구축부터

운영 완전 정복

거침없이 배우는 JBoss

거침없이 배우는

JBoss EAP

Share This Story, Choose Your Platform!

Go to Top