참조 아키텍처: 3계층 OLTP 애플리케이션
전형적인 업무 애플리케이션(주문, 결제, 재고)은 짧고 단일 행이며 일관성이 핵심인 다수의 트랜잭션(OLTP)을 실행한다. 이 트리는 부하 프로필 식별에서 출발해 주 관계형 데이터베이스, 커넥션 풀러, 읽기 복제본, 캐시 계층, 백업 + PITR, 모니터링을 언제 도입할지 단계별로 보여 준다. 목표는 '처음부터 모든 것을 추가'하는 것이 아니라 각 병목이 입증될 때 올바른 구성 요소를 추가하는 것이다.
부하 프로필은 무엇인가: 트랜잭션 구성과 일관성 요구 사항은?
OLTP 아키텍처의 첫 결정은 워크로드가 정말 트랜잭션 중심인지(ACID가 필요한 짧은 쓰기와 읽기의 혼합) 여부다. 데이터가 본질적으로 관계형이고 일관성이 핵심인가(금액, 재고, 주문), 워크로드가 대부분 읽기인가, 아니면 부하가 아직 매우 낮은가?
- 짧은 트랜잭션, 강한 일관성(금액/재고/주문)
- 읽기가 압도적이고 쓰기는 적으며 트래픽이 증가 중
- 부하가 매우 낮음, 가장 단순한 구성으로 충분한가?
주 데이터베이스 엔진을 선택했는가, 확장이 걱정되는가?
트랜잭션 핵심에는 관계형 엔진이 올바른 기반이다(PostgreSQL, MySQL/InnoDB, Oracle, SQL Server). 엔진 선택이 명확해지면 다음 질문은 확장이다: 지금은 단일 인스턴스로 충분한가, 아니면 연결 수와 읽기 부하가 증가하고 있는가?
- 엔진은 정해졌고, 지금은 단일 인스턴스로 충분함
- 연결 수가 급증했고 리소스가 부족함
- 읽기 부하가 증가해 주 쓰기 인스턴스를 압박함
읽기를 어떻게 확장할 것인가: 복제본인가, 캐시인가?
읽기 부하가 주 인스턴스를 압박한다면 상호 보완적인 두 가지 옵션이 있다. 보고서/목록처럼 약간 지연된 데이터를 허용하는 읽기는 읽기 복제본으로 라우팅할 수 있고, 같은 '핫' 데이터가 반복해서 요청된다면 마이크로초 지연의 캐시(Redis)가 DB 부담을 덜어 준다.
- 보고서/목록 읽기가 많음, 약간의 지연은 허용
- 같은 인기 데이터를 반복해서 읽음
권장: 단일 primary + 풀 + 백업으로 시작
초기에는 아키텍처를 단순하게 유지한다: 단일 관계형 primary 인스턴스, 그 앞단의 커넥션 풀, 정기 백업으로 충분하다. 측정된 병목이 요구할 때만 복잡성을 더한다.
권장: 커넥션 풀러 추가
OLTP에서 모든 애플리케이션 인스턴스가 자체 연결을 열면 주 DB는 수천 개의 연결에서 메모리와 스케줄러 오버헤드로 마비된다. 중간에 풀러를 두면 소수의 실제 DB 연결을 다수의 애플리케이션 요청이 공유한다.
권장: 읽기 복제본 추가
쓰기는 primary에 유지하고, 읽기 전용 트래픽(보고서, 목록, 검색)은 primary에서 공급받는 하나 이상의 비동기 복제본으로 라우팅한다. 이로써 primary는 쓰기와 일관성이 핵심인 읽기에 집중할 수 있다.
권장: 캐시 계층 추가(Redis)
같은 인기 데이터(세션, 카탈로그, 프로필, 페이지 조각)를 반복해서 읽는다면 DB 앞단에 인메모리 캐시를 두어 대부분의 읽기를 DB에 도달하지 않고 처리한다. 지연이 줄고 주 DB 부담이 덜어진다.