[인증/인가] 다중 서버 환경에서 Session은 어떻게 공유하고 관리할까?
서버가 한 대일 때는 문제가 단순하다.
해당 서버의 메모리에 세션을 저장하면 끝이다.
하지만 서버가 여러 대로 확장되는 순간, 이야기는 달라진다.
서버 하나당 하나의 세션 저장소가 존재하기 때문이다.
이때, 별도의 처리 없이 로드 밸런싱만 적용하면 각 서버 간 세션 데이터가 서로 공유되지 않는다.
그 결과, 정합성 이슈가 발생한다.
(알고 넘어가기) 정합성 이슈란?
정합성(Consistency)이란, 시스템의 모든 구성 요소가 동일한 데이터를 바라보는 상태를 의미한다.
예를 들어보자.
- 사용자가 로그인 요청을 보낸다.
- 해당 요청은 서버 1에서 처리된다.
- 세션은 서버 1의 메모리에 저장된다.
이후 사용자가 공연 티켓팅 요청을 보냈는데, 이번에는 요청이 서버 2로 전달된다면?
서버 2에는 해당 사용자의 세션이 존재하지 않는다.
결과적으로 사용자는 로그인하지 않은 상태로 처리된다.
이것이 다중 서버 환경에서 발생하는 세션 정합성 문제이다.
이 정합성 이슈를 해결하기 위해 등장한 대표적인 방식은 3가지다.
- Sticky Session
- Session Clustering
- Session Storage 분리 (In-Memory DB)
이제 하나씩 살펴보자.
Sticky Session (고정 세션)
Sticky Session은 처음 세션을 생성한 서버로 이후 요청도 계속 보내는 방식이다.
1
2
3
4
사용자가 처음 요청을 보낸다.
로드 밸런서는 일반적인 분산 알고리즘에 따라 서버를 선택한다.
해당 서버에서 세션이 생성된다.
이후 요청부터는, 로드 밸런서가 세션 정보를 확인해 그 세션이 존재하는 서버로만 요청을 전달한다.
즉, 세션을 서버끼리 공유하는 것이 아니라 세션이 저장된 서버로 사용자를 고정시키는 방식이다.
장점
- 구현이 비교적 단순하다.
- 서버 간 세션 동기화가 필요 없다.
- 세션이 항상 같은 서버 메모리에 존재하므로 빠르게 처리할 수 있다.
단점
트래픽 불균형
- 특정 서버에 사용자가 몰릴 수 있다.
- 다른 서버는 여유가 있는데, 한 서버만 과부하가 발생할 수 있다.
장애 대응 취약
- 사용자의 세션은 오직 한 서버에만 존재한다.
- 해당 서버에 장애가 발생하면 세션도 함께 사라진다.
- 사용자는 로그인 상태를 유지할 수 없으며, 다시 로그인해야 한다.
확장성 한계
- 기존 사용자는 이미 특정 서버에 고정되어 있다.
- 서버를 추가해도 기존 사용자는 다른 서버로 이동하지 않는다.
- 새 서버는 신규 사용자 요청이 들어와야만 활동된다.
- 그 결과, 서버 간 트래픽이 균등하게 분산되지 않을 수 있다.
Session Clustering
Clustering은 여러 대의 서버를 마치 하나의 시스템처럼 동작하도록 만드는 기술이다.
Session Clustering은 각 서버가 동일한 세션 정보를 가지도록 복제하는 방식이다.
(Tomcat 기준) 대표적으로 두 가지 방식이 있다.
1. All-to-All Replication (DeltaManager)
한 서버에서 생성되거나 변경된 세션을 모든 서버에 복제하는 방식이다.
1
2
3
4
5
사용자가 서버 1에 로그인한다.
서버 1에서 세션이 생성된다.
서버 1은 해당 세션 정보를 다른 모든 서버로 복제한다.
다른 서버들도 동일한 세션 데이터를 각자의 메모리에 저장한다.
이후 세션 값이 변경되면, 그 변경 내용 역시 모든 서버에 다시 전달된다.
즉, 세션을 특정 서버에 고정시키는 것이 아니라
모든 서버가 동일한 세션 데이터를 공유하도록 만드는 방식이다.
장점
- 어느 서버로 요청이 가더라도 동일한 세션을 보장한다.
- 특정 서버에 장애가 발생해도 다른 서버가 동일한 세션을 보유하고 있어 서비스가 지속된다.
단점
- 하나의 세션이 모든 서버에 복제되어 저장된다.
- 서버 수만큼 세션이 복사되므로 메모리 사용량이 증가한다.
- 세션 변경 시, 모든 서버로 전파해야 하므로 서버 수가 늘어날수록 네트워크 트래픽이 증가한다.
- 세션 변경 내용이 모든 서버에 즉시 반영되지 않을 수 있다.
따라서 일반적으로 서버 수가 많지 않은 소규모 환경에 적합하다.
2. Primary-Secondary Replication (BackupManager)
모든 서버에 세션을 복제하는 대신,
각 세션을 하나의 Primary 서버와 하나의 Secondary 서버에만 복제하는 방식이다.
1
2
3
4
사용자가 서버 1에서 로그인한다.
서버 1이 해당 세션의 Primary가 된다.
서버 1은 세션 정보를 지정된 Secondary 서버 한 곳에만 복제한다.
Primary 서버에 장애가 발생하면, Secondary 서버가 대신 세션을 처리한다.
즉, 세션을 모든 서버에 복제하는 것이 아니라,
한 서버에 문제가 생길 경우를 대비해 다른 한 서버에만 추가로 복제해두는 방식이다.
장점
- 모든 서버에 복제하지 않으므로
All-to-All방식보다 메모리 부담이 적다. - 세션 변경 시 한 서버에만 복제하면 되므로 네트워크 비용이 상대적으로 적다.
단점
- 여전히 세션 복제 작업이 필요하므로 복제 비용이 완전히 사라지지는 않는다.
- Primary 서버에 의존하는 구조이므로 특정 서버에 부하가 집중될 수 있다.
- Secondary 서버까지 동시에 장애가 발생하면 세션이 손실될 수 있다.
Session Storage 분리 (In-Memory DB)
앞선 두 방식은 세션을 서버 메모리 안에서 어떻게 공유할 것인가?에 대한 방식이었다.
이번 방식은 접근하는 것이 다르다.
세션을 서버 메모리에 두지 않고, 별도의 중앙 저장소에 분리하는 방식이다.
예를 들어, Redis와 같은 In-Memory DB를 사용한다.
구조를 단순하게 생각해보면 다음과 같다.
- 여러 대의 서버가 존재하고
- 모든 서버가 하나의 세션 저장소에 접근한다.
- 세션 데이터는 오직 그 저장소에만 존재한다.
즉, 세션은 더 이상 “서버에 종속된 데이터”가 아닌, 공통 저장소에 존재하는 데이터가 된다.
그래서 서버가 몇 대로 늘어나더라도 어느 서버에서 요청을 처리하든 동일한 세션을 조회할 수 있다.
장점
- 모든 서버가 동일한 저장소를 사용하므로 세션 정합성 문제가 발생하지 않는다.
- 세션이 서버에 묶여 있지 않으므로 서버 확장에 매우 유리하다.
- 로드 밸런싱이 자유롭다. (사용자를 특정 서버에 고정할 필요가 없다.)
- 특정 서버가 장애가 나더라도 세션 데이터는 그대로 유지된다.
단점
- 하나의 세션 저장소만 사용할 경우, 해당 저장소에 장애가 발생하면 전체 인증 시스템이 멈출 수 있다.
이러한 구조를 SPOF(Single Point Of Failure)라고 한다. Redis와 같은 별도의 세션 저장소를 운영해야 하므로 인프라 구성 및 관리 비용이 증가한다.
SPOF (Single Point Of Failure)
단일 장애 지점이라는 의미로, 하나의 구성 요소가 실패하면 전체 시스템이 영향을 받는 구조를 말한다.
예를 들어, 세션 저장소를 하나만 두었다면 그 저장소가 고장이 나는 순간 모든 사용자의 로그인 상태를 확인할 수 없게 된다.
그래서 무엇을 선택해야 할까?
| 방식 | 장점 | 단점 |
|---|---|---|
| Sticky Session | 구현 단순 | 트래픽 불균형, 장애 취약 |
| Session Clustering | 서버 장애 대응 가능 | 복제 비용 증가 |
| Storage 분리 | 확장성 우수, 구조 명확 | 별도 저장소 필요 |
실무에서는 대체로 Session Storage 분리 방식을 선택한다.
이유는 다음과 같다.
서버는 Stateless하게 유지하고,
상태는 외부 저장소에 위임하는 것이 수평 확장(Scale-Out)에 유리하기 때문이다.
In-Memory DB vs Disk-Based DB
In-Memory DB
데이터를 디스크가 아닌 메모리(RAM)에 저장하고 관리하는 데이터베이스이다.
대표적인 예로 Redis, Memcached 등이 있다.
메모리는 디스크보다 훨씬 빠른 접근 속도를 가지기 때문에 데이터 조회 및 처리 속도가 매우 빠르다.
디스크 접근을 최소화하고 대부분의 작업을 메모리에서 수행하기 때문에, 대량의 읽기/쓰기 요청이 발생하는 환경에서 뛰어난 성능을 보인다.
다만 RAM은 기본적으로 휘발성이기 때문에 서버 장애나 전원 꺼짐이 발생하면 데이터가 손실될 수 있다.
(일부 In-Memory DB는 디스크 백업 기능을 제공한다.)
Disk-Based DB
데이터를 디스크에 저장하는 전통적인 데이터베이스다.
대표적인 예로 MySQL, PostgreSQL, Oracle, MongoDB 등이 있다.
디스크는 전원이 꺼져도 데이터가 유지되므로 지속성과 안정성이 기본적으로 보장된다.
대용량 데이터를 저장하는 데 적합하며, 핵심 비즈니스 데이터를 영구적으로 보관하는 데 사용된다.
다만 디스크는 메모리보다 접근 속도가 느리기 때문에 많은 I/O가 발생하는 환경에서는 성능 병목이 발생할 수 있다. 이를 보완하기 위해 버퍼 캐시 등을 활용하지만, 근본적으로 메모리 기반 시스템보다는 느리다.
| 구분 | In-Memory DB (인메모리 DB) | Disk-Based DB (디스크 기반 DB) |
|---|---|---|
| 데이터 저장 위치 | 메모리 (RAM) | 디스크 (HDD/SSD) |
| 접근 속도 | 매우 빠름 (메모리 직접 접근) | 상대적으로 느림 (디스크 I/O 발생) |
| 영속성 | 기본적으로 휘발성 (일부 영속성 옵션 제공) | 기본적으로 영구 저장 보장 |
| I/O 특성 | 디스크 접근 최소화 | 디스크 읽기/쓰기 발생 |
| 장애 시 데이터 보존 | 설정에 따라 손실 가능 | 일반적으로 데이터 유지 |
| 주 사용 목적 | 캐시, 세션 저장, 빠른 조회가 필요한 데이터 | 핵심 비즈니스 데이터 저장 |
| 대표 예시 | Redis, Memcached | MySQL, PostgreSQL, Oracle, MongoDB |
언제 무엇을 사용하면 될까?
- 영구적으로 보존해야 하는 핵심 데이터
- Disk 기반 DB가 적합하다.
- 빠른 조회가 중요하고, 일정 시간이 지나면 사라져도 되는 데이터
- In-Memory DB가 적합하다.
세션 데이터는 로그인 상태와 같은 일시적 정보이며,
요청마다 반복적으로 조회되고 일정 시간이 지나면 자동으로 만료된다.
따라서 세션 저장소로는 빠른 조회에 유리한 In-Memory DB를 사용하는 것이 적절하다.
마무리
세션은 단일 서버 환경에서는 단순하다.
하지만 서버가 여러 대가 되는 순간, 세션은 더 이상 단순한 개념이 아니라 설계의 문제가 된다.
- 사용자 고정 전략 (Sticky)
- 서버 간 복제 전략 (Clustering)
- 저장소 분리 전략 (In-Memory DB)
어떤 방식을 선택하느냐에 따라 서비스의 확장성, 가용성, 운영 비용이 달라진다.
결국 세션은 확장성 관점에서 ‘어딘가에 사용자 상태를 저장해야 한다’는 전제를 깔고 있는 구조다.
이 전제가 존재하는 한, 서버가 늘어날수록 우리는 “상태를 어디에, 어떻게 공유할 것인가?”를 고민하게 된다.
그렇다면 이렇게 생각해볼 수 있지 않을까?
“서버가 사용자 상태를 직접 보관하지 않아도 되는 방법은 없을까?”
만약 서버가 상태를 보관하지 않아도 된다면, 서버 수가 늘어나더라도 세션 공유를 고민할 필요는 없을 것이다.
여기서 등장한 개념이 바로 JWT(JSON Web Token)이다.
다음 글에서는 이 JWT에 대해 알아보자.


