OLTP, OLAP, ETL, ...OTL

Twalla·2026년 5월 15일

학습 정리

목록 보기
2/2
post-thumbnail

들어가며

이번 글에서는 OLAP, OLTP, ETL에 대해서 학습한 내용을 정리해보려 한다. 학습 키워드는 선배 백엔드 개발자분께서 던져주셨다.

학습 레퍼런스는 아래와 같다.

[YouTube] ETL이란 무엇인가 | 데이터 웨어하우스란 무엇인가 | OLTP 대 OLAP

mysql binlog를 알아보자

핵심 개념 정리

OLTP (Online Transaction Processing)

고객의 실시간 거래 정보를 처리하는 시스템이다. 서비스 운영에 필수적인 시스템으로, 데이터의 무결성과 빠른 트랜잭션 처리가 중요하다.

OLAP (Online Analytical Processing)

비즈니스 의사결정을 위해 데이터를 분석하는 시스템이다. 운영 시스템(OLTP)에 부하를 주지 않으면서 대용량 데이터를 처리하여 통찰력을 얻는 것이 목적이다.

Data Warehouse

조직 내 다양한 소스에서 생성된 데이터를 모아 분석용으로 저장하는 통합 저장소이다.

ETL 프로세스

데이터를 운영 시스템에서 분석 시스템으로 옮기는 과정을 말하며, 다음과 같이 3단계로 진행된다.

  1. Extract (추출): 여러 소스(MySQL, Oracle, 클라우드 스토리지 등)에서 데이터를 가져온다.

  2. Transform (변환): 분석하기 좋게 데이터를 가공한다. (예: 통화 단위 통일, 데이터 집계, null 값 제거, 오류 수정 등)

  3. Load (적재): 가공된 데이터를 데이터 웨어하우스에 저장한다.

왜 이렇게 분리하나요?

운영 중인 DB(OLTP)에서 직접 복잡한 분석 쿼리를 실행하면 시스템 성능이 저하되어 고객 서비스에 차질이 생긴다. 따라서 이를 별도의 분석용 저장소(OLAP/데이터 웨어하우스)로 복사하여 분석하는 것이 표준적인 방법이다.

사용되는 Tool

  • ETL: Apache NiFi (오픈소스), Talend, Informatica 등

  • Data Warehouse: Teradata, Amazon Redshift, Snowflake, Greenplum 등

이 도구들은 기업이 데이터에 기반한 현명한 경영 전략을 세우는 데 필수적인 기초 토대다.

MySQL을 데이터 웨어하우스로 사용하는 것도 가능하다. 하지만 Greenplum 같은 상용 도구를 활용하면 대규모 병렬 처리 같은 실용적인 솔루션을 활용할 수 있다.

Deep Dive

대규모 회사에 가면 '데이터 플랫폼 팀'이나 '데이터 엔지니어/분석가'가 따로 있어서 OLAP 인프라나 대규모 ETL 파이프라인을 전담해 준다. 즉 백엔드 개발자가 BigQuery 튜닝까지 깊게 할 일은 별로 없다.

하지만, 대기업이든 스타트업이든 데이터가 생성되는 시작점(OLTP)과 데이터 파이프라인의 입구(Extract)는 백엔드 개발자의 영역이다.

따라서 백엔드 관점에서 Deep Dive 하기 좋은 핵심 키워드 2개를 학습해보려 한다.

CDC와 DB Log

데이터 팀이 OLAP로 데이터를 가져가려면, 백엔드가 관리하는 운영 DB에서 데이터를 추출해야 한다. 그런데 데이터 팀이 매달, 혹은 매시간 운영 DB에 SELECT 쿼리를 긁어가면 운영 서버가 뻗어버릴 것이다.

CDC (Change Data Capture) 란?

CDC는 데이터베이스의 데이터 변경 사항(Insert, Update, Delete)을 실시간으로 감지하여 다른 시스템(OLAP, 캐시 서버, 검색 엔진 등)으로 전달하는 기술이다.

과거에는 분석용 데이터를 모으기 위해 새벽 시간에 SELECT * FROM table WHERE updated_at >= ... 같은 무거운 배치 쿼리를 가동했다. 하지만 이 방식은 두 가지 치명적인 문제가 있다.

  1. 운영 DB 부하: 대량의 데이터를 조회하는 순간 DB CPU가 높아지고 서비스가 마비될 수 있다.

  2. 실시간성 부재: 데이터가 이동하는 주기(예: 하루 1번)만큼 분석 데이터의 시차가 발생한다.

