한 줄 정의
공간 기반 아키텍처
데이터베이스를 트랜잭션 경로에서 제외 하고, 모든 처리 단위가 메모리 내 복제 데이터 그리드 를 통해 데이터를 공유하면서 백그라운드에서 비동기로 DB와 동기화하는, 극단적 확장성·탄력성·동시성 을 위한 아키텍처입니다.
쉽게 말하면
콘서트 티켓팅이나 이베이 경매처럼 “평소엔 한산하다가 특정 순간에 수만 명이 몰리는” 시스템을 위한 아키텍처입니다.
전형적인 웹 시스템에서는 부하가 몰리면 결국 데이터베이스가 병목이 됩니다. 웹 서버를 늘려도 병목은 애플리케이션 서버로, 그다음엔 DB로 옮겨갈 뿐입니다. 공간 기반 아키텍처는 발상을 뒤집습니다. 트랜잭션 처리 경로에서 DB를 아예 빼버리고, 모든 데이터를 메모리에 두고, 처리 단위들끼리 메모리 내용을 자동 복제(replicate)합니다. DB는 백그라운드에서 비동기로 따라오는 기록용 저장소 일 뿐입니다.
이름의 어원은 튜플 공간(tuple space) 입니다. 여러 병렬 프로세서가 공유 메모리를 통해 통신한다는 개념에서 따왔습니다.
왜 이렇게 설계했는가?
- 해결하는 문제: 동시 사용자 부하가 가변적이고 예측 불가능한 시스템에서 DB가 결국 확장의 천장이 되는 구조적 한계 입니다. 전통적인 토폴로지에서 부하 대응책은 웹 서버 → 애플리케이션 서버 → DB 순으로 확장하는 것이지만, 결국은 가장 확장이 어려운 DB가 병목으로 남는 삼각형 구조 가 만들어집니다.
- 이게 없다면: 콘서트 티켓 오픈 직후 수만 명의 동시 좌석 갱신 요청을 일반 RDBMS의 표준 트랜잭션으로 처리하려 하면, DB 락 경합으로 응답 시간이 폭발하고 결국 서비스가 멈춥니다. 이를 캐시 추가, DB 샤딩, 리드 레플리카 등으로 사후 보강 하는 것보다, 처음부터 그런 문제에 특화된 아키텍처를 쓰는 것이 낫다 는 것이 이 스타일의 출발점입니다.
토폴로지
flowchart LR subgraph PU["처리 단위"] direction TB C["컴포넌트"] G["메모리 내 데이터 그리드<br/>(캐시)"] R["데이터 복제 엔진"] C --> G --> R end subgraph VM["가상화된 미들웨어"] direction LR MG["메시징 그리드"] DG["데이터 그리드"] PG["처리 그리드"] DM["배포 관리자"] end PumpOut["데이터 펌프"] Writer["데이터 기록기"] PumpIn["데이터 펌프"] Reader["데이터 판독기"] DB[("데이터베이스")] PU <--> VM PU -- 갱신 --> PumpOut --> Writer --> DB DB --> Reader --> PumpIn -- 적재 --> PU
핵심 발상
데이터는 메모리에 유지 되고 모든 활성 처리 단위 사이에서 복제 됩니다. 한 처리 단위가 데이터를 갱신하면, 그 갱신은 데이터 펌프 를 통해 비동기로 DB에 전송됩니다. 부하가 변하면 시스템은 처리 단위를 동적으로 시동/종료해서 가변 확장성에 대응합니다.
표준 트랜잭션 처리에 중앙 DB가 관여하지 않으므로 DB 병목이 제거되고, 거의 무한에 가까운 확장성을 확보합니다.
핵심 내용
처리 단위 (Processing Unit)
처리 단위(processing unit) 는 애플리케이션 로직 전체 또는 일부를 담습니다. 작은 시스템은 모든 기능을 한 처리 단위에 담고, 큰 시스템은 기능 영역에 따라 여러 처리 단위로 분할합니다(이때 처리 단위가 마이크로서비스와 매우 흡사해집니다).
처리 단위 안에는 다음이 포함됩니다.
- 비즈니스 컴포넌트
- 메모리 내 데이터 그리드(in-memory data grid): 캐시
- 데이터 복제 엔진(data replication engine): 다른 처리 단위와 캐시를 동기화
구현 제품으로는 헤이즐캐스트(Hazelcast), 아파치 이그나이트(Apache Ignite), 오라클 코히어런스(Oracle Coherence) 가 자주 쓰입니다.
가상화된 미들웨어
가상화된 미들웨어(virtualized middleware) 는 처리 단위들을 관리·제어하는 인프라 계층입니다. 단일 제품이 아니라 다수의 서드파티 제품 조합 으로 구성하는 것이 일반적입니다(웹 서버, 캐싱 도구, 부하 분산기, 서비스 오케스트레이터, 배포 관리자 등).
| 구성요소 | 역할 | 흔한 구현 |
|---|---|---|
| 메시징 그리드(Messaging Grid) | 입력 요청과 사용자 세션 상태 관리, 가용 처리 단위로 요청 라우팅 | HA Proxy, Nginx 등 부하 분산기 |
| 데이터 그리드(Data Grid) | 처리 단위 간 데이터 동기화·복제 관리 | Hazelcast 등 (대부분 처리 단위 내부에 분산 구현) |
| 처리 그리드(Processing Grid) | 여러 처리 단위 간 요청 오케스트레이션 (선택적) | 오케스트레이션 처리 단위로 구현 |
| 배포 관리자(Deployment Manager) | 부하에 따른 처리 단위 인스턴스 시작/종료 | Kubernetes 등 |
메시징 그리드의 동작
요청이 가상화된 미들웨어에 들어오면, 메시징 그리드는 그 요청을 처리할 수 있는 활성 처리 단위를 선택해서 전달 합니다. 라운드로빈처럼 단순한 알고리즘부터 처리 단위의 여유 정도를 추적하는 복잡한 알고리즘까지 다양합니다. HA Proxy나 Nginx 같은 일반 웹 서버로 구현하는 것이 보통입니다.
데이터 그리드의 핵심성
가장 중요한 구성요소는 데이터 그리드 입니다. 메시징 그리드가 어느 처리 단위로든 요청을 보낼 수 있으므로, 모든 처리 단위의 메모리 내 데이터가 정확히 동일하게 유지 되어야 합니다. 이 동기화가 무너지면 시스템 전체가 잘못된 데이터를 반환하게 됩니다.
데이터 복제는 처리 단위들 사이에서 비동기적 으로 수행되며, 보통 100ms 이내 에 완료됩니다.
Hazelcast 멤버 목록 예시
각 처리 단위 인스턴스는 같은 이름의 캐시를 가진 다른 인스턴스의 IP/포트를 담은 멤버 목록 을 유지합니다. 새 인스턴스가 시작되면 캐싱 제공자(예: Hazelcast)를 통해 합류 요청을 브로드캐스팅하고, 응답한 인스턴스 중 하나가 캐시 데이터를 새 인스턴스로 전송합니다.
HazelcastInstance hz = Hazelcast.newHazelcastInstance();
Map<String, CustomerProfile> profileCache =
hz.getReplicatedMap("CustomerProfile");CustomerProfile 캐시를 갱신하면, 데이터 그리드가 같은 이름의 캐시를 가진 다른 모든 처리 단위에 갱신 내용을 자동 복제 합니다. 한 인스턴스가 다운되면 다른 인스턴스의 멤버 목록에서도 즉시 제거됩니다.
캐싱 모델: 복제 vs 분산 vs 근접
공간 기반 아키텍처의 트랜잭션 처리는 캐싱에 의존합니다. 캐싱 모델의 선택이 이 아키텍처의 성패를 가르는 핵심 입니다.
복제 캐싱 (Replicated Caching) — 표준 모델
처리 단위마다 개별적인 메모리 내 데이터 그리드 를 두고, 같은 이름의 캐시를 사용하는 모든 처리 단위 사이에서 동기화합니다.
flowchart LR PU1[처리 단위 1<br/>캐시 사본] <-.동기화.-> PU2[처리 단위 2<br/>캐시 사본] PU2 <-.동기화.-> PU3[처리 단위 3<br/>캐시 사본] PU1 <-.동기화.-> PU3
- 장점: 매우 빠르고, 단일 장애점(SPOF) 없음 (캐시 보유 중앙 서버가 없음)
- 한계: 캐시가 100MB 이상으로 커지면 처리 단위 메모리 부담이 커져 인스턴스 수가 제한됨. 갱신율이 너무 높으면 데이터 그리드가 따라가지 못해 일관성 문제 발생
분산 캐싱 (Distributed Caching)
중앙 집중식 외부 캐시 서버에 데이터를 두고, 처리 단위는 전용 프로토콜 로 원격 접근합니다.
flowchart TB PU1[처리 단위 1<br/>클라이언트 라이브러리] PU2[처리 단위 2<br/>클라이언트 라이브러리] PU3[처리 단위 3<br/>클라이언트 라이브러리] PU1 -- 동기 전용 프로토콜 --> Cache[(캐싱 서버)] PU2 --> Cache PU3 --> Cache
- 장점: 데이터가 한곳에 있어 데이터 일관성이 항상 더 높음
- 한계: 원격 접근으로 성능 저하, 캐시 서버가 SPOF, 미러링으로 완화하더라도 미러링 전 다운 시 일관성 문제
복제 vs 분산 결정 기준
| 결정 기준 | 복제 캐시 | 분산 캐시 |
|---|---|---|
| 최적화 대상 | 성능 | 일관성 |
| 캐시 크기 | 작음(<100MB) | 큼(>500MB) |
| 데이터 유형 | 비교적 정적 | 매우 동적 |
| 갱신 빈도 | 낮음 | 높음 |
| 내결함성 | 높음 | 낮음 |
처리 단위마다 다른 모델 가능
애플리케이션 전반에 일관된 캐싱 모델 하나를 강요할 필요가 없습니다. 재고 관리 처리 단위는 데이터 일관성을 위해 분산 캐시, 고객 프로필 처리 단위는 성능을 위해 복제 캐시 — 이런 식으로 처리 단위의 성격에 맞게 골라 쓰는 것이 바람직합니다.
근접 캐시는 권장하지 않음
근접 캐시(near-cache) 는 분산 캐시(전체 후면 캐시)와 메모리 내 데이터 그리드(전면 캐시)를 결합한 하이브리드입니다. 전면 캐시는 MRU(최근 사용), MFU(최빈 사용), 임의 교체 같은 퇴거 정책으로 일부만 유지합니다.
flowchart TB PU1[처리 단위 1<br/>전면 캐시 일부] -.동기화.-> Backing[캐싱 서버<br/>전체 후면 캐시] PU2[처리 단위 2<br/>전면 캐시 일부] -.동기화.-> Backing PU3[처리 단위 3<br/>전면 캐시 일부] -.동기화.-> Backing
문제는 처리 단위들의 전면 캐시가 서로 동기화되지 않는다는 점 입니다. 동일 데이터 컨텍스트를 공유하는 처리 단위들의 성능과 반응성이 일관되지 못하게 됩니다. 이 때문에 공간 기반 아키텍처에서는 근접 캐시를 권장하지 않습니다.
처리 그리드
처리 그리드(processing grid) 는 가상화된 미들웨어의 선택적(생략 가능) 구성요소입니다. 하나의 비즈니스 요청에 유형이 다른 둘 이상의 처리 단위가 협력해야 할 때, 처리 단위들 사이의 오케스트레이션을 관리합니다. 예를 들어 주문 처리 단위와 결제 처리 단위가 함께 작동해야 한다면, 처리 그리드가 두 처리 단위 사이에서 요청을 중재·조율합니다.
현대적인 공간 기반 구현(특히 세분화된 서비스를 갖춘 구현)은 단일 조율 엔진 대신 세분도가 높은 오케스트레이션 처리 단위(orchestration processing unit) 여러 개 로 처리 그리드 기능을 구현합니다. 각 오케스트레이션 처리 단위는 하나의 주요 작업흐름을 전담합니다.
전자상거래 예시
고객이 상품을 주문하면 주문 접수 · 결제 · 재고 조정 세 처리 단위가 협력해야 합니다. 이때 주문 접수 오케스트레이터 라는 오케스트레이션 처리 단위를 만들어 세 처리 단위의 협업을 조율합니다. 반품 처리 나 재고 보충 같은 다른 작업흐름은 각각 별도의 오케스트레이션 처리 단위로 만들 수 있습니다.
배포 관리자
배포 관리자(deployment manager) 는 가상화된 미들웨어의 필수 구성요소 로, 부하 조건에 따라 처리 단위 인스턴스를 동적으로 시작·종료 합니다. 응답 시간과 사용자 부하를 지속적으로 모니터링하면서 부하가 증가하면 새 처리 단위를 시작하고, 감소하면 기존 처리 단위를 종료합니다.
이 동적 인스턴스 관리가 곧 가변적인 확장성(탄력성) 의 본체입니다. 대부분의 클라우드 기반 인프라(AWS, GCP, Azure)와 쿠버네티스 같은 서비스 오케스트레이션 제품이 이 기능을 제공합니다.
데이터 펌프와 데이터 기록기 (DB 동기화)
처리 단위는 DB와 직접 상호작용하지 않으므로, 메모리 내 캐시와 DB 사이를 잇는 비동기 통로 가 필요합니다. 이것이 데이터 펌프(data pump) 와 데이터 기록기(data writer) 입니다.
데이터 펌프
데이터 펌프는 보통 메시징 으로 구현됩니다. 메시징 덕분에 다음이 보장됩니다.
- 비동기 통신
- 전달 보장
- 메시지 영속성 (영속성 대기열로 디스크 저장)
- 메시지 순서 보장(FIFO)
- 처리 단위와 데이터 기록기의 분리 (기록기 다운돼도 처리 단위 작업 중단 없음)
대부분의 공간 기반 아키텍처는 도메인 또는 하위 도메인마다(고객, 재고 등) 전용 데이터 펌프 를 둡니다. 캐시 유형이나 처리 단위 도메인 단위로 더 세밀하게 둘 수도 있습니다.
데이터 기록기 패턴
데이터 펌프에서 받은 메시지로 DB를 갱신하는 구성요소입니다. 두 가지 패턴이 있습니다.
flowchart TB subgraph A["도메인 기반 데이터 기록기"] direction LR PU_A1[프로필<br/>처리 단위] --> P_A1[프로필 펌프] PU_A2[찜목록<br/>처리 단위] --> P_A2[찜목록 펌프] PU_A3[지갑<br/>처리 단위] --> P_A3[지갑 펌프] PU_A4[환경설정<br/>처리 단위] --> P_A4[환경설정 펌프] P_A1 & P_A2 & P_A3 & P_A4 --> CDW[고객 데이터 기록기] CDW --> DB_A[(DB)] end subgraph B["처리 단위별 전용 데이터 기록기"] direction LR PU_B1[프로필<br/>처리 단위] --> P_B1[프로필 펌프] --> W_B1[프로필 기록기] PU_B2[찜목록<br/>처리 단위] --> P_B2[찜목록 펌프] --> W_B2[찜목록 기록기] PU_B3[지갑<br/>처리 단위] --> P_B3[지갑 펌프] --> W_B3[지갑 기록기] PU_B4[환경설정<br/>처리 단위] --> P_B4[환경설정 펌프] --> W_B4[환경설정 기록기] W_B1 & W_B2 & W_B3 & W_B4 --> DB_B[(DB)] end
처리 단위별 전용 데이터 기록기 모델은 기록기 수가 늘어나지만 확장성과 민첩성이 더 뛰어납니다.
데이터 판독기 (DB → 캐시 적재)
데이터 판독기(data reader) 는 DB에서 데이터를 읽어 역방향 데이터 펌프(reverse data pump) 를 통해 처리 단위로 전송합니다. 다음 세 가지 상황에서만 호출됩니다.
- 같은 이름의 캐시를 가진 모든 처리 단위 인스턴스가 다운됐을 때
- 같은 이름의 캐시를 가진 모든 처리 단위가 재배포될 때
- 복제 캐시에 없고 다른 곳에 보관된(archived) 데이터를 가져와야 할 때
콜드 스타트 동작
캐시 적재가 시작되면 한 처리 단위 인스턴스가 캐시에 대한 잠금(lock)을 획득 해 임시 캐시 소유자가 됩니다. 나머지 인스턴스는 잠금이 해제될 때까지 대기합니다. 임시 소유자가 데이터를 요청 → 데이터 판독기가 DB 쿼리 → 역방향 데이터 펌프로 전송 → 적재 완료 후 잠금 해제 → 다른 인스턴스들이 동기화 시작.
데이터 추상화 계층 vs 데이터 접근 계층
데이터 기록기와 판독기는 본질적으로 데이터 추상화 계층(data abstraction layer) 을 형성합니다.
| 계층 | 처리 단위와 DB의 관계 |
|---|---|
| 데이터 접근 계층 | 처리 단위가 DB의 바탕(underlying) 자료 구조와 결합. 판독기·기록기를 통해 DB에 간접 접근 |
| 데이터 추상화 계층 | 별도의 계약을 이용해 처리 단위와 DB 스키마를 분리. DB 변경이 처리 단위에 영향 미치지 않을 수 있음 |
공간 기반 아키텍처는 일반적으로 데이터 추상화 계층 모델 에 의존합니다. 이 덕분에 처리 단위 캐시 스키마를 DB 스키마와 다르게 구성할 수 있고, DB의 점진적 변경이 처리 단위에 반드시 영향을 미치지는 않습니다.
데이터 토폴로지
처리 단위가 DB와 직접 상호작용하지 않으므로, 사용 가능한 DB 토폴로지가 매우 유연합니다. 주된 결정 요인은 시스템이 후면 DB(backing database)를 어떻게 사용하느냐 입니다.
| 상황 | 권장 DB 토폴로지 |
|---|---|
| 보고와 데이터 분석이 중요 | 모놀리스 DB |
| 보고/분석을 데이터 메시(data mesh)로 수행 | 도메인 기반 DB |
| 다운스트림 시스템이 DB 직접 사용 | 모놀리스 DB |
| 도메인별 데이터 분할 가능, 동기화 시간 단축 우선 | 도메인 기반 DB |
클라우드 / 온프레미스 혼합 토폴로지
공간 기반 아키텍처는 클라우드와 온프레미스에 동시 배포 가 가능하다는 독특한 강점이 있습니다. 다른 아키텍처 스타일에서는 찾아보기 어려운 특징입니다.
flowchart TB subgraph Cloud["클라우드 환경"] PUs[처리 단위들] VM[가상화된 미들웨어] PUs --- VM end subgraph OnPrem["온프레미스 환경"] Reader[데이터 판독기] Writer[데이터 기록기] DB[(데이터베이스)] Reader --> DB Writer --> DB end Cloud -.데이터 펌프.-> OnPrem OnPrem -.역방향 데이터 펌프.-> Cloud
- 트랜잭션 처리 (탄력적 부하): 관리형 클라우드 환경
- 물리적 데이터 관리·보고·분석 (보안 민감): 온프레미스
- 비동기 데이터 펌프와 최종 일관성 모델 덕분에 이런 혼합이 자연스럽게 가능
일반적인 위험
빈번한 데이터베이스 읽기
공간 기반 아키텍처의 확장성·동시성은 모든 트랜잭션 데이터를 캐싱하기 때문 입니다. DB 작업이 많으면 시스템의 전반적인 확장성·탄력성·반응성이 낮아져, 이 스타일의 장점이 발휘되지 못합니다.
적합하지 않은 시나리오
보관된 데이터(주문 내역, 과거 은행 거래 명세서 등)를 자주 읽거나, 콜드 스타트 시 캐싱할 데이터양이 너무 많거나, 처리 단위가 자주 다운/재배포되는 도메인에는 이 아키텍처가 적합하지 않습니다.
데이터 동기화와 일관성
데이터 펌프는 메모리 내 캐시와 DB 사이의 동기화를 책임지지만, 동시 사용자 부하가 매우 높을 때 데이터 펌프 자체가 병목 이 되기 쉽습니다.
- DB 도달 시간 지연 → 다운스트림 시스템이 갱신 데이터를 늦게 받음
- 영속성 대기열로 데이터 유실 위험은 완화 가능
- 클라이언트 확인(client-acknowledgment) 모드로 안정성 ↑, 단 반응성·일관성과 트레이드오프
대용량 데이터
모든 트랜잭션 메모리가 처리 단위 안에 캐싱되므로, 데이터 용량을 비교적 낮게 유지 해야 합니다. 메모리 부족으로 처리 단위가 다운되는 것을 피하려면 캐시 크기에 세심한 주의가 필요합니다.
데이터 충돌 (Data Collision)
복제 캐싱을 활성/활성(active/active) 상태로 운용할 때 발생하는 가장 까다로운 위험 입니다. 한 캐시(A)가 갱신되어 다른 캐시(B)로 복제되는 도중에, B에서 동일 데이터가 갱신되어 데이터 일관성이 깨지는 현상입니다.
충돌 시나리오 (재고 갱신 예)
| 단계 | 인스턴스 A | 인스턴스 B |
|---|---|---|
| 1 | 재고 500 | 재고 500 |
| 2 | 10개 구매 → A의 캐시 490 | 재고 500 |
| 3 | A의 데이터가 B로 복제되기 전 | 5개 구매 → B의 캐시 495 |
| 4 | A 캐시(490)가 B로 복제 → B는 490 | (덮어쓰임) |
| 5 | B 캐시(495)가 A로 복제 → A는 495 | |
| 6 | 올바른 값은 485, 그러나 두 캐시 모두 부정확 |
충돌률 공식
충돌률 = N · UR² / S · RL
- N: 같은 이름의 캐시를 사용하는 서비스 인스턴스 수
- UR: 캐시 갱신율 (UR이 제곱인 이유는 충돌에 두 개의 캐시가 관여하기 때문)
- S: 캐시 크기 (행 수)
- RL: 복제 지연시간
기준값 계산 예 (시간당 72,000회 갱신)
| 변수 | 값 | 충돌률 | 비율 |
|---|---|---|---|
| 기본 (UR 20/s, N 5, S 50,000, RL 100ms) | — | 시간당 14.4회 | 0.02% |
| RL을 100ms → 1ms 로 단축 | 복제 빨라짐 | 시간당 0.1회 | 0.0002% |
| 인스턴스 수 5 → 2 로 축소 | 복제 대상 ↓ | 시간당 5.8회 | 0.008% |
| 캐시 크기 50,000 → 10,000 으로 축소 | 충돌 가능성 ↑ | 시간당 72.0회 | 0.1% |
캐시 크기는 충돌률과 반비례
캐시 크기는 충돌률과 반비례하는 유일한 요소 입니다. 캐시가 작을수록 같은 키에 대한 갱신이 겹칠 확률이 커집니다. 인스턴스 수, 갱신율, 복제 지연시간은 모두 충돌률에 정비례합니다.
이 공식은 시스템 부하의 최대(peak)·평균·최소 시점별로 충돌률을 추정해 복제 캐싱이 실행 가능한 선택지인지 판단하는 데 사용합니다.
거버넌스
공간 기반 아키텍처는 ‘움직이는 부품’이 많아 적절한 거버넌스 없이는 운영이 어렵습니다. 핵심은 지속적·자동화된 거버넌스 적합성 함수(fitness function) 작성입니다.
메모리 사용량 추적
처리 단위 인스턴스가 자신의 현재 메모리 사용량을 주기적으로 보고하게 합니다. 적합성 함수는 메모리 사용이 임계치를 넘는 처리 단위 이름만 보고하면 됩니다. 별도 함수로 인스턴스 수를 기록해 처리 단위당 총 메모리 소비량을 계산합니다.
동기화 시간 추적
캐시가 갱신된 순간부터 DB가 갱신되기까지의 시간을 측정합니다. 갱신 요청에 타임스탬프 + 요청 ID 를 붙이고, DB 커밋 시점에 같은 요청 ID로 다시 타임스탬프를 기록한 뒤 차이를 계산합니다. 이 추세를 분석해 아키텍처 변경의 효과를 추적합니다.
데이터 펌프 백프레셔 추적
데이터 펌프는 배압 지점(backpressure point) 역할을 하므로 시스템 전체의 병목이 될 수 있습니다. 데이터 펌프 대기열의 깊이를 추적하는 적합성 함수 를 작성합니다. 병목이 심해지면 동기화 시간이 늘어나고, 데이터 손실 및 데이터 충돌 가능성이 커집니다.
그 외 추적 대상
- DB 읽기(데이터 판독기 호출) 빈도
- 확장성, 탄력성, 반응성 측정 — 이 아키텍처를 선택한 주된 이유 이므로 추적이 합당함
팀 토폴로지 고려 사항
공간 기반 아키텍처는 특정 도메인을 구성하는 요소들이 기술적으로 분할 된 경우가 많습니다(처리 단위, 데이터 펌프, 데이터 판독기·기록기, 백엔드 DB). 그래서 대체로 기술 분할 방식을 따르는 아키텍처 로 간주됩니다.
| 팀 유형 | 적합도 | 이유 |
|---|---|---|
| 스트림 정렬 팀 (기능 전담 팀) | 낮음 | 기술적 분할 때문에 단일 스트림 기반 변경이 처리 단위, 데이터 펌프, 판독기, 기록기, 캐시 계약, 오케스트레이터, DB까지 영향. 시스템이 클수록 효율성 떨어짐 |
| 활성화 팀 (역량 코칭 팀) | 높음 | 데이터 펌프·판독기·기록기·가상화 미들웨어가 여러 영역에 걸치고 여러 처리 단위에 공유됨. 특정 구성요소를 전담하는 팀이 다른 팀과 독립적으로 실험·개선 가능 |
| 난해한 하위시스템 팀 (전문 도메인 팀) | 높음 | 데이터 그리드나 데이터 펌프처럼 극도로 복잡한 부분에 집중. 데이터 충돌·비동기 동기화 오류는 기능적 도메인 팀보다 전문 팀이 처리하는 편이 바람직 |
| 플랫폼 팀 (공통 기반 팀) | 높음 | 데이터 펌프·가상화 미들웨어가 플랫폼의 일부로 간주되면 모든 팀이 공통 도구·서비스의 혜택을 누릴 수 있음 |
장단점
| 아키텍처 특성 | 평가 |
|---|---|
| 전반적인 비용 | 매우높음($$$$) |
| 분할 방식 | 기술적 |
| 퀀텀 개수 | 1 이상 |
| 단순성 | ★☆☆☆☆ |
| 모듈성 | ★★★☆☆ |
| 유지보수성 | ★★★☆☆ |
| 테스트성 | ★☆☆☆☆ |
| 배포성 | ★★★☆☆ |
| 진화성 | ★★★☆☆ |
| 반응성 | ★★★★★ |
| 확장성 | ★★★★★ |
| 탄력성 | ★★★★★ |
| 내결함성 | ★★☆☆☆ |
반응성·확장성·탄력성 ★★★★★
이 세 특성에 모두 만점을 받은 유일한 아키텍처 스타일 입니다. 이 조합이 극대화되는 것이 공간 기반 아키텍처를 선택하는 주된 이유입니다. 메모리 내 캐싱을 활용하고 DB를 제약조건에서 제외한 덕분에, 수백만 명의 동시 사용자 를 처리할 수 있는 수준입니다.
단순성 ★☆☆☆☆ / 테스트성 ★☆☆☆☆
장점에 대한 트레이드오프입니다. 캐싱 사용으로 최종적인 기록 시스템(system of record) 의 일관성을 별도로 보장해야 하고, 움직이는 부품이 많아 충돌 시 데이터 손실 방지에 특별한 주의가 필요합니다.
테스트성이 별 1개인 이유는 높은 확장성·탄력성을 테스트 환경에서 시뮬레이션하기가 매우 어렵기 때문 입니다. 수십만 동시 사용자 테스트는 비용이 많이 들고, 결국 실제 프로덕션의 극단적 부하에서 검증되는데 이는 운영 위험을 동반합니다.
비용
공간 기반 아키텍처는 전반적으로 가장 비싼 아키텍처 중 하나 입니다.
- 캐싱 제품 라이선스 비용
- 높은 확장성·탄력성을 지원하기 위한 클라우드/온프레미스 자원 비용
- 시스템 자체의 복잡성 비용
내결함성 ★★☆☆☆
별 2개에 그치는 이유는 데이터 충돌, 비동기 동기화 실패, 데이터 펌프 손실 등의 위험 요인 때문입니다.
퀀텀 개수
처리 단위는 DB와 동기적으로 통신하지 않으므로, DB 자체는 퀀텀 수 계산에 포함되지 않습니다. 결과적으로 퀀텀들은 다양한 UI와 처리 단위 간의 연관성을 기준으로 경계가 정해지는 것이 보통입니다.
적합한 상황
사용하면 좋은 경우
- 사용자 수나 요청량이 급증 하는 애플리케이션
- 10,000명 이상의 동시 사용자 를 위한 처리량 요구
- 사용자 부하가 가변적이고 예측 불가능 한 시스템
- DB가 트랜잭션 처리량의 상한을 결정짓는 시스템에서 그 천장을 뚫어야 할 때
사용하지 말아야 할 경우
- DB 읽기가 빈번한 도메인 (보관 데이터 조회 중심)
- 처리 단위가 자주 다운/재배포 되는 도메인 (콜드 스타트 비용 ↑)
- 캐싱할 데이터양이 너무 커서 대부분의 데이터를 후면 DB에 보관 해야 하는 도메인
- 강한 동기적 ACID 트랜잭션 이 핵심 요구사항인 시스템
- 동시 사용자가 적고 단순함이 더 중요한 일반적인 비즈니스 애플리케이션
예시
콘서트 티켓팅 시스템
평소엔 동시 사용자가 수백 명이지만, 인기 연예인 콘서트 티켓 판매가 시작되면 수천~수만 명 으로 급증하고, 모두가 더 좋은 좌석을 잡으려 동시에 갱신을 시도합니다. 티켓은 몇 분 안에 매진됩니다.
왜 공간 기반 아키텍처인가?
- 좌석 현황은 매우 빠르게(수만 건의 동시 갱신) 갱신되어야 함
- 표준 RDBMS 트랜잭션으로 이 부하를 처리하는 것은 사실상 불가능
- 배포 관리자 를 티켓 판매 시작 직전에 가동하도록 설정 → 부하 급증 직전에 처리 단위들이 이미 대기 상태
- 사용자 부하 폭증을 즉시 인지해 대량 처리 단위를 추가 시작
- 메모리 내 데이터 그리드로 좌석 상태를 동기화하면서 동시 갱신 처리
온라인 경매 시스템 (이베이 등)
평소 부하는 낮지만 경매 시작 시점부터 종료까지 호가(asking price)마다 동시 입찰이 폭증합니다. 얼마나 많은 사람이 참여할지, 호가마다 동시 입찰이 얼마나 발생할지 예측 불가능 합니다.
왜 공간 기반 아키텍처인가?
- 부하 증가 시 다수의 처리 단위 시작, 경매 막바지에 처리량 적어지면 처리 단위 제거
- 각 경매에 개별적인 처리 단위를 배정 함으로써 입찰 데이터의 일관성 보장
- 데이터 펌프가 비동기 → 입찰 내역, 입찰 분석, 감사 등 다른 처리로 보낼 때 거의 지연 없음
비교 / 트레이드오프
| 스타일 | 공통점 | 차이점 |
|---|---|---|
| Ch14 서비스 기반 아키텍처 | 분산 아키텍처 | 서비스 기반은 단순·저렴함이 강점, 공간 기반은 극단적 확장성·탄력성이 강점. 서비스 기반은 DB 공유, 공간 기반은 DB를 트랜잭션 경로에서 제외 |
| Ch15 이벤트 주도 아키텍처 | 비동기 메시징 활용 (데이터 펌프) | 이벤트 주도는 비즈니스 이벤트 흐름이 본질, 공간 기반은 메모리 내 데이터 그리드가 본질. 결합도 더 클 수 있음 |
| Ch18 마이크로서비스 아키텍처 | 분산, 동적 인스턴스 관리 | 마이크로서비스는 도메인 분할, 공간 기반은 기술 분할. 마이크로서비스는 DB 분할/서비스별, 공간 기반은 캐시 중심·DB 비동기 |
다른 아키텍처와의 결정적 차이
공간 기반의 유일성
반응성·확장성·탄력성의 조합이 극대화되는 아키텍처 스타일은 공간 기반뿐입니다. 주로 캐싱을 활용하고 DB에 직접 접근하지 않는 점 때문입니다. 이 세 가지를 모두 별점 5개로 받은 다른 스타일은 없습니다.
내 생각
- 이 아키텍처는 “DB가 결국 병목이 된다” 는 명제를 가장 정직하게 받아들인 설계입니다. 다른 분산 아키텍처는 캐시 추가, 샤딩, CQRS 같은 사후 조치로 DB 병목을 우회하지만, 공간 기반은 처음부터 DB를 트랜잭션 경로에서 빼버립니다. 사용 시나리오는 좁지만 그 시나리오에서는 압도적 입니다.
- 한국에서 떠올리기 좋은 사례는 인터파크/예스24 콘서트 티켓팅, 네이버 라이브 커머스의 한정 수량 판매, 백화점 명품 오픈런 예약, 국세청 5월 종합소득세 신고 마감 직전 입니다. 모두 평소엔 한산하다가 특정 순간에 폭증하는 패턴입니다. 이런 시스템에 일반 RDBMS 트랜잭션으로 대응하다가 매번 장애가 나는데, 공간 기반은 정확히 이 문제의 해법으로 설계된 셈입니다.
- 데이터 충돌 공식이 매우 실용적 입니다.
N · UR² / S · RL— 인스턴스 수와 갱신율, 캐시 크기, 복제 지연시간 네 변수만으로 복제 캐싱의 가능성을 사전 계산할 수 있습니다. 콘서트 티켓팅 같은 케이스는 갱신율이 너무 높아서 복제 캐싱이 위험할 수 있고, 좌석별로 처리 단위를 격리하거나 분산 캐싱을 섞는 식의 설계가 필요할 수 있습니다. - 가장 큰 장벽은 운영 역량 입니다. Hazelcast/Ignite/Coherence 같은 IMDG 제품을 운영해본 사람이 매우 적고, 이 제품들의 라이선스 비용도 만만치 않습니다. AWS ElastiCache나 Redis Cluster로 분산 캐시 모델만 차용하는 형태 가 현실적인 절충안일 수 있습니다.
- 테스트성이 별 1개라는 사실을 절대 가볍게 보면 안 됩니다. 수십만 동시 사용자 부하 테스트는 사실상 프로덕션에서만 검증되는데, 이는 곧 첫 부하 폭증 때 장애 가능성이 매우 높다는 뜻입니다. 카오스 엔지니어링 + 점진적 트래픽 증가 시뮬레이션 + 사전 워밍업 이 거의 필수 운영 절차가 됩니다.
- 근접 캐시를 권장하지 않는 이유가 흥미롭습니다. “같은 데이터 컨텍스트를 공유하는 처리 단위들의 전면 캐시가 동기화되지 않는다” 이는 표면적으로는 사소해 보이지만, 사용자가 같은 페이지를 새로고침할 때마다 다른 가격이 보이는 현상으로 이어질 수 있습니다. 캐싱 모델 결정은 비즈니스 사용자 경험과 직결됩니다.
더 알아볼 것
- Hazelcast로 복제 캐시 vs 분산 캐시 비교 PoC 구성
- Apache Ignite SQL 기능으로 메모리 내 데이터 그리드를 SQL로 쿼리하는 패턴
- 데이터 충돌 공식을 실제 시스템 메트릭에 적용해 충돌률 시뮬레이션
- AWS ElastiCache(Redis Cluster) 기반의 “공간 기반 라이트” 아키텍처 구성 가능성
- Kubernetes HPA + Hazelcast 자동 멤버 디스커버리 연동
- 콘서트 티켓팅 시스템의 좌석 락 전략 (페시미스틱 vs 옵티미스틱 vs 좌석별 처리 단위 격리)
- 카오스 엔지니어링으로 처리 단위 다운 시 데이터 펌프 백프레셔 검증
관련 개념
출처
- 마크 리처즈, 닐 포드, 『소프트웨어 아키텍처 The Basics』, 16장 공간 기반 아키텍처 스타일