Canva가 1억 세션을 처리하는 방법: S3 기반 세션 폐기 아키텍처
세션 관리는 모든 인증 시스템의 핵심이지만, 규모가 커질수록 세션 폐기(Revocation) 처리는 생각보다 훨씬 복잡한 문제가 된다. 사용자가 로그아웃하거나 보안 이슈로 강제 만료가 필요할 때, 이를 즉시 반영하면서도 수억 건의 요청을 빠르게 처리해야 하기 때문이다. Canva는 1억 개의 활성 세션을 운영하면서 이 문제를 정면으로 마주했고, 기존 DB 중심 구조를 전면 재설계했다.
기존 구조의 한계와 재설계 배경
전통적인 세션 폐기 방식은 요청이 들어올 때마다 데이터베이스를 조회해 해당 세션이 폐기됐는지 확인하는 구조다. 소규모에서는 문제없지만, 트래픽이 급증하면 DB에 가해지는 읽기 부하가 선형적으로 증가한다. Canva의 경우 수억 건의 세션을 DB 조회로 처리하는 건 인프라 비용과 지연 시간 측면 모두에서 한계가 명확했다.
핵심 목표는 두 가지였다. 첫째, 폐기 여부 확인 시 DB 조회를 최소화할 것. 둘째, 폐기 정보를 신뢰성 있게 저장하면서도 빠르게 조회할 수 있는 구조를 만들 것. 이를 위해 Canva는 영속 저장소로 Amazon S3를, 실시간 조회를 위한 레이어로 압축된 인메모리 인덱스를 선택했다.
S3 + 인메모리 인덱스의 분산 아키텍처
Canva의 새로운 구조는 크게 세 계층으로 나뉜다.
- S3 영속 저장소: 폐기된 세션 레코드를 S3에 저장한다. S3는 고가용성과 내구성을 기본 제공하므로 별도 DB 인프라 없이 신뢰할 수 있는 소스 오브 트루스(source of truth) 역할을 한다.
- 압축 인메모리 인덱스: S3에 저장된 폐기 데이터를 기반으로 압축된 인덱스를 빌드하여, 각 애플리케이션 게이트웨이에 분산 배포한다. 요청 처리 시점에는 이 인메모리 인덱스만 조회하므로 DB 왕복이 불필요하다.
- 게이트웨이 로컬 조회: 각 게이트웨이 인스턴스가 폐기 인덱스를 로컬에서 보유하므로, 세션 유효성 확인이 네트워크 I/O 없이 완결된다.
[세션 폐기 요청]
↓
[S3에 폐기 레코드 저장]
↓
[인덱스 빌드 & 압축]
↓
[각 게이트웨이에 인덱스 배포]
↓
[요청 수신 시 로컬 인덱스 조회 → DB 조회 없음]
이 구조에서 세션 폐기 캐시의 메모리 사용량이 87.5% 절감됐다는 점이 인상적이다. 압축 인덱스를 활용해 동일한 데이터를 훨씬 작은 메모리 풋프린트로 표현했기 때문이다.
실무 관점에서의 시사점
이 아키텍처가 흥미로운 이유는 비싼 DB를 S3로 대체했다는 단순한 이야기가 아니라는 점이다. 핵심은 데이터의 접근 패턴을 명확히 분리한 것이다. 폐기 레코드는 쓰기가 드물지만 읽기가 매우 빈번하다. 이런 읽기 헤비(read-heavy) 패턴에서는 데이터를 미리 인덱싱해 각 처리 노드에 분산하는 방식이 중앙화된 DB 조회보다 훨씬 유리하다.
배포 속도 개선도 주목할 만하다. DB 스키마나 인프라 변경 없이 S3에 저장된 데이터와 인덱스 빌드 로직만 업데이트하면 되므로, 운영 복잡도가 줄어든다. Java 백엔드 관점에서 비슷한 설계가 필요하다면, Bloom Filter나 RoaringBitmap 같은 압축 자료구조를 인메모리 인덱스로 활용하는 패턴을 참고할 수 있다.
// 세션 폐기 여부 로컬 인덱스 조회 예시 (개념)
public boolean isRevoked(String sessionId) {
// DB 조회 없이 로컬 인메모리 인덱스 확인
return revocationIndex.contains(sessionId);
}
정리
- S3를 소스 오브 트루스로, 인메모리 인덱스를 게이트웨이에 분산 배포해 DB 조회를 제거했다
- 압축 인덱스 도입으로 폐기 캐시 메모리 사용량 87.5% 절감, DB 인프라 요구사항도 감소했다
- 읽기 헤비한 데이터는 중앙 DB보다 미리 빌드된 로컬 인덱스가 성능·비용 면에서 효과적이라는 점을 실증했다