CDC는 이러한 문제를 해결하기 위해, 운영 DB에 직접적인 쿼리를 날리지 않고 'DB가 일을 하면서 남긴 흔적'을 뒤에서 몰래 읽어가는 방식을 취한다. 덕분에 운영 서버에 가해지는 부하를 최소화하면서도, 밀리초 단위의 실시간 데이터 동기화를 달성할 수 있다.

WAL(Write-Ahead Logging)과 데이터 저장 메커니즘

CDC가 어떻게 운영 DB에 부하를 주지 않고 데이터를 가져오는지 이해하려면, 먼저 DB가 데이터를 디스크에 쓰는 본질적인 메커니즘인 WAL을 알아야 한다.

많은 주니어들이 "사용자가 데이터를 저장하면 DB가 즉시 디스크의 테이블 스페이스에 데이터를 쓴다"고 착각하곤 한다. 하지만 디스크 I/O는 컴퓨터 부품 중 가장 느린 작업이기 때문에, 매번 디스크의 무작위 위치(Random Access)에 데이터를 쓰면 DB는 엄청난 병목에 빠지게 된다.

그래서 관계형 데이터베이스는 다음과 같은 순서로 일을 처리한다.

  1. 메모리 버퍼 갱신: 사용자의 쓰기 요청이 오면, 메모리(Buffer Pool)에 있는 데이터 페이지를 먼저 수정한다.

  2. 로그 선행 기록 (WAL): 메모리 변경 사항을 디스크의 로그 파일에 순차적(Sequential Append-Only)으로 빠르게 기록한다.

  3. 지연 플러시 (Checkpointer): 디스크에 로그가 안전하게 기록되면 사용자에게 "성공"을 반환하고, 실제 데이터 페이지를 디스크의 테이블 스페이스에 반영하는 작업은 나중에 백그라운드 프로세스가 모아서 처리한다.

즉, DB는 실질적으로 디스크의 본 데이터 테이블에 값을 쓰기 전에, 반드시 로그부터 디스크에 기록(Write-Ahead)한다. 크래시가 나더라도 이 로그를 보고 복구(Redo/Undo)할 수 있기 때문이다.

CDC는 바로 이 "안전을 위해 남겼던 로그"를 읽어서 데이터를 추출하는 기술이다. 이미 디스크에 순차적으로 쓰여 있는 로그 파일만 읽어가니, 운영 중인 DB 엔진에는 아무런 부담을 주지 않는다.

MySQL Binlog의 내부 구조와 동작 방식

MySQL(InnoDB 엔진) 환경에서 CDC를 구현할 때 가장 핵심이 되는 로그가 바로 Binlog (Binary Log)다.

InnoDB 내부의 복구를 위한 로그가 Redo Log라면, Binlog는 MySQL 서버 레이어에서 관리하는 로그로, 데이터베이스에 가해진 모든 구문적,실제적 변경 사항이 Binary 형태로 기록된다.

Binlog의 3가지 Logging Format은 아래와 같이 비교해볼 수 있다.

  1. Statement-Based Logging (SBL)
  • 원리: 변경을 일으킨 SQL 문장 자체를 그대로 로그에 기록한다. (예: UPDATE users SET status = 'active' WHERE id = 5;)

  • 특징: SQL 문장만 적으니 로그 파일 용량이 매우 작다.

  • CDC 관점의 치명적 한계: UUID(), NOW() 같은 비결정적 함수가 포함된 쿼리는 실행할 때마다 결과가 달라져서, 이 로그를 기반으로 대상을 추출하면 데이터 불일치가 발생할 수 다. 그래서 CDC 환경에서는 거의 쓰이지 않는다.

  1. Row-Based Logging (RBL)
  • 원리: SQL 문장이 아니라, 실제 변경된 Row의 Before/After 데이터 자체를 바이너리 형태로 기록한다. (예: "5번 유저의 status 컬럼 값이 'inactive'에서 'active'로 변경됨")

  • 특징: 데이터가 어떻게 변했는지가 명확하게 물리적으로 기록되므로 가장 안전하고 정확하다.

  • CDC 관점의 장점: Debezium 같은 현대적인 CDC 도구들은 모두 이 Row-Based 구조를 기반으로 움직인다. SQL을 파싱할 필요 없이 "어떤 테이블의 어떤 값이 변했다"는 데이터 이벤트(Change Event)를 직관적으로 캡처할 수 있기 때문이다. 단, 대량 업데이트 발생 시 로그 용량이 커진다는 단점이 있다.

  1. Mixed-Based Logging (MBL)
  • 기본적으로 Statement 방식을 쓰되, 데이터 불일치 우려가 있는 쿼리(UUID, 데이터 랜더링 등)만 자동으로 Row 방식으로 기록하는 혼합형이다.

