Search

[Designing Data-Intensive Applications] -1편. 데이터 집약적 애플리케이션

현대의 대부분 소프트웨어는 단순한 웹 페이지를 렌더링하는 수준을 넘어서, 많은 양의 데이터를 지속적으로 저장하고, 조회하고, 전달하고, 변환해야 합니다. SNS 피드, 쇼핑몰 추천, 실시간 분석, 로그 수집, 금융 거래 시스템까지 이 모든 서비스의 근본적인 어려움은 “데이터가 어떻게 흐르고, 어떤 기술과 결합되는가”에서 발생합니다.
이번 글에서는 Designing Data-Intensive Applications 책의 1장을 정리하면서 데이터 시스템 설계에서 가장 기본이 되는 개념을 이해해보려고 합니다.

연산 중심(Compute-Intensive) vs 데이터 중심(Data-Intensive)

현대 소프트웨어 시스템은 크게 두 부류로 나눌 수 있습니다

연산 중심(Compute-Intensive)

병목이 CPU/GPU 연산량에 있는 시스템입니다.
물리 계산
그래픽 렌더링
머신러닝 학습
고성능 수치 연산(HPC)
핵심은 하드웨어 성능, 병렬 최적화, 알고리즘 개선입니다.

데이터 중심(Data-Intensive)

반대로 현대의 대부분 서비스는 CPU 연산이 아니라 데이터의 양·속도·다양성·일관성이 전체 난이도를 결정합니다.
SNS 피드 생성
추천 시스템
로그 수집 및 분석
검색 인덱싱
금융 트랜잭션 처리
스트리밍 서비스
데이터 파이프라인(ETL/ELT)
이런 시스템이 어려운 이유는 CPU가 아니라 저장소, 네트워크, 지연(latency), 데이터 품질, 복제·동기화 문제 때문이다. 다시 말해, 오늘날 대부분의 애플리케이션은 데이터 집약적(data-intensive)이라고 볼 수 있습니다.

데이터 시스템을 구성하는 주요 컴포넌트

데이터 집약적 애플리케이션은 하나의 시스템으로 해결하지 않습니다. 보통 여러 시스템이 함께 동작하며 하나의 파이프라인을 구성합니다.

1. 데이터베이스

데이터의 영속 저장소입니다. 관계형, 문서형, 키-값, 컬럼 기반 등 다양한 모델이 존재합니다. 각 모델은 일관성과 확장성, 질의 패턴에 따라 장단점이 갈립니다.

캐시

읽기 성능을 높이기 위해 메모리에 데이터를 보관합니다. 하지만 캐시 갱신 시점에 따라 일관성 문제가 발생할 수 있습니다.
예) SNS에서 좋아요 수가 캐시와 DB에서 다르게 보일 수 있음

3) 검색 인덱스 (Search Index)

전문 검색을 위해 역색인 구조 등을 사용하는 별도 시스템입니다. Elasticsearch, Solr 등이 대표적이며 RDB와는 저장 방식이 완전히 다릅니다.
예) 쇼핑몰에서 “청바지” 검색 시 DB 스캔이 아니라 역색인 구조로 빠르게 탐색

4) 배치 처리 시스템

대량 데이터를 모아 한 번에 처리하는 방식입니다. Hadoop, Spark 등이 대표적입니다.
예) 하루치 클릭 로그를 모아 추천 모델 생성

5) 스트림 처리 시스템

데이터가 발생하는 즉시 처리합니다. Kafka Streams, Flink 등이 대표적입니다.
예) 결제 이벤트를 받아 즉시 이상거래 탐지에 활용

좋은 데이터 시스템의 기준

이 책에서는 좋은 데이터 시스템이 갖춰야 할 기준을 신뢰성(Reliability) / 확장성(Scalability) / 유지보수성(Maintainability) 세 가지로 정리합니다.

신뢰성 (Reliability)

신뢰성은 단순히 “장애가 없다”는 뜻이 아니라, 장애가 발생해도 데이터 손실 없이 예상 가능한 방식으로 복구되는 것을 의미합니다.

신뢰성을 위협하는 요소

