현대의 대부분 소프트웨어는 단순한 웹 페이지를 렌더링하는 수준을 넘어서, 많은 양의 데이터를 지속적으로 저장하고, 조회하고, 전달하고, 변환해야 합니다. 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장을 정리하면서 데이터 시스템의 가장 근본적인 요소인 데이터 모델이 왜 전체 아키텍처를 규정하는지 살펴보겠습니다.