Debezium & Kafka를 통한 실시간 CDC 아키텍처

이제 이 로그를 안전하게 가공하여 OLAP로 전달하는 파이프라인의 핵심 도구인 Debezium과 Kafka의 역할을 알아보자.

Debezium: Binlog의 실시간 리스너

Debezium은 분산 오픈소스 CDC 플랫폼이다. MySQL의 소스 코드를 변형하는 것이 아니라, 외부에서 MySQL의 Replica(Slave) 서버인 것처럼 위장해서 데이터베이스에 접속한다.

MySQL 서버 입장에서는 Debezium을 그저 "데이터를 복제해 가려는 또 다른 MySQL"로 인식하고, Binlog에 새 로그가 찍힐 때마다 스트리밍 방식으로 쏴준다.

Debezium은 이 바이너리 로그를 실시간으로 가로채서 사람이 읽을 수 있는 JSON 이벤트를 생성한다.

Apache Kafka: 데이터 충격 완화장치 (Message Broker)

보통 Debezium이 추출한 변경 이벤트를 OLAP DB에 직접 밀어 넣지 않고, 중간에 Kafka라는 메시지 큐에 먼저 저장한다. 왜 굳이 카프카를 사이에 둘까?

  • 결합도 분리: 백엔드/소스 DB는 타겟 OLAP가 BigQuery인지, Snowflake인지, 혹은 장애로 죽어 있는지 신경 쓸 필요가 없다. 오직 카프카에 던지기만 하면 끝이다.

  • 속도 차이 극복: 소스 DB에서 초당 만 건의 Write가 일어나서 CDC 이벤트가 쏟아지는데, 타겟 OLAP가 그 속도를 못 받아내면 시스템이 터질 것이다. 카프카는 중간에서 이 이벤트를 쌓아두고, 타겟 시스템이 자신이 처리할 수 있는 속도로 안전하게 가져가도록(Pull 방식) 제어해준다.

실무에서의 Trade-off: CDC가 항상 정답일까?

실제 대규모 서비스에서 CDC를 도입할 때는 많은 비용과 리스크를 감수해야 한다.

CDC 도입 시 발생할 수 있는 문제점

  • 치명적인 인프라 비용과 관리 공수: Debezium을 띄우려면 Kafka Connect가 필요하고, 카프카 클러스터도 유지해야 한다. 실무용 DB와 카프카는 매우 비싼 자원이다. 서버가 늘어난다는 건 관리 포인트, 모니터링 시스템, 장애 포인트가 몇 배로 늘어남을 뜻한다.

  • 스키마 변경(Schema Migration)의 지옥: 서비스가 성장하면서 백엔드 개발자가 운영 DB의 테이블 컬럼명을 바꾸거나 타입을 변경(ALTER TABLE)하면 어떻게 될까? Binlog의 형태가 바뀌는 순간 CDC 파이프라인은 에러를 뿜으며 멈춰버린다. 데이터 팀과 싱크를 맞추지 않으면 매번 장애가 날 것이다.

  • 과도한 네트워크 I/O와 트래픽 비용: 소스 DB에서 대량의 배치 작업이나 더티 데이터 삭제 작업이 일어나면, 굳이 OLAP에 안 가도 되는 수천만 건의 데이터가 Binlog에 기록되고, 이게 전부 카프카 네트워크 트래픽 비용으로 청구된다.

그렇다면 대안은 무엇인가?