하드웨어 고장 (디스크 불량, 네트워크 단절)
소프트웨어 버그 (race condition, deadlock)
운영자 실수 (잘못된 스키마 변경, 설정 오류)
트래픽 급증 (세일 시작, 이벤트 폭주)

사례1. 결제 API 재시도 중복 처리

네트워크 문제로 결제가 여러 번 요청되더라도 시스템은 idempotency로 중복 처리를 방지해야 합니다.

사례2. 단일 노드 장애로 서비스 중단

DB 한 대 고장으로 전체 서비스가 다운되어선 안 됩니다. 복제(replication)와 자동 failover가 필수입니다.

사례3. 잘못된 데이터 입력이 전체 파이프라인을 멈출 수 있다

ETL 파이프라인에서 JSON 한 줄이 깨졌다고 배치 작업 전체가 실패하면 유지 불가능한 구조입니다.

확장성 (Scalability)

확장성은 부하 증가에 예측 가능하게 대응할 수 있는 능력입니다.

사례1. 쇼핑몰 세일 시작

00시가 되면 상품 조회·장바구니·결제가 동시에 폭주합니다. 시스템은 순간적인 스파이크를 견딜 수 있어야 합니다.

사례2. SNS 타임라인 폭증

팔로워 수백만 명을 가진 사용자가 글을 올리면 읽기 부하가 순식간에 터집니다.

확장 전략

시스템을 확장하는 방법은 아래와 같이 다양한 방법이 있습니다.
수직 확장: 더 좋은 서버
수평 확장: 더 많은 서버(샤딩, 파티셔닝)
캐싱
로드 밸런싱
지리적 복제(geo-replication)
중요한 것은 단순히 확장하는 것이 아니라 확장성을 설계할 때 다양한 것을 고려해야 한다는 점입니다. 어떤 부하를 처리해야 하는지, 병목은 어디서 발생하는지, 어떤 방식으로 자원을 늘릴 것인지를 다 같이 고려해야 제대로 된 확장 전략을 짤 수 있습니다.

유지보수성 (Maintainability)

유지보수성은 시간이 지나도 시스템을 운영하고, 변경하고, 진화시키기 쉬운 구조를 말합니다.

1. 운영 가능성(Operability)

운영팀이 모니터링·로그·알람을 통해 시스템 상태를 쉽게 파악하고 대응할 수 있어야 합니다.

2. 단순함(Simplicity)

불필요한 복잡성(accidental complexity)은 곧 장애로 이어집니다.
예) 중복된 ETL 파이프라인, 비관측 가능한 데이터 흐름
예) 캐시 → DB → 검색 인덱스 간 업데이트 경로가 꼬여 추적 불가

3. 진화 가능성(Evolvability)

새로운 요구사항을 추가할 때 시스템 전체를 뜯어고쳐야 한다면 그 시스템은 오래 살아남기 어렵습니다.
예) 컬럼 하나 추가하려고 앱 서버·배치·스트림·캐시를 모두 수정해야 한다면 그 시스템은 진화 불가능하다.

데이터 시스템은 왜 어려운가?

데이터는 단순히 한 곳에 저장되는 것이 아닙니다. 여러 시스템을 거쳐 흐르고, 복제되고, 변환되고, 소비됩니다. 시스템과 시스템이 연결되면서 복잡성이 기하급수적으로 증가합니다.
이 복잡성을 관리하기 위해서는 신뢰성, 확장성, 유지보수성이라는 세 가지 기준을 중심에 두고 설계해야 합니다.

마무리

1장은 “데이터 시스템이 왜 어려운가”라는 질문을 던지고, 그 답을 데이터 중심 구조의 복잡성과 이를 해결하기 위한 3대 원칙에서 찾습니다. 이 세 가지 원칙은 너무 당연해 보이지만, 실제로 시스템을 만들다 보면 얼마나 깊게 적용해야 하는지, 어디까지 고려해야 하는지 판단하기 어려운 경우가 많습니다. 그래서 이런 개념들을 참고해 설계 방향을 더 나은 쪽으로 잡아가는 것이 중요합니다.
다음 글에서는 2장을 정리하면서 데이터 시스템의 가장 근본적인 요소인 데이터 모델이 왜 전체 아키텍처를 규정하는지 살펴보겠습니다.