실무에서는 데이터의 '실시간성'이 정말 1분 1초를 다투는 도메인(예: 금융 이상거래 탐지, 실시간 커머스 랭킹)이 아니라면, 다음과 같은 대안을 훨씬 많이 쓴다.

  • 전통적인 Query-Based Batch

    • 방법: 새벽 3시처럼 사용자가 가장 적은 시간에 Airflow 같은 스케줄러를 돌려 WHERE updated_at >= NOW() - INTERVAL 1 DAY 쿼리로 변경분만 긁어오는 방식

    • 장점: 카프카, Debezium이 필요없다. 인프라 비용이 없고 구조가 단순해서 유지보수가 편하다. 실무에서는 "실시간이 정말 필요한가? 하루 전 데이터면 충분하지 않나?"라는 질문으로 타협하고 이 방식을 많이 선택한다.

  • Application-Level Event Publishing

    • 방법: DB 로그를 훔쳐보는 게 아니라, 백엔드 애플리케이션 로직 내부(Java/Spring Boot 등)에서 비즈니스가 성공했을 때 분석용 이벤트를 직접 카프카나 AWS SQS로 쏴주는 방식

    • 장점: DB 레이어에 아예 손을 대지 않고 백엔드 개발자가 코드로 제어할 수 있어서 스키마 변경에 유연하게 대처할 수 있다.

아웃박스 패턴과 멱등성

백엔드에서 "주문 완료"라는 트랜잭션이 성공하면 해당 데이터를 데이터 팀이나 다른 마이크로서비스로 보내야 한다. 그런데 DB 저장에는 성공했는데, 네트워크가 끊겨서 데이터 전송에 실패하면 어떻게 될까? 운영 DB 데이터와 분석계 데이터가 꼬이기 시작할 것이다.

Transactional Outbox Pattern이란?

백엔드 개발을 하다 보면, 내 서비스의 DB에 데이터를 저장하는 동시에 외부 시스템(타 서비스의 API, 카프카, 데이터 팀의 분석계 등)으로 이벤트를 발행해야 하는 상황을 자주 마주하게 된다.

가장 단순하게 코드를 짜면 다음과 같을 것이다.

@Transactional
public void completeOrder(Order order) {
    orderRepository.save(order); // 1. 로컬 DB에 주문 저장
    eventPublisher.publish(new OrderEvent(order)); // 2. 외부 메시지 큐로 이벤트 전송
}

하지만 네트워크 세상은 언제나 불안정하다. 이 구조는 두 가지 치명적인 결함을 가지고 있다.

  1. DB는 성공했는데, 네트워크가 깨진 경우:

    주문은 성공적으로 DB에 저장되었는데, 외부 시스템으로 이벤트를 보내는 과정에서 네트워크 타임아웃이나 카프카 장애가 발생하면? 사용자는 결제가 됐는데 배송 팀이나 데이터 분석 팀은 주문조차 모르는 데이터 불일치 상태가 된다.

  2. 이벤트는 나갔는데, DB 트랜잭션이 롤백된 경우:

    이벤트를 먼저 보냈거나 보내는 도중 DB 작업에서 에러가 발생해 롤백된다면? 실제로는 취소된 주문인데 데이터 분석계에는 주문이 완료되었다고 기록되는 유령 데이터가 생긴다.

트랜잭션 아웃박스 패턴은 이를 해결하기 위해 "웹 API 호출이나 메시지 큐 전송을 비즈니스 트랜잭션과 직접 묶지 않는다" 는 아이디어에서 출발한다. 외부 전송을 바로 하지 않고, 우리 DB 안에 '아웃박스(Outbox, 보낼 편지함)'라는 임시 테이블을 만들어 전송할 이벤트 내용을 일단 저장해 두는 패턴이다.

아웃박스 패턴의 핵심 메커니즘과 동작 순서

이 패턴의 핵심은 RDBMS가 가장 잘하는 ACID 트랜잭션을 100% 활용하는 것이다.

단계별 동작 흐름

  1. 동일 트랜잭션 내 저장: 사용자의 주문이 들어오면 백엔드 애플리케이션은 단일 트랜잭션(@Transactional) 안에서 두 가지 작업을 동시에 수행한다.
  • Order 테이블에 주문 정보 저장 (비즈니스 데이터)

  • Outbox 테이블에 "주문이 완료됨"이라는 이벤트 메시지 저장 (이벤트 데이터)

  1. 원자성(Atomicity) 보장: 하나의 트랜잭션으로 묶여 있기 때문에, 주문 저장과 아웃박스 저장은 '둘 다 성공하든지, 둘 다 실패(롤백)'하든지 둘 중 하나만 일어난다. 이로써 1차적인 데이터 정합성이 보장된다.

  2. Message Relay 가동: 이제 DB 밖에서 별도로 작동하는 독립된 프로세스(Message Relay)가 주기적으로 Outbox 테이블을 살피며(Polling) 아직 전송되지 않은 이벤트를 읽어온다.

  3. 외부 전송 및 상태 변경: 메시지 릴레이가 카프카나 외부 API로 이벤트를 안전하게 전송하는 데 성공하면, Outbox 테이블의 해당 데이터 상태를 PROCESSED(처리됨)로 변경하거나 삭제한다.

이렇게 하면 소스 DB의 트랜잭션 원자성을 해치지 않으면서도, 외부 시스템으로 데이터를 유실 없이 안전하게 전달할 수 있는 파이프라인이 완성된다.

Message Relay를 구현하는 두 가지 방법

아웃박스 테이블에 쌓인 이벤트를 읽어서 외부로 쏴주는 Message Relay는 실무에서 보통 두 가지 방식으로 구현한다.

  • Polling Publisher:

    • 방법: 애플리케이션 스케줄러(예: Spring Scheduler, Quartz)가 0.5초나 1초마다 SELECT * FROM outbox WHERE status = 'READY' 쿼리를 날려서 이벤트를 가져와 발행하는 방식

    • 특징: 구현이 매우 단순하지만, DB에 지속적으로 SELECT 쿼리를 날려야 하므로 약간의 성능 오버헤드가 있고 실시간성이 떨어질 수 있다.

  • Transaction Log Miner (CDC 활용):

    • 방법: 위에서 배운 Debezium과 Binlog를 여기서 다시 써먹는 것이다. Debezium이 다른 테이블은 다 무시하고 오직 Outbox 테이블의 Binlog만 실시간으로 감시하게 만든다.

    • 특징: DB에 주기적인 폴링 쿼리를 날리지 않으므로 성능 부하가 전혀 없고, 밀리초 단위의 초고속 실시간 이벤트 발행이 가능해진다. 대규모 MSA 환경에서 가장 선호하는 방식이다.

At-Least-Once와 멱등성

Message Relay가 아웃박스 테이블을 읽어 카프카나 외부 시스템으로 데이터를 보낼 때, 분산 네트워크 환경의 특성상 '데이터 중복'은 피할 수 없다.

왜 중복이 발생할까? (At-Least-Once의 한계)

메시지 시스템의 전송 신뢰성 등급 중 가장 널리 쓰이는 방식이 바로 At-Least-Once(최소 한 번 전송)다. 말 그대로 최소한 한 번은 가도록 보장하지만, 두 번 갈 수도 있다는 뜻이다.

  1. Message Relay가 카프카로 "주문 완료" 이벤트를 전송한다.

  2. 카프카는 데이터를 잘 받았고, Relay에게 "잘 받았어!" 하고 확인 신호(ACK)를 보낸다.

  3. 그런데 하필 이 타이밍에 네트워크가 찰나의 순간 끊겨서 ACK 신호가 증발해 버린다.

  4. Message Relay 입장에서는 전송이 실패했다고 판단하고, 아웃박스 테이블의 상태를 PROCESSED로 바꾸는 대신 이벤트를 다시 재전송하게 된다.

  5. 결국 받는 쪽(OLAP나 타 마이크로서비스)은 똑같은 "주문 완료" 이벤트를 두 번 받게 된다.

데이터 오차 막기: 멱등성 처리

이 중복 수신으로 인해 매출 통계가 더블로 잡히거나, 배송이 두 번 나가는 사고를 막으려면 consumer(데이터를 받는 쪽)가 반드시 멱등성을 보장하도록 설계해야 한다. 멱등성이란 연산을 여러 번 적용해도 결과가 달라지지 않는 성질을 말한다.

실무에서 consumer가 멱등성을 확보하는 대표적인 방법 2가지는 다음과 같다.

  • Unique Key 제약 조건 활용:

    • 모든 이벤트 메시지에 고유한 Event ID나 비즈니스 키(예: order_id)를 심어서 보낸다.

    • 데이터를 받는 쪽(OLAP 등)에서 데이터를 적재할 때 이 키를 Primary Key 또는 Unique Key로 지정해 두면, 중복된 이벤트가 수신되더라도 DB 레이어에서 충돌(Duplicate Key Exception)이 발생해 자연스럽게 무시되거나 덮어쓰기 처리가 된다.

  • Idempotency Repository:

    • 데이터를 처리하기 전에 Processed_Events라는 별도의 이력 테이블을 조회한다.

    • "이미 처리된 order_id인가?"를 먼저 SELECT 해보고, 존재한다면 로직을 수행하지 않고 그냥 성공 래포트를 날려버리는 방식이다.

실무에서의 Trade-off: 아웃박스 패턴의 부작용과 대안

트랜잭션 아웃박스 패턴은 분산 시스템의 정석 같아 보이지만, 실무에 적용하면 발생하는 부작용들도 존재한다.

발생할 수 있는 부작용

  • 아웃박스 테이블의 폭발적인 증식 (Table Bloating):

    • 트래픽이 많은 서비스라면 Outbox 테이블에 초당 수천, 수만 건의 레코드가 쌓인다.

    • Message Relay가 제때 처리해서 지우거나 상태를 바꾼다 해도, 데이터가 너무 빠르게 쌓이면 RDBMS의 디스크 용량이 거덜 나거나 인덱스 성능이 저하된다. 결국 이미 처리된 아웃박스 데이터를 주기적으로 지워주는 별도의 배치 작업을 또 만들어서 관리해야 하는 번거로움이 생긴다.

  • DB 커넥션 및 가용성 경쟁:

    • 비즈니스 로직을 수행하는 것도 바쁜데, 아웃박스 데이터를 쓰고 읽는 행위 자체가 운영 DB의 자원(I/O, Memory, Connection)을 갉아먹는다.

    • 특히 Message Relay를 Polling 방식으로 만들면, DB에 지속적으로 락이나 조회가 걸려 정작 중요한 주문 로직이 느려질 수 있다.

  • 비즈니스 코드의 복잡도 증가:

    • 모든 도메인 행위마다 아웃박스 엔티티를 생성하고 저장하는 로직이 파편화되어 들어가기 때문에 코드가 지저분해지고 유지보수 비용이 올라간다.

그렇다면 대안은 무엇인가?

실무에서는 이 부작용들을 피하기 위해 아웃박스 패턴 외에 다음과 같은 대안들을 선택하기도 한다.

  • CDC (Change Data Capture) 직접 활용:

    • 방법: 굳이 Outbox라는 임시 테이블을 따로 만들지 말고, 원래 있던 Order 테이블 자체의 Binlog를 Debezium으로 바로 바라보게 한다.

    • 장점: 아웃박스 테이블을 관리할 필요가 전혀 없어서 DB 부하와 용량 문제가 해결된다. 다만, 데이터 분석계로 보낼 메시지 포맷을 세밀하게 제어하기 어렵다는 단점이 있다.

  • Two-Phase Commit (2PC) 또는 Saga 패턴:

    • 방법: 분산 트랜잭션 오케스트레이터를 두어 여러 서비스 간의 정합성을 맞추거나, 실패했을 때 보상 트랜잭션(Compensating Transaction)을 실행하는 아키텍처를 도입한다.

    • 장점: DB 레이어의 부담을 분산시킬 수 있지만, 아키텍처 난이도가 매우 어려워진다.

마치며

처음 OLTP, OLAP, ETL이라는 키워드를 접했을 때는 '이건 데이터 분석가나 데이터 엔지니어의 영역이 아닌가?'라는 막연한 거리감이 있었다. 하지만 깊이 파고들수록 데이터가 생성되는 시작점(OLTP)과 데이터가 흐르는 파이프라인의 입구(Extract)는 결국 백엔드 개발자의 영토임을 깨달았다. 대규모 트래픽 환경에서 운영 DB의 성능을 보호하고, 데이터의 정합성을 보장하는 아키텍처를 설계하는 것은 백엔드 역량이었다.

특히 최근 각광받는 MSA가 모든 문제를 해결해 줄 만능 치트키처럼 보였으나, 분산 시스템이라는 네트워크 환경 속에서는 오히려 데이터 불일치라는 부작용을 낳을 수 있음을 배웠다. CDC나 트랜잭션 아웃박스 패턴 같은 고급 아키텍처조차 결국은 '인프라 비용'과 '시스템 복잡도'라는 값비싼 세금을 내야 하는 Trade-off의 영역이었다. 엔지니어링에 은탄환은 없다는 명제를 다시 한번 가슴에 새기게 된다.

결국 이 모든 심화 아키텍처를 관통하는 핵심은 RDBMS의 내부 메커니즘(WAL, Binlog, MVCC)에 있었다. 화려한 아키텍처 패턴이나 최신 프레임워크를 좇기 전에, 근간이 되는 데이터베이스 공부를 절대 게을리하지 말아야겠다.

profile
글도 쓰고 코드도 쓰고

0개의 댓글