모던 데이터 아키텍처
경계와 계약으로 설계하기
데이터가 여러 시스템에 흩어진 조직에서
아키텍처를 어떻게 설계하고 운영할지 다룬다.
전체 주장은 한 문장이다.
비즈니스 경계로 책임을 나누고,
경계를 넘을 때는 명시적인 계약으로 연결하며,
공통 기반은 플랫폼으로 표준화해서
작은 범위부터 점진적으로 확장한다.
23개 장은 이 문장을 풀어 쓴 것이다.
시작하기
처음이라면 0장. 이 책의 지도부터 읽는다.
전체 구조와 목적별 읽기 경로가 정리되어 있다.
목차
0장. 이 책의 지도
전체 구조, 읽는 순서, 반복해서 나오는 개념
1부 · 문제 — 왜 데이터가 흩어졌고 무엇이 문제인가
| 장 | 다루는 내용 |
|---|---|
| 1장. 데이터는 이미 흩어져 있다 | 데이터 관리의 범위, 중앙집중형의 성과와 환경 변화 |
| 2장. 저장 위치가 아니라 책임의 문제 | 중앙팀 병목, 사라지는 맥락, Data Lake가 남긴 것 |
| 3장. 이름들의 지도 | Data Mesh, Data Fabric, DataOps가 풀려는 문제 |
2부 · 경계 — 어디에 선을 긋고 누가 책임지는가
| 장 | 다루는 내용 |
|---|---|
| 4장. 좋은 경계의 원리 | 응집도와 결합도, 변경의 영향을 가두는 법 |
| 5장. 비즈니스로 도메인 나누기 | Domain, Bounded Context, 유비쿼터스 언어 |
| 6장. 데이터 소유권 | 데이터 도메인, 소유권, Data Sprawl |
| 7장. 무엇을 공개하고 무엇을 감출 것인가 | 내부 모델과 외부 계약의 분리 |
3부 · 연결 — 경계를 어떻게 넘는가
| 장 | 다루는 내용 |
|---|---|
| 8장. API로 연결하기 | REST, 계약, OpenAPI, Gateway |
| 9장. 서비스 경계와 조회 모델 | 마이크로서비스, Service Mesh, BFF, GraphQL, CQRS |
| 10장. 이벤트로 연결하기 | 이벤트 설계, 전달, 스키마, 내부와 공개 이벤트 |
| 11장. 이벤트를 운영한다는 것 | 중복, 순서, 멱등성, DLQ, Backpressure |
| 12장. 무엇으로 연결할 것인가 | API·이벤트·배치의 선택 기준, 분산 정합성 |
4부 · 제품 — 데이터를 어떻게 쓸 수 있게 하는가
| 장 | 다루는 내용 |
|---|---|
| 13장. 데이터 프로덕트 | 정의, 읽기 모델, 분석 모델링, 계보 |
| 14장. 데이터 프로덕트를 신뢰할 수 있게 만들기 | 품질, 이력 관리, 수집과 제공, 보안, 플랫폼 |
5부 · 신뢰 — 찾고, 믿고, 안전하게 쓰려면
| 장 | 다루는 내용 |
|---|---|
| 15장. 메타데이터와 데이터 지도 | 메타데이터, 메타모델, 계보, 카탈로그, 데이터 민주화 |
| 16장. 거버넌스 | 역할과 책임, 데이터 계약, 관측 가능성 |
| 17장. 보안과 접근 제어 | 분류, ACL·RBAC·ABAC, RLS·CLS, 마스킹 |
| 18장. 마스터 데이터 관리 | 골든 레코드, 네 가지 구현 스타일, 식별자 설계 |
6부 · 가치 — 어떻게 성과로 바꾸는가
| 장 | 다루는 내용 |
|---|---|
| 19장. 데이터를 소비하는 환경 | 소비자 특화 변환, 파이프라인, BI, 시맨틱 계층 |
| 20장. 머신러닝과 MLOps | 실험 추적, 피처 스토어, 모델 배포와 모니터링 |
7부 · 실행 — 어디서부터 시작하는가
| 장 | 다루는 내용 |
|---|---|
| 21장. 도메인 토폴로지 | 중앙화와 분산 사이의 여러 형태 |
| 22장. 플랫폼과 조직 | 도메인 팀과 플랫폼 팀, Team Topologies, Golden Path |
| 23장. 실행 로드맵 | 첫 유스케이스부터 DataOps까지 |
부록
| 부록 | 내용 | 언제 보면 되나 |
|---|---|---|
| A. 클라우드 랜딩 존과 Blueprint | 도메인을 클라우드에 배치하는 방법 | 21장 이후 |
| B. 지식 그래프와 시맨틱 웹 | RDF, OWL, SPARQL, 데이터 마켓플레이스 | 15장 이후 |
| C. 용어집 | 용어 106개를 주제별로 정리 | 모르는 용어를 만났을 때 |
| D. 흔한 오해 | 본문에서 바로잡은 오해 55개 | 설계 판단이 서지 않을 때 |
더 읽기 전에
목적별 읽기 경로, 반복해서 나오는 개념의 설명 위치,
이 책이 드는 예시에 대해서는
0장. 이 책의 지도에 정리해 두었다.
급하다면 이것만 기억하면 된다.
기술 이름을 외우는 책이 아니다.
도구는 계속 바뀌지만 아래 질문은 바뀌지 않는다.
이 데이터는 무엇인가?
누가 책임지는가?
어디에서 왔는가?
얼마나 믿을 수 있는가?
누가 어떤 목적으로 쓰는가?
경계를 넘을 때 무엇을 약속했는가?
각 장을 덮을 때 이 질문에 조금 더 답할 수 있다면
그 장은 제 몫을 한 것이다.
0장. 이 책의 지도
모던 데이터 아키텍처 — 경계와 계약으로 설계하기
제목의 두 낱말이 책 전체를 떠받친다.
경계는 어디서 나눌 것인가이고,
계약은 그 경계를 넘을 때 무엇을 약속할 것인가다.
이 책은 데이터가 여러 시스템에 흩어진 조직에서
아키텍처를 어떻게 설계하고 운영할지 다룬다.
먼저 전체 주장을 한 문장으로 적어 둔다.
비즈니스 경계로 책임을 나누고,
경계를 넘을 때는 명시적인 계약으로 연결하며,
공통 기반은 플랫폼으로 표준화해서
작은 범위부터 점진적으로 확장한다.
나머지 23개 장은 이 문장을 풀어 쓴 것이다.
1. 전체 구조
flowchart TD
p1["<b>1부 · 문제</b><br/>왜 이런 고민이 생겼는가<br/>1~3장"]
p2["<b>2부 · 경계</b><br/>무엇을 어디까지 나눌 것인가<br/>4~7장"]
p3["<b>3부 · 연결</b><br/>경계를 어떻게 넘을 것인가<br/>8~12장"]
p4["<b>4부 · 제품</b><br/>데이터를 쓸 수 있게 하는 법<br/>13~14장"]
p5["<b>5부 · 신뢰</b><br/>그 데이터를 믿어도 되는가<br/>15~18장"]
p6["<b>6부 · 가치</b><br/>어떻게 성과로 바꾸는가<br/>19~20장"]
p7["<b>7부 · 실행</b><br/>어디서부터 시작하는가<br/>21~23장"]
p1 --> p2 --> p3 --> p4 --> p5 --> p6 --> p7
각 부는 하나의 질문에 답한다.
| 부 | 질문 | 장 |
|---|---|---|
| 1부 | 왜 데이터가 흩어졌고 무엇이 문제인가 | 1~3 |
| 2부 | 어디에 경계를 긋고 누가 책임지는가 | 4~7 |
| 3부 | API·이벤트·배치 중 무엇을 언제 쓰는가 | 8~12 |
| 4부 | 데이터를 어떻게 제품처럼 제공하는가 | 13~14 |
| 5부 | 찾고, 믿고, 안전하게 쓰려면 무엇이 필요한가 | 15~18 |
| 6부 | 분석과 머신러닝으로 어떻게 연결하는가 | 19~20 |
| 7부 | 조직과 플랫폼을 어떻게 바꾸는가 | 21~23 |
2. 읽는 순서
전체를 처음 배운다면 1장부터 순서대로 읽으면 된다.
목적이 분명하다면 아래 경로가 빠르다.
모놀리스에서 서비스를 분리하는 중이라면
flowchart TD
a["2장<br/>문제 인식"]
b["4~6장<br/>경계와 소유권"]
c["7장<br/>무엇을 공개할 것인가"]
d["8~12장<br/>연결 방법과 선택 기준"]
e["13장<br/>데이터를 어떻게 넘길 것인가"]
f["23장<br/>어디서부터 시작할까"]
a --> b --> c --> d --> e --> f
15~18장은 분리가 끝난 뒤에 읽어도 늦지 않다.
데이터 플랫폼을 만든다면
flowchart LR
a["3장<br/>이름들의 지도"] --> b["13~15장<br/>제품과 메타데이터"] --> c["19장<br/>소비 환경"] --> d["21~23장<br/>조직과 실행"]
거버넌스를 맡았다면
flowchart LR
a["2장<br/>책임의 문제"] --> b["6장<br/>데이터 소유권"] --> c["14~18장<br/>품질·메타데이터·보안·기준"] --> d["23장<br/>어디서부터 시작할까"]
3. 반복해서 나오는 개념
몇 개념은 여러 장에 걸쳐 등장한다.
설명을 한 곳에 모아 두었으니 처음 만났을 때
아래 장을 펼치면 된다.
| 개념 | 설명하는 장 |
|---|---|
| Data Mesh 네 가지 원칙 | 3장 |
| 응집도와 결합도 | 4장 |
| 유비쿼터스 언어 · Bounded Context | 5장 |
| 데이터 소유권 | 6장 |
| API 계약 | 8장 |
| CQRS | 9장 |
| 이벤트 설계 | 10장 |
| API·이벤트·배치 선택 기준 | 12장 |
| 데이터 프로덕트 | 13장 |
| 데이터 품질 · Bronze / Silver / Gold | 14장 |
| 셀프서비스 플랫폼 · Federated Governance | 14장 |
| 메타데이터 · 카탈로그 · 계보 | 15장 |
| 데이터 계약 · 거버넌스 체계 | 16장 |
| 접근 제어와 데이터 보호 | 17장 |
| 마스터 데이터 · 골든 레코드 | 18장 |
| 시맨틱 계층 · 셀프서비스 분석 | 19장 |
| Team Topologies · Golden Path | 22장 |
다른 장에서 이 개념이 나오면
한두 문장으로 짚고 넘어간 뒤 해당 장을 가리킨다.
4. 이 책을 읽는 방법
기술 이름을 외우는 책이 아니다.
Kafka, dbt, Debezium 같은 도구는 계속 바뀐다.
바뀌지 않는 것은 아래 질문들이다.
이 데이터는 무엇인가?
누가 책임지는가?
어디에서 왔는가?
얼마나 믿을 수 있는가?
누가 어떤 목적으로 쓰는가?
경계를 넘을 때 무엇을 약속했는가?
각 장을 덮을 때 이 질문에 조금 더 답할 수 있다면
그 장은 제 몫을 한 것이다.
5. 예시에 관하여
설명에는 온라인 쇼핑몰을 예로 든다.
회원 · 상품 · 주문 · 결제 · 배송 · 정산
판매자에게 대금을 지급하는 출금,
유상과 무상으로 나뉘는 포인트도 자주 나온다.
특정 업종에 익숙하지 않아도 읽을 수 있도록
가장 흔한 형태 하나로 통일했다.
6. 부록
본문에서 덜어낸 내용과 참고 자료를 부록에 두었다.
| 부록 | 내용 | 언제 보면 되나 |
|---|---|---|
| A. 클라우드 랜딩 존과 Blueprint | 도메인을 실제 클라우드에 배치하는 방법 | 21장을 읽고 클라우드 환경을 설계할 때 |
| B. 지식 그래프와 시맨틱 웹 | 메타데이터 관계를 그래프로 다루는 기술 | 15장 이후 메타데이터를 본격적으로 다룰 때 |
| C. 용어집 | 본문 용어를 주제별로 정리 | 모르는 용어를 만났을 때 |
| D. 흔한 오해 | 본문에서 바로잡은 오해 모음 | 설계 판단이 서지 않을 때 |
A와 B는 처음 읽을 때 건너뛰어도 된다.
C와 D는 순서대로 읽는 것보다
필요할 때 찾아보는 쪽이 쓸모 있다.
특히 D는 실무에서 결정을 앞두고 다시 보면
흔한 함정을 미리 피할 수 있다.
1장. 데이터는 이미 흩어져 있다
1부 · 문제 — 왜 데이터가 흩어졌고 무엇이 문제인가
1장 · 2장 · 3장
데이터는 왜 한곳에 모이지 않게 되었나
기업이 데이터를 많이 가지고 있다고 해서
곧바로 데이터 중심 조직이 되는 것은 아니다.
데이터 중심 조직은 필요한 데이터를 쉽게 찾고,
그 데이터의 의미를 이해할 수 있으며,
신뢰할 수 있는 상태로 활용할 수 있는 조직이다.
그리고 가장 중요한 것은
데이터가 실제 비즈니스 의사결정과
서비스 개선으로 이어져야 한다는 점이다.
현대의 데이터 환경은 과거와 크게 달라졌다.
클라우드, SaaS, 마이크로서비스, 실시간 처리,
머신러닝과 AI가 보편화되면서
데이터는 더 이상 한곳에만 존재하지 않는다.
이 장에서는 이러한 변화 속에서
왜 기존의 중앙집중형 데이터 관리 방식이
한계에 부딪히기 시작했는지 살펴본다.
1. 데이터 관리란 무엇인가
데이터 관리는 단순히
DB를 안정적으로 운영하는 일이 아니다.
데이터가 만들어진 순간부터
더 이상 필요하지 않아 삭제될 때까지
전체 수명주기를 관리하는 활동이다.
flowchart LR
n0["생성"] --> n1["수집"] --> n2["저장"] --> n3["가공"] --> n4["공유"] --> n5["분석 / 활용"] --> n6["보관"] --> n7["폐기"]
이 과정에서는 계속 여러 질문이 발생한다.
이 데이터는 정확한가?
누가 이 데이터를 책임지는가?
누가 사용할 수 있는가?
어디에서 만들어졌는가?
어떤 과정을 거쳐 변환되었는가?
얼마나 보관해야 하는가?
개인정보는 안전하게 보호되고 있는가?
따라서 데이터 관리는
기술만의 문제가 아니다.
조직, 정책, 보안, 품질, 책임, 아키텍처가
모두 함께 움직여야 한다.
2. 데이터 관리의 기본 틀: DAMA-DMBOK
앞 절의 말이 추상적으로 들린다면
이 분야의 표준 체계를 한 번 보는 것이 도움이 된다.
대표적인 것이 DAMA-DMBOK다.
데이터 관리를 여러 전문 영역으로 나누고
그 가운데에 데이터 거버넌스를 둔다.
flowchart LR
G["데이터 거버넌스"]
G --- A["데이터 아키텍처"]
G --- B["데이터 모델링"]
G --- C["저장과 운영"]
G --- D["보안"]
G --- E["데이터 통합"]
G --- F["메타데이터"]
G --- H["데이터 품질"]
G --- I["웨어하우징 · BI"]
style G fill:#e8f4ff,stroke:#4a90e2,stroke-width:3px,color:#1a1a1a
여기서 두 가지만 읽으면 된다.
하나, 데이터 관리는 기술 하나가 아니라 여러 영역의 묶음이다.
앞 절에서 “조직, 정책, 보안, 품질, 책임, 아키텍처가
모두 함께 움직여야 한다“고 한 것이 이 그림이다.
둘, 그 가운데에 거버넌스가 있다.
누가 어떤 기준으로 책임질지 정하지 않으면
나머지 영역을 아무리 잘 만들어도 따로 논다.
거버넌스는 16장 「거버넌스」에서 자세히 다룬다.
이 틀은 지금도 유용하다.
다만 현대의 분산 시스템, 클라우드, 데이터 제품,
실시간 데이터와 같은 환경에서는
이 기본 틀을 새로운 아키텍처 방식과 함께 해석할 필요가 있다.
즉,
DAMA-DMBOK가 잘못됐다기보다는
현대적인 분산 데이터 환경에 맞는 보완이 필요하다
고 이해하는 편이 정확하다.
3. 중앙집중형 데이터 관리가 등장한 이유
과거 기업 시스템은 지금보다 비교적 단순했다.
여러 업무 시스템에서 만들어진 데이터를
한곳에 모아 분석하는 것이 효율적이었다.
대표적인 구조가
엔터프라이즈 데이터 웨어하우스, 즉 EDW다.
flowchart LR
a["회원 시스템"] --> dw[("Data Warehouse")]
b["결제 시스템"] --> dw
c["상품 시스템"] --> dw
d["회계 시스템"] --> dw
dw --> bi["BI"] --> rep["보고서"]
이 방식은 매우 큰 장점이 있었다.
여러 시스템에 흩어진 데이터를 통합할 수 있었고,
회사의 공식적인 데이터를 한곳에서 관리할 수 있었다.
여기서 자주 등장하는 개념이
Single Source of Truth
즉, 진실의 단일 원천이다.
다만 이 개념을
모든 데이터를 반드시 하나의 DB에 저장한다
라고 이해하면 안 된다.
더 중요한 의미는
회사가 중요한 지표와 데이터에 대해
어떤 정의를 공식 기준으로 사용할지 합의되어 있다
는 것이다.
예를 들어 회사에서 매출이라는 용어를 사용할 때
결제 성공 금액 - 환불 금액
을 공식 매출이라고 정의했다면
어떤 시스템에서 계산하더라도
동일한 정의를 사용하도록 만드는 것이 중요하다.
물리적으로 데이터가 여러 곳에 존재하더라도
정의와 기준이 일관적이라면
Single Source of Truth의 목표를 달성할 수 있다.
4. 그런데 기업 환경이 크게 변했다
현대 기업의 애플리케이션 구조는
점점 더 분산되고 있다.
과거에는 하나의 거대한 시스템과
하나의 DB를 사용하는 경우가 많았다.
flowchart TD
subgraph app["하나의 애플리케이션"]
f1["회원"]
f2["결제"]
f3["배송"]
f4["주문"]
f5["정산"]
end
app --> db[("하나의 DB")]
하지만 지금은 서비스가 여러 개로 나뉘는 경우가 많다.
flowchart LR
s1["회원 서비스"] --> d1[("회원 DB")]
s2["결제 서비스"] --> d2[("결제 DB")]
s3["배송 서비스"] --> d3[("배송 DB")]
s4["주문 서비스"] --> d4[("주문 DB")]
여기에 클라우드와 외부 서비스까지 추가된다.
사내 DB
AWS / GCP / Azure
S3
Kafka
외부 PG
외부 SaaS
AI 서비스
Data Warehouse
즉 데이터는 애초부터
여러 환경에 분산되어 존재한다.
이러한 상황에서 모든 데이터를 다시 중앙으로 가져와
하나의 팀이 모두 이해하고 관리하는 방식은
조직이 커질수록 부담이 커질 수 있다.
여기서 중요한 점은
중앙집중형이 잘못됐다는 뜻이 아니라는 것이다.
조직이 작고 데이터 구조가 단순하다면
중앙집중형 방식이 오히려 가장 효율적일 수 있다.
문제는 규모가 커지면서
중앙 시스템과 중앙 조직이 모든 요구를 감당하기 어려워질 때다.
5. 분석과 AI가 데이터를 더욱 복잡하게 만든다
과거에는 데이터를 주로
보고서와 통계에 사용했다.
flowchart LR
n0["데이터"] --> n1["집계"] --> n2["보고서"]
하지만 지금은 같은 데이터를
여러 목적으로 사용한다.
flowchart LR
src["원본 데이터"] --> a["BI"]
src --> b["실시간 분석"]
src --> c["추천 시스템"]
src --> d["이상 탐지"]
src --> e["이탈 예측"]
src --> f["머신러닝 / AI"]
같은 사용자 데이터라도
목적에 따라 다른 형태로 가공된다.
BI용 데이터
추천 모델용 데이터
마케팅 분석용 데이터
ML 학습 데이터
실시간 처리용 데이터
이 과정에서 데이터가 여러 장소로 복제된다.
flowchart LR
n0["운영 DB"] --> n1["Kafka"] --> n2["S3"] --> n3["Data Warehouse"] --> n4["Feature Store"] --> n5["ML Dataset"]
그리고 새로운 문제가 발생한다.
어느 데이터가 최신인가?
어느 데이터가 공식 데이터인가?
왜 같은 지표인데 값이 다른가?
이 데이터를 누가 책임지는가?
그래서 현대 데이터 환경에서는
데이터 자체만 관리하는 것으로 부족하다.
데이터가 어디에 있고, 무슨 뜻이며, 누가 책임지는지를
함께 관리해야 한다.
6. 1장 정리
세 가지만 기억하면 된다.
데이터 관리는 DB를 안정적으로 운영하는 일이 아니다.
데이터가 만들어진 순간부터 폐기될 때까지
의미·책임·품질·보안을 함께 관리하는 활동이다.
중앙집중형 데이터 웨어하우스는 지금도 유효하다.
다만 클라우드, 마이크로서비스, SaaS, AI가 보편화되면서
데이터는 애초부터 여러 곳에 흩어져 생겨난다.
같은 데이터가 여러 목적으로 복제되기 시작했다.
BI, 추천, 이상 탐지, 학습 데이터가 각각 다른 형태를 요구한다.
그 결과 새로운 질문이 생긴다.
어느 데이터가 최신인가?
어느 데이터가 공식인가?
왜 같은 지표인데 값이 다른가?
다음 장에서는 이 질문들이
왜 저장 기술을 바꾸는 것만으로 풀리지 않는지 본다.
2장. 저장 위치가 아니라 책임의 문제
1부 · 문제 — 왜 데이터가 흩어졌고 무엇이 문제인가
1장 · 2장 · 3장
대시보드 숫자가 이상하다는 연락을 받았다.
어디부터 봐야 할까.
원본 DB인가, 중간 집계 테이블인가, 리포트 로직인가.
그리고 이 데이터는 누구에게 물어봐야 하는가.
1장에서는 데이터가 왜 여러 곳으로 흩어지는지 살펴봤다.
그런데 흩어진 데이터를 다시 모으는 것만으로는
문제가 풀리지 않는다.
이 장에서는 데이터가 많아질 때
무엇이 실제로 발목을 잡는지 본다.
중앙 데이터팀의 병목,
사라지는 비즈니스 맥락,
복잡해지는 파이프라인,
그리고 Data Lake가 해결한 것과 남긴 것이다.
여기까지 오면 질문이 바뀐다.
데이터를 어디에 저장할 것인가
에서
이 데이터는 누가 책임지는가
로 옮겨간다.
1. 중앙 데이터팀의 병목
중앙집중형 구조에서는
데이터 업무가 중앙팀에 집중되는 경우가 많다.
sequenceDiagram
participant S as 서비스팀
participant D as 중앙 데이터팀
S->>D: 데이터 요청
D->>D: ETL 변경
D->>D: Warehouse 수정
D->>D: 검증
D-->>S: 결과 전달
조직이 작을 때는 괜찮다.
하지만 수많은 도메인이 존재하면
중앙팀이 모든 비즈니스 규칙을 이해하기 어렵다.
예를 들어 주문 데이터만 하더라도
유상 포인트인가?
무상 포인트인가?
출금 가능한가?
프로모션 지급인가?
유효기간이 있는가?
같은 규칙이 존재할 수 있다.
이러한 규칙을 가장 잘 이해하는 사람은
대부분 중앙 데이터팀이 아니라
주문 서비스를 직접 개발하고 운영하는 팀이다.
여기서 현대 데이터 아키텍처의 중요한 질문이 등장한다.
과거에는
데이터를 어디에 저장할 것인가?
가 중요한 질문이었다면,
이제는
누가 이 데이터의 의미와 품질을 책임질 것인가?
라는 질문이 중요해진다.
2. 값만 봐서는 알 수 없다
데이터가 많아질수록
데이터 자체보다 데이터에 대한 정보가 중요해진다.
amount라는 컬럼이 있다고 하자.
이름만으로는 결제 금액인지 주문 금액인지 알 수 없다.
단위가 원인지 포인트인지도 모른다.
이 데이터가 어디에서 만들어져 어디까지 흘러갔는지도 알아야 한다.
앞의 것을 메타데이터, 뒤의 것을 데이터 계보라고 부른다.
둘 다 15장 「메타데이터와 데이터 지도」에서 다룬다.
더 어려운 것은 맥락이다
이름과 단위를 적어 두는 것은 그나마 쉽다.
중앙에서 모든 데이터를 하나의 형태로 통합하려고 하면
원래 데이터가 가지고 있던 비즈니스 맥락이 사라진다.
예를 들어 이런 값이 있다고 하자.
point_amount = 1000
숫자만 보면 단순하다.
하지만 실제 서비스에서는 이에 따라 의미가 완전히 달라진다.
결제로 충전한 포인트인가?
이벤트로 지급한 포인트인가?
출금 가능한 포인트인가?
유효기간이 있는가?
이미 주문으로 사용된 포인트인가?
이것은 컬럼 설명을 잘 적는다고 해결되지 않는다.
이 규칙들은 서비스가 바뀔 때마다 함께 바뀌고,
그 변화를 아는 사람은 그 서비스를 만드는 팀뿐이다.
데이터가 흩어질수록
그 데이터를 설명할 수 있는 사람이 필요해진다.
그리고 그 사람은 대개 중앙팀이 아니라 도메인 팀이다.
이것이 뒤에서 볼 도메인 중심 데이터 소유권으로 이어진다.
3. 중앙 시스템이 복잡해지는 과정
Data Warehouse 자체가 문제인 것은 아니다.
문제는 오랜 기간 수많은 요구사항이 들어오면서
데이터 파이프라인의 의존성이 지나치게 복잡해지는 경우다.
ETL
SQL Script
Batch
Cron
View
임시 테이블
집계 테이블
ML 데이터
BI 데이터
처음에는 서로 독립적이지만
시간이 지나면서 서로 참조하기 시작한다.
flowchart LR
a["raw_payment"] --> b["payment_clean"] --> c["daily_payment"]
c --> d["정산"] --> e["회계"]
c --> f["BI"] --> g["대시보드"]
그 상태에서 작은 컬럼 하나를 변경하려고 해도
이 컬럼을 누가 사용하지?
이 테이블을 변경하면 무엇이 깨지지?
이 ETL은 왜 존재하지?
를 확인해야 한다.
이런 상태를 소프트웨어 분야에서는
Big Ball of Mud,
즉 거대한 진흙덩이에 비유한다.
하지만 이것 역시
Data Warehouse는 시간이 지나면 반드시 이렇게 된다
라는 의미는 아니다.
잘 설계된 모델, 데이터 계약, 메타데이터 관리,
자동 테스트와 변경 관리가 있다면
복잡성을 상당 부분 통제할 수 있다.
즉 문제의 핵심은
중앙 저장소 자체보다 지나친 결합과 관리 부족이다.
4. Data Lake의 등장
기존의 Data Warehouse는
대체로 데이터를 저장하기 전에
구조를 먼저 정의하는 경향이 강했다.
flowchart LR
n0["원본"] --> n1["정제"] --> n2["변환"] --> n3["스키마 적용"] --> n4["저장"]
이를 흔히
Schema-on-Write
라고 한다.
하지만 미래에 어떤 분석을 할지
미리 알 수 없는 경우가 많다.
그래서 원본에 가까운 데이터를 먼저 보관하고
나중에 사용할 때 필요한 구조로 해석하는
Data Lake가 주목받기 시작했다.
flowchart TD
hub["Data Lake"]
s0["DB 데이터"] --> hub
s1["로그"] --> hub
s2["JSON"] --> hub
s3["CSV"] --> hub
s4["이미지"] --> hub
s5["영상"] --> hub
전통적으로 이를
Schema-on-Read
라고 설명한다.
다만 이 구분도 절대적인 것은 아니다.
현대의 데이터 레이크나 Lakehouse는
스키마 검증과 데이터 품질 규칙을
저장 시점에도 적용할 수 있다.
따라서 더 정확하게 이해하면 다음과 같다.
전통적인 Warehouse
→ 저장 전에 구조를 강하게 정의하는 경향
전통적인 Data Lake
→ 원본을 먼저 저장하고
활용 시점에 구조를 적용하는 경향
현대 Lakehouse
→ 두 방식의 장점을 결합하려는 접근
5. Data Lake도 만능은 아니다
Data Lake는 유연한 저장 문제를 해결했지만
조직과 데이터 소유권 문제까지 해결한 것은 아니다.
flowchart TD
hub["중앙 Data Lake"]
s0["회원"] --> hub
s1["결제"] --> hub
s2["배송"] --> hub
s3["주문"] --> hub
데이터를 기준 없이 계속 저장하면
이 데이터가 무엇인지 모르겠다.
누가 만들었는지 모르겠다.
어느 파일이 최신인지 모르겠다.
믿고 분석해도 되는지 모르겠다.
라는 상황이 발생할 수 있다.
이런 상태를 흔히
Data Swamp, 즉 데이터 늪이라고 부른다.
따라서 Data Lake 역시
메타데이터, 소유권, 품질, 보안,
카탈로그와 거버넌스가 필요하다.
중요한 교훈은 이것이다.
저장 기술을 바꾸는 것만으로
데이터 관리 문제가 해결되지는 않는다.
6. 2장 정리
세 가지만 기억하면 된다.
데이터가 많아지면 데이터에 대한 정보가 중요해진다.
값만 봐서는 의미를 알 수 없기 때문에
메타데이터와 데이터 계보가 필요해진다.
중앙 데이터팀은 규모가 커질수록 병목이 된다.
모든 도메인의 비즈니스 규칙을 한 팀이 이해하기 어렵고,
중앙으로 모으는 과정에서 원래의 맥락이 사라진다.
Data Lake는 저장 문제를 풀었지만 소유권 문제는 남겼다.
기준 없이 쌓기만 하면 늪이 된다.
그래서 질문이 옮겨간다.
flowchart LR
n0["데이터를 어디에 저장할 것인가"] --> n1["이 데이터는 누가 책임지는가"]
다음 장에서는 이 문제에 이름을 붙인
여러 접근을 한 번에 정리한다.
3장. 이름들의 지도
1부 · 문제 — 왜 데이터가 흩어졌고 무엇이 문제인가
1장 · 2장 · 3장
“우리도 Data Mesh를 해야 하지 않나요?”
이런 질문을 받았을 때 바로 답하기는 어렵다.
그 이름이 무슨 문제를 풀려고 나왔는지 모르면
도입할지 말지도 판단할 수 없다.
Data Mesh, Data Fabric, DataOps.
데이터 아키텍처를 공부하면
비슷해 보이는 이름들이 쏟아진다.
이 장에서는 각 이름이
어떤 문제를 풀려고 나왔는지만 정리한다.
세부 구현은 뒤에서 하나씩 다루므로
여기서는 지도를 그린다는 느낌으로 읽으면 된다.
마지막에는 1부 전체를 한 번에 정리한다.
1. 중앙집중과 탈중앙화
여기에서 데이터 전략의 중요한 선택이 등장한다.
모든 데이터를 중앙에서 관리하면
통제와 일관성을 확보하기 쉽다.
하지만 조직이 커질수록
중앙팀의 병목이 생길 수 있다.
반대로 각 팀에게 모든 권한을 주면
빠르게 움직일 수 있다.
하지만 각 팀이 제각각 움직이면
새로운 데이터 사일로가 생길 수 있다.
| 중앙집중 | 탈중앙화 | |
|---|---|---|
| 얻는 것 | 통제가 강하다 표준화가 쉽다 일관성을 확보하기 쉽다 | 자율성이 높다 변경 속도가 빠르다 |
| 잃는 것 | 자율성이 낮아질 수 있다 속도가 느려질 수 있다 중앙 병목이 생길 수 있다 | 표준이 어긋난다 중복 투자가 생긴다 데이터 통합이 어려워진다 새로운 사일로가 생긴다 |
따라서 현실적인 문제는
중앙집중이냐 탈중앙화냐
둘 중 하나를 선택하는 것이 아니다.
무엇을 중앙에서 관리하고
무엇을 도메인에 위임할 것인가
를 결정하는 것이다.
2. 연합형 거버넌스
현대 데이터 아키텍처에서는
중앙과 도메인이 역할을 나누는
연합형 접근이 중요하게 다뤄진다.
flowchart TD
subgraph center["중앙"]
c1["보안"]
c2["개인정보 정책"]
c3["공통 표준"]
c4["공통 플랫폼"]
c5["거버넌스"]
end
d1["회원 도메인"]
d2["결제 도메인"]
d3["배송 도메인"]
resp["데이터 의미<br/>데이터 품질<br/>데이터 제공<br/>변경 책임"]
center --> d1
center --> d2
center --> d3
d1 --> resp
d2 --> resp
d3 --> resp
중앙에서 모든 데이터를 직접 관리하지 않는다.
대신 조직 전체가 반드시 지켜야 하는
공통 기준과 플랫폼을 제공한다.
도메인 팀은 자신이 가장 잘 알고 있는
데이터의 의미와 품질을 책임진다.
3. Data Mesh는 단순한 분산이 아니다
Data Mesh를
각 팀이 자기 데이터를 관리한다
정도로만 이해하면 부족하다.
Data Mesh의 핵심에는 크게 네 가지 생각이 있다.
도메인 중심 데이터 소유권,
Data as a Product,
Self-Service Data Platform,
Federated Computational Governance다.
쉽게 말하면 다음과 같다.
| 원칙 | 뜻 |
|---|---|
| 도메인 소유권 | 데이터를 가장 잘 아는 팀이 책임진다 |
| Data as a Product | 다른 사람이 쉽게 사용할 수 있도록 데이터를 제품처럼 관리한다 |
| Self-Service Platform | 각 팀이 모든 인프라를 직접 만들지 않도록 공통 플랫폼을 제공한다 |
| Federated Governance | 중앙과 도메인이 함께 데이터 관리 규칙을 만든다 |
따라서 Data Mesh는
모든 것을 각 팀에게 맡기는 완전한 탈중앙화가 아니다.
공통 플랫폼과 거버넌스가 없는 상태에서
팀마다 제각각 데이터를 운영한다면
그것은 Data Mesh라기보다
새로운 데이터 사일로에 가까울 수 있다.
또 Data Mesh가
Data Warehouse나 Data Lake를 반드시 대체하는 것도 아니다.
물리적으로는 같은 Warehouse나 Lake를 사용하면서도
논리적인 데이터 소유권을 도메인에 나눌 수 있다.
4. Data Fabric과 DataOps
Data Mesh와 함께
Data Fabric이라는 개념도 자주 등장한다.
둘은 해결하려는 문제의 초점이 다르다.
Data Mesh가 주로
누가 데이터를 책임지는가?
를 고민한다면,
Data Fabric은
여러 환경에 흩어진 데이터를
어떻게 발견하고 연결하고 관리할 것인가?
에 더 가깝다.
메타데이터와 자동화를 적극적으로 활용해
분산된 데이터의 통합과 관리를 돕는 접근이다.
DataOps는 또 다른 문제를 다룬다.
데이터 파이프라인을
어떻게 빠르고 안정적으로 변경할 것인가?
소프트웨어 분야의 DevOps와 비슷한 철학을
데이터 엔지니어링에 적용한다고 생각하면 쉽다.
flowchart LR
n0["데이터 코드 변경"] --> n1["자동 테스트"] --> n2["데이터 품질 검사"] --> n3["배포"] --> n4["모니터링"] --> n5["피드백"]
Data Mesh, Data Fabric, DataOps는
반드시 하나만 선택해야 하는 경쟁 개념은 아니다.
서로 다른 문제를 해결하기 때문에
함께 사용할 수도 있다.
5. 이름은 달라도 향하는 곳은 비슷하다
지금까지 본 이름들은 서로 경쟁하는 개념이 아니다.
Data Mesh는 누가 책임지는가를,
Data Fabric은 흩어진 것을 어떻게 연결하는가를,
DataOps는 어떻게 빠르고 안정적으로 바꾸는가를 다룬다.
풀려는 문제가 다르므로 함께 쓸 수 있다.
이 책의 나머지는 이 이름들을 하나씩 풀어 쓴 것이다.
| 무엇을 다루나 | 어디서 |
|---|---|
| 경계와 책임 | 2부 |
| 경계를 넘는 방법 | 3부 |
| 데이터를 제품으로 | 4부 |
| 믿을 수 있게 | 5부 |
| 성과로 바꾸기 | 6부 |
| 조직과 실행 | 7부 |
6. 3장 정리
세 가지만 기억하면 된다.
이름들은 경쟁 관계가 아니다.
Data Mesh는 누가 책임지는가를,
Data Fabric은 흩어진 것을 어떻게 연결하는가를,
DataOps는 어떻게 빠르고 안정적으로 바꾸는가를 다룬다.
풀려는 문제가 다르므로 함께 쓸 수 있다.
Data Mesh는 단순한 분산이 아니다.
도메인 소유권, 데이터 제품, 셀프서비스 플랫폼,
연합형 거버넌스가 함께 있어야 한다.
나누기만 하면 새로운 사일로가 된다.
중앙집중이냐 탈중앙화냐를 고르는 문제가 아니다.
무엇을 중앙에서 관리하고 무엇을 도메인에 맡길지 정하는 문제다.
여기까지가 1부다
1부를 하나의 이야기로 보면 다음과 같다.
flowchart TB
P["과거<br/>──────────<br/>중앙 Data Warehouse로 전사 데이터를 통합해<br/>효율적으로 분석했다"]
C["환경 변화<br/>──────────<br/>Cloud / SaaS · Microservice · AI / ML<br/>실시간 처리 · 데이터 증가<br/>데이터가 자연스럽게 분산됐다"]
R["문제 발생<br/>──────────<br/>ETL 복잡성 증가 · 데이터 복제 증가<br/>중앙 데이터팀 병목 · 도메인 맥락 손실<br/>기술 부채 증가"]
L["Data Lake 등장<br/>──────────<br/>원본을 더 많이 저장하고 유연하게 분석하게 됐지만<br/>소유권 · 품질 · 거버넌스 문제와<br/>중앙집중 문제는 그대로 남았다"]
H["새로운 관점<br/>──────────<br/>‘어디에 저장할 것인가?’에서<br/>‘누가 책임질 것인가?’로"]
N["현대적인 방향<br/>──────────<br/>도메인 중심 데이터 소유 · 공통 데이터 플랫폼<br/>연합형 거버넌스 · 메타데이터와 품질 관리<br/>비즈니스 중심 데이터 전략"]
P --> C --> R --> L --> H --> N
style P fill:#fafafa,stroke:#bbb,color:#1a1a1a
style C fill:#fafafa,stroke:#bbb,color:#1a1a1a
style R fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style L fill:#fafafa,stroke:#bbb,color:#1a1a1a
style H fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style N fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
1부에서 놓치지 말아야 할 것은 둘이다.
중앙집중형 Data Warehouse와 Data Lake는 지금도 유용하다.
다만 조직 규모와 데이터 복잡성이 커지면
중앙집중적인 운영 모델이 병목이 될 수 있다.
질문이 저장 위치에서 책임으로 옮겨갔다.
어디에 둘 것인가보다 누가 의미와 품질을 책임지는가가 중요해졌다.
현대의 데이터는 이미 여러 시스템과 조직에 분산되어 있다.
모든 것을 중앙으로 모으거나 각 팀에 맡기는 극단보다,
비즈니스 목표를 기준으로 중앙의 통제와 도메인의 자율성을
조율하는 데이터 전략이 필요하다.
다음 부에서는 그 출발점인
경계를 어디에 그을 것인가를 본다.
4장. 좋은 경계의 원리
2부 · 경계 — 어디에 선을 긋고 누가 책임지는가
4장 · 5장 · 6장 · 7장
서비스가 작을 때는 데이터 관리가 어렵지 않다.
애플리케이션도 몇 개 없고,
데이터베이스도 많지 않다.
필요한 데이터가 있으면 테이블을 조회하고,
조금 복잡하면 여러 테이블을 JOIN해서 해결할 수도 있다.
하지만 서비스가 성장하면 상황이 달라진다.
회원
결제
상품
배송
주문
출금
정산
판매자
통계
...
기능과 데이터가 많아지고
여러 팀이 같은 데이터를 사용하기 시작한다.
처음에는 편했던 공용 DB와 직접 조회가
나중에는 변경을 어렵게 만드는 원인이 된다.
이 장에서는 이러한 문제를 해결하기 위해
시스템과 데이터를 비즈니스 경계를 기준으로 나누고,
각 도메인이 자신의 데이터에 책임을 가지는 방법을 알아본다.
단, 목표는 시스템을 무조건 잘게 쪼개는 것이 아니다.
핵심은 다음 질문에 명확하게 답할 수 있는 구조를 만드는 것이다.
이 기능은 누가 책임지는가?
이 데이터는 누가 책임지는가?
다른 영역과는 어떤 계약으로 연결되는가?
1. 왜 경계가 필요한가
1부에서 본 것처럼 데이터는 이미 여러 곳에 흩어져 있고
중앙에서 모두 해석하는 방식은 한계에 부딪힌다.
그렇다고 아무렇게나 나누면
작은 변경 하나가 여러 시스템으로 번진다.
결제 구조를 바꿨더니 ETL이 깨지고
리포트와 통계까지 손봐야 하는 상황이다.
그래서 필요한 것이 경계다.
이 장에서는 소프트웨어 설계가 오래 써 온 두 가지 원칙,
응집도와 결합도에서 출발한다.
2. 좋은 소프트웨어 설계에서 힌트를 얻다
데이터 도메인을 이해하기 전에
소프트웨어 설계의 기본 원칙을 알아야 한다.
핵심은 두 가지다.
응집도는 높이고, 결합도는 낮추는 것이다.
높은 응집도
응집도는 쉽게 말하면
서로 밀접하게 관련된 것들이
얼마나 가까이 모여 있는가
를 의미한다.
예를 들어 주문 영역에는 다음 기능이 있을 수 있다.
flowchart TD
n0["주문"]
n1["주문 생성"]
n2["주문 조회"]
n3["주문 취소"]
n4["주문 상태 변경"]
n5["주문 데이터"]
n0 --> n1
n0 --> n2
n0 --> n3
n0 --> n4
n0 --> n5
이 기능들은 모두 주문이라는
같은 비즈니스 문제를 다룬다.
따라서 같은 경계 안에 있으면
이해하기도 쉽고 변경하기도 쉽다.
반대로 같은 주문을 다루는 기능이
이렇게 흩어져 있다면 복잡해진다.
flowchart LR
A["시스템 A<br/>주문 생성"]
B["시스템 B<br/>주문 조회"]
C["시스템 C<br/>주문 취소"]
D["시스템 D<br/>주문 상태"]
style A fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style B fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style C fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style D fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
주문 규칙 하나를 바꾸려면 네 곳을 손봐야 한다.
좋은 설계에서는
함께 변경되는 것들을 가능한 한 함께 둔다.
낮은 결합도
결합도는
한 시스템이 다른 시스템의 내부 구조를
얼마나 많이 알아야 하는가
를 의미한다.
예를 들어 주문 시스템이
결제 DB를 직접 조회한다고 해보자.
flowchart LR
n0["주문 시스템"] --> n1["결제 테이블 직접 SELECT"]
주문 시스템이 결제 DB의
테이블 이름,
컬럼 이름,
JOIN 관계
를 알아야 한다.
그러면 결제팀이 내부 테이블을 변경할 때
주문 시스템까지 영향을 받을 수 있다.
반대로 명확한 인터페이스를 두면 달라진다.
flowchart LR
n0["주문"]
n1["결제 인터페이스"]
n2["결제 내부 로직"]
n3["결제 DB"]
n0 -- "결제 요청" --> n1
n1 --> n2
n2 --> n3
주문은 결제 내부가 어떻게 구현되었는지
알 필요가 없다.
결제 내부 구조가 변경되더라도
외부 계약만 유지하면 된다.
좋은 아키텍처의 중요한 목적 중 하나는
변경의 영향을 자신의 경계 안에 가두는 것
이다.
3. 경계를 만들고 계약으로 연결한다
하나의 시스템에는
외부에 공개해야 할 부분과
내부에서만 알아야 할 부분이 있다.
예를 들어 결제 시스템을 생각해보자.
flowchart LR
OTHER["다른 시스템"]
subgraph PAYMENT["결제 시스템"]
API["외부 계약<br/><br/>결제 요청<br/>결제 취소<br/>결제 상태 조회"]
subgraph IMPL["🔒 내부 구현"]
PG["PG 연동"]
RETRY["실패 재처리"]
DB["결제 테이블"]
STATE["내부 상태 관리"]
end
API --> IMPL
end
OTHER -->|"계약을 통해서만 접근"| API
style API fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style IMPL fill:#f5f5f5,stroke:#999,stroke-dasharray: 5 5,color:#1a1a1a
다른 시스템은 외부에 공개된 계약만 사용한다.
결제 내부의 테이블 구조까지
알 필요가 없다.
이를 흔히 캡슐화라고도 한다.
이 원칙은 나중에 데이터에도 그대로 적용된다.
내부 데이터 모델을 그대로 공개하지 말고
필요한 형태의 명확한 계약으로 제공하자.
4. 마이크로서비스에서 배우는 것
마이크로서비스의 큰 장점은
각 서비스를 독립적으로 개발하고 배포할 수 있다는 것이다.
회원 서비스
주문 서비스
결제 서비스
상품 서비스
상품 기능을 변경하면
상품 서비스만 수정하고 배포할 수 있다.
하지만 여기서 중요한 점이 있다.
서비스를 많이 나눈다고
좋은 아키텍처가 되는 것은 아니다.
서비스가 많아지면
다음과 같은 구조가 만들어질 수 있다.
flowchart LR
A["A"] --> B["B"]
A --> C["C"]
B --> D["D"]
C --> D
D --> E["E"]
E --> B
style E fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
누가 누구에게 의존하는지 파악하기 어려워진다.
특히 E → B처럼 되돌아오는 연결이 생기면
한 바퀴 도는 의존이 만들어진다.
서비스 하나의 장애가
다른 서비스로 전파될 수도 있다.
즉 물리적으로 서비스를 나누었지만
논리적으로는 여전히 강하게 결합되어 있을 수 있다.
5. Service Mesh가 해결하는 것과 해결하지 못하는 것
서비스가 많아지면
라우팅,
재시도,
타임아웃,
보안,
모니터링
같은 공통 통신 기능이 필요하다.
이런 운영상의 복잡성을 관리하기 위해
Service Mesh 같은 기술을 사용할 수 있다.
하지만 한 가지 주의해야 한다.
Service Mesh가 해결하는 것은 주로
서비스 간 통신의 기술적·운영적 복잡성
이다.
다음 질문까지 해결해주는 것은 아니다.
A 서비스가 정말 B 서비스를 호출해야 하는가?
이것은 기술 문제가 아니라
도메인 설계 문제다.
따라서 잘못된 비즈니스 경계를
Service Mesh가 해결해주는 것은 아니다.
6. 4장 정리
세 가지만 기억하면 된다.
함께 변경되는 것은 함께 둔다.
이것이 높은 응집도다.
다른 시스템의 내부 구조를 알아야 한다면 결합도가 높은 것이다.
명확한 인터페이스를 두면
상대의 내부가 바뀌어도 영향을 받지 않는다.
좋은 아키텍처의 목적은 변경의 영향을 경계 안에 가두는 것이다.
서비스를 많이 나누는 것 자체는 목적이 아니다.
물리적으로 나눠도 논리적으로 강하게 묶여 있을 수 있고,
Service Mesh 같은 기술이 잘못 그은 경계를 고쳐주지도 않는다.
그렇다면 남는 질문은 하나다.
경계를 어디에 그을 것인가
다음 장에서 그 방법을 본다.
5장. 비즈니스로 도메인 나누기
2부 · 경계 — 어디에 선을 긋고 누가 책임지는가
4장 · 5장 · 6장 · 7장
“이 기능은 어느 팀이 맡나요?”
회의에서 이 질문이 나왔는데
아무도 선뜻 답하지 못한 적이 있는가.
기능은 분명히 동작하고 있는데
책임의 경계가 어디인지는 아무도 모르는 상태다.
4장에서 좋은 경계의 원리를 봤다.
그렇다면 실제로 어디에 선을 그어야 할까.
이 장에서는 도메인 주도 설계가 제안하는 방법을 본다.
Domain과 Subdomain,
Bounded Context,
유비쿼터스 언어,
그리고 비즈니스 역량이다.
기술 구조가 아니라
비즈니스 문제를 기준으로 나누는 것이 핵심이다.
1. 도메인 주도 설계란?
답해야 할 질문은 이런 것들이다.
서비스를 어디까지 하나로 볼 것인가?
데이터를 누가 책임질 것인가?
어떤 기능끼리 함께 있어야 하는가?
이 질문에 답하는 방법으로 도메인 주도 설계(DDD) 가 있다.
DDD의 핵심은 단순하다.
기술 구조보다
실제 비즈니스 문제를 먼저 이해하자.
예를 들어 어떤 플랫폼이 다음 기능을 제공한다고 해보자.
회원
상품
결제
주문
출금
정산
판매자 관리
DDD에서는 처음부터
payment_table
order_log
payout_history
같은 테이블 구조부터 생각하지 않는다.
먼저 다음을 질문한다.
결제는 어떤 책임을 가지는가?
주문은 무엇을 의미하는가?
출금에는 어떤 규칙이 있는가?
어떤 규칙들이 함께 변경되는가?
어디까지를 하나의 문제 영역으로 볼 것인가?
이렇게 비즈니스를 이해하면서
자연스러운 경계를 발견한다.
2. Domain과 Subdomain
Domain은 우리가 해결하려는
비즈니스 문제 영역이다.
그런데 회사 전체의 비즈니스는 너무 크다.
그래서 큰 문제를
더 작은 문제 영역으로 나눈다.
이를 Subdomain이라고 한다.
예를 들어 커머스라는 큰 영역이 있다면
flowchart TD
n0["커머스"]
n1["상품"]
n2["주문"]
n3["결제"]
n4["환불"]
n0 --> n1
n0 --> n2
n0 --> n3
n0 --> n4
처럼 나누어 볼 수 있다.
여기서 중요한 기준은
프로그램이나 테이블의 개수가 아니다.
비즈니스 문제가 서로 다른가가 핵심이다.
3. Bounded Context
DDD에서 가장 중요한 개념 중 하나가
Bounded Context다.
쉽게 말하면
같은 모델과 용어가
일관된 의미를 가지는 경계
라고 이해하면 된다.
예를 들어 상품이라는 단어가 있다고 하자.
커머스에서는
상품
= 고객에게 판매하는 대상
일 수 있다.
정산에서는
상품
= 매출과 지급 금액을 계산하기 위한 대상
일 수 있다.
통계에서는
상품
= 매출 분석을 위한 분류 단위
일 수도 있다.
같은 상품이라는 단어지만
필요한 정보와 규칙은 다르다.
그래서 모든 시스템이
하나의 거대한 상품 모델을 공유하게 만들 필요가 없다.
flowchart LR
subgraph c1["커머스 Context"]
a1["상품"]
a2["판매 가격"]
a3["판매 상태"]
end
subgraph c2["정산 Context"]
b1["상품"]
b2["매출"]
b3["정산 금액"]
end
각 Context 안에서
자신에게 필요한 모델을 가지면 된다.
4. Ubiquitous Language
Bounded Context와 함께 알아야 할 것이
Ubiquitous Language다.
쉽게 말하면
같은 Context 안에서는
현업, 기획자, 개발자가
같은 용어를 같은 의미로 사용하자.
는 것이다.
예를 들어 조직에서
출금 환산율
출금 환산단가
판매자 지급단가
를 섞어서 사용한다고 해보자.
세 용어가 정말 같은 개념이라면
하나로 통일하는 편이 좋다.
반대로 실제 규칙이 다르다면
서로 다른 이름을 사용해야 한다.
언어의 차이는 단순한 표현 문제가 아니다.
모델이 다른 것을 발견하는 단서가 되기도 한다.
예를 들어
구매 취소
환불
PG 취소
를 모두 같은 의미로 사용하고 있었는데
업무를 자세히 보면
구매 취소
= 주문 자체의 취소
환불
= 사용자에게 돈을 반환
PG 취소
= PG 승인 거래의 취소
처럼 실제로는 다른 개념일 수 있다.
5. 비즈니스 역량
도메인의 경계를 찾는 또 다른 관점은
Business Capability, 즉 비즈니스 역량이다.
쉽게 말하면
회사가 비즈니스를 수행하기 위해
할 수 있어야 하는 일
이다.
예를 들어 커머스 회사라면 이런 것들을 할 수 있어야 한다.
상품을 등록하고 노출한다
주문을 받고 처리한다
결제를 승인하고 취소한다
상품을 배송한다
판매자에게 정산한다
고객 문의에 응대한다
앞에서 본 도메인 목록과 비슷해 보이지만
표현이 다르다는 점을 보자.
도메인은 주문처럼 영역을 가리키고,
역량은 주문을 받고 처리한다처럼 할 수 있는 일을 가리킨다.
이것은 조직도와 다르다.
개발1팀
개발2팀
운영팀
사업팀
은 조직 구조다.
조직은 자주 바뀔 수 있지만
결제
예약
주문
정산
출금
같은 영역에서 하는 일은
상대적으로 오래 유지된다.
기술도 마찬가지다.
PHP에서 Go로 바뀌어도
고객의 결제를 처리한다.
라는 비즈니스 능력은 남는다.
6. 비즈니스 역량과 Bounded Context는 같은 것이 아니다
여기서 주의해야 한다.
비즈니스 역량과 Bounded Context는
서로 밀접하게 관련되어 있지만
동일한 개념은 아니다.
비즈니스 역량은
우리가 무엇을 할 수 있는가?
에 초점을 둔다.
Bounded Context는
어디까지 같은 모델과 언어를 사용할 것인가?
에 초점을 둔다.
따라서 다음처럼 기계적으로 생각하면 안 된다.
비즈니스 역량 하나
=
Bounded Context 하나
=
애플리케이션 하나
=
DB 하나
실제 설계에서는
서로 잘 맞춰보는 것이 좋지만
반드시 1:1일 필요는 없다.
7. 조직과 Context는 어떤 관계인가
Bounded Context를 현재 조직도에 억지로 맞추는 것은 좋지 않다.
조직은 자주 바뀌지만 비즈니스 문제는 그렇지 않기 때문이다.
그렇다고 조직 구조가 아무 관련이 없는 것도 아니다.
어떤 팀이 어떤 업무를 담당하는지,
어떤 사람들끼리 자주 대화하는지,
어떤 용어를 공유하는지는
도메인 경계를 발견하는 중요한 단서가 된다.
도메인이 조직도에 종속될 필요는 없지만
조직과 의사소통 구조는 경계를 찾는 중요한 정보다.
한 Context에 책임 팀이 하나면 좋다
이상적으로는 하나의 Bounded Context에
명확한 책임 팀이 있는 것이 좋다.
flowchart LR
n0["주문 Context"] --> n1["주문 담당 팀"]
그러면 누가 변경하는지, 누가 장애를 책임지는지,
누가 정책을 결정하는지가 명확해진다.
하지만 절대 규칙은 아니다.
큰 Context를 여러 팀이 담당할 수도 있고,
작은 회사에서는 한 팀이 여러 Context를 담당할 수도 있다.
핵심은 팀의 개수가 아니다.
책임의 주체가 명확한가
8. 물리적 시스템과 논리적 도메인은 다르다
현실에서는 하나의 오래된 시스템이
회원
결제
주문
출금
통계
를 모두 가지고 있을 수 있다.
물리적으로는 하나의 애플리케이션이다.
하지만 이것이
하나의 도메인이라는 뜻은 아니다.
예를 들어 하나의 MariaDB에
customer
payment
order
point
payout
product
가 들어 있다고 해보자.
논리적으로는 다음처럼 볼 수 있다.
flowchart LR
subgraph db["하나의 MariaDB"]
c["고객 Domain · customer"]
p["결제 Domain · payment"]
o["주문 Domain · order"]
w["출금 Domain · payout"]
end
따라서 다음 공식은 성립하지 않는다.
DB 1개 = Domain 1개
Application 1개 = Domain 1개
Microservice 1개 = Domain 1개
도메인은 물리적인 배치보다
비즈니스 책임과 모델의 경계로 판단한다.
9. 5장 정리
세 가지만 기억하면 된다.
도메인은 비즈니스 문제로 나눈다.
테이블이나 프로그램 개수가 기준이 아니다.
Bounded Context는 같은 용어가 일관된 의미를 갖는 경계다.
같은 상품이라도 판매·정산·통계에서
필요한 정보와 규칙이 다르다.
그래서 하나의 거대한 공통 모델을 만들 필요가 없다.
물리적 배치와 논리적 경계는 다른 문제다.
DB 1개 = Domain 1개
Application 1개 = Domain 1개
Microservice 1개 = Domain 1개
이 공식은 성립하지 않는다.
하나의 DB 안에서도 도메인 경계를 그을 수 있다.
다음 장에서는 경계를 나눈 뒤에 따라오는 질문,
즉 데이터를 누가 책임지는가를 본다.
6장. 데이터 소유권
2부 · 경계 — 어디에 선을 긋고 누가 책임지는가
4장 · 5장 · 6장 · 7장
값이 이상하다는 이야기가 나왔다.
그런데 여러 팀에서 같은 답이 돌아온다.
“그건 저희가 만든 데이터가 아닌데요.”
분명히 어딘가에서 만들어진 데이터인데
아무도 자기 것이라고 하지 않는다.
경계를 나눴다면 다음 질문이 따라온다.
이 데이터는 누가 책임지는가
이 장에서는 데이터 도메인과 데이터 소유권을 다룬다.
복사했다고 소유권이 옮겨가지 않는다는 것,
하나의 도메인이 여러 데이터 제품을 가질 수 있다는 것,
그리고 분산이 각자 마음대로가 아니라는 것이다.
1. 데이터 도메인
이제 이 생각을 데이터에 적용해보자.
예를 들어 주문이라는 비즈니스 영역이 있다면
flowchart LR
n0["주문 Domain"]
n1["주문 규칙"]
n2["주문 Application"]
n3["주문 Data"]
n0 --> n1
n0 --> n2
n0 --> n3
처럼 볼 수 있다.
여기서 데이터 도메인은
어떤 비즈니스 영역이
어떤 데이터에 책임을 가지는가
를 나타낸다.
데이터가 어느 DB에 저장되어 있는지만 보는 것이 아니다.
2. Data Ownership
도메인을 나누었다면
다음 질문을 해야 한다.
이 데이터는 누가 책임지는가?
이것이 Data Ownership이다.
데이터 소유권은 단순히
테이블을 만든 사람이 누구인가를 뜻하지 않는다.
도메인은 자신의 데이터에 대해
의미,
품질,
변경,
접근 권한,
보안,
개인정보,
제공 방식
등을 책임져야 한다.
예를 들어 주문 데이터의 값이 이상하다면
이 데이터가 맞는지
누가 최종적으로 판단할 것인가?
라는 질문에 답할 수 있어야 한다.
3. 복사했다고 소유권이 바뀌는 것은 아니다
주문 데이터를 출금 도메인으로 전달했다고 해보자.
flowchart LR
n0["주문 Domain"]
n1["출금 Domain"]
n0 -- "데이터 제공" --> n1
출금 시스템이 이 데이터를 저장했다고 해서
원본 주문 데이터의 소유자가 바뀌는 것은 아니다.
출금 쪽에서
필터링하고,
JOIN하고,
이름을 바꾸고,
새로운 값을 계산해도
원본 주문 데이터에 대한 책임은
여전히 주문 도메인에 있을 수 있다.
대신 출금 도메인이 새롭게 계산한
출금 가능 금액
출금 상태
출금 처리 결과
같은 데이터는
출금 도메인의 책임이 된다.
이렇게 어떤 데이터의 어떤 의미를 누가 책임지는가를
명확하게 해야 한다.
4. Data Product
소유권을 정했다면 그것을 밖에서도 알 수 있어야 한다.
데이터를 다른 사람이 믿고 쓸 수 있도록
관리해서 제공하는 형태를 Data Product라고 부른다.
중요한 것은 이것이다.
Data Product는 단순한 테이블 하나가 아니다.
데이터와 함께 스키마, 의미 설명, 품질 기준,
접근 정책, 메타데이터, 제공 인터페이스를 같이 생각한다.
그래야 사용자가 이 질문에 답할 수 있다.
이 데이터를 믿고 사용해도 되는가?
한 가지 덧붙이면, Data Mesh에서 말하는 Data Product는
원래 분석용 데이터를 중심에 둔 개념이다.
실무에서는 운영 API나 도메인 인터페이스까지
넓게 부르는 경우도 있다.
무엇을 갖춰야 데이터 제품이라고 부를 수 있는지는
13장 「데이터 프로덕트」에서 자세히 다룬다.
이 장에서는 도메인이 소유권을 드러내는 형태
정도로 생각하면 충분하다.
5. 도메인은 여러 데이터 제품을 가질 수 있다
하나의 도메인이
반드시 데이터 제품 하나만 제공하는 것은 아니다.
예를 들어 주문 도메인에서
flowchart LR
n0["주문 Domain"]
n1["원천 주문 데이터"]
n2["분석용 주문 데이터"]
n3["판매자 실적 데이터"]
n4["일별 주문 집계 데이터"]
n0 --> n1
n1 --> n2
n1 --> n3
n1 --> n4
처럼 여러 데이터 제품을 만들 수 있다.
따라서
Domain 1개
=
Data Product 1개
가 아니다.
6. 분산형 데이터 관리
기존에는 데이터 관리 책임이
중앙 데이터 조직에 집중되어 있었다.
flowchart LR
s0["회원"] --> hub
s1["결제"] --> hub
s2["주문"] --> hub
s3["출금"] --> hub
hub["중앙 데이터팀"]
style hub fill:#fff4f4,stroke:#d9534f,stroke-width:2px,color:#1a1a1a
도메인 중심 구조에서는 책임을 나눈다.
- 회원 Domain — 회원 데이터 책임
- 결제 Domain — 결제 데이터 책임
- 주문 Domain — 주문 데이터 책임
- 출금 Domain — 출금 데이터 책임
이것이 Data Mesh가 말하는 중요한 방향 가운데 하나다.
분산은 ’각자 마음대로’가 아니다
여기서 매우 흔한 오해가 있다.
중앙 관리를 걷어내면 각 팀이 알아서 하면 된다는 생각이다.
그렇게 하면 같은 의미의 데이터가 제각각 만들어진다.
user_id
member_no
uid
account_key
날짜 형식, 개인정보 처리 방식,
품질 기준, 보안 정책도 모두 달라진다.
그래서 도메인 자율성과 함께 공통 기준이 필요하다.
flowchart LR
GOV["공통 기준<br/>──────────<br/>표준 · 보안 · 품질<br/>개인정보 · 메타데이터"]
GOV --> A["결제<br/>자율 관리"]
GOV --> B["주문<br/>자율 관리"]
GOV --> C["출금<br/>자율 관리"]
style GOV fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
Data Mesh에서는 이 방향을 Federated Governance라고 부른다.
중앙에서 모든 데이터를 직접 관리하지는 않지만
회사 전체가 따라야 하는 기준은 함께 만든다.
7. Data Sprawl
분산형 데이터 환경의 위험 가운데 하나는
데이터가 여기저기 무질서하게 퍼지는 것이다.
flowchart TD
src["원본 데이터"] --> a["운영 DB"]
src --> b["Redis"]
src --> c["DW"]
src --> d["S3"]
src --> e["팀 A DB"]
src --> f["팀 B DB"]
src --> g["개인 분석 데이터"]
어느 순간
어떤 것이 진짜 원본인가?
를 알기 어려워진다.
이를 Data Sprawl이라고 볼 수 있다.
따라서 데이터가 복제되더라도
원본은 어디인가?
누가 소유하는가?
어디로 전달되는가?
누가 소비하는가?
얼마나 최신인가?
를 추적할 수 있어야 한다.
8. 처음부터 완벽하게 바꾸려고 하지 않는다
오래 운영한 시스템에는 이미
공용 DB
직접 JOIN
공통 테이블
배치
ETL
레거시 코드
가 복잡하게 얽혀 있을 수 있다.
이것을 한 번에 모두 뜯어고치는 것은 위험하다.
먼저 현재 구조를 파악해야 한다.
AS-IS
어떤 서비스가
어떤 테이블을 읽는가?
누가 데이터를 수정하는가?
어떤 시스템이 직접 연결되어 있는가?
데이터 원본은 어디인가?
그다음 목표 구조를 설계한다.
flowchart LR
n1["도메인 경계 정의"] --> n2["데이터 소유권 정의"] --> n3["불필요한 직접 의존 제거"] --> n4["공개 인터페이스 정의"] --> n5["점진적으로 확대"]
style n5 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
작은 영역부터 적용하면서
경험을 쌓는 것이 현실적이다.
9. 6장 정리
세 가지만 기억하면 된다.
데이터 소유권은 테이블을 만든 사람이 누구인가가 아니다.
의미·품질·변경·접근 정책을 책임지는 주체를 말한다.
복사했다고 소유권이 옮겨가지 않는다.
다만 받은 데이터로 새로운 값을 계산했다면
그 값에는 새로운 소유자가 생긴다.
분산은 각자 마음대로가 아니다.
같은 의미의 데이터가 팀마다 다른 이름을 갖고,
날짜 형식과 품질 기준이 제각각이 되면
도메인을 나눈 의미가 없어진다.
그래서 도메인 자율성과 공통 거버넌스가 함께 가야 한다.
다음 장에서는 경계를 넘어
다른 도메인에 데이터를 넘기는 방법을 본다.
7장. 무엇을 공개하고 무엇을 감출 것인가
2부 · 경계 — 어디에 선을 긋고 누가 책임지는가
4장 · 5장 · 6장 · 7장
떼어내기로 한 서비스가 있다.
그런데 코드를 뒤져 보니
다른 팀 여러 곳에서 그 서비스의 테이블을
직접 조회하고 있다.
테이블 이름 하나만 바꿔도
어디가 깨질지 알 수 없는 상태다.
도메인을 잘 나누면 곧바로 현실적인 문제가 생긴다.
다른 도메인의 데이터가 필요하면 어떻게 하지?
이 장에서는 경계를 넘는 방법을 다룬다.
핵심은 하나다.
내부 데이터 모델과 외부 공개 계약을 나누는 것이다.
모놀리스에서 서비스를 떼어내는 중이라면
이 장이 가장 먼저 쓰인다.
1. 다른 도메인이 데이터를 필요로 한다면
도메인을 잘 나누면
다음 문제가 생긴다.
다른 도메인의 데이터가 필요하면 어떻게 하지?
예를 들어 출금에서
주문 데이터가 필요하다고 해보자.
가장 쉬운 방법은
flowchart LR
n0["출금"] --> n1["주문 DB 직접 조회"]
다.
처음에는 편하다.
하지만 출금 시스템이 주문 DB의
테이블 구조,
컬럼,
JOIN 관계
까지 알게 된다.
결국 두 도메인이 다시 강하게 결합된다.
2. 공개 인터페이스를 만든다
대신 주문 도메인이
외부에 사용할 수 있는 계약을 제공할 수 있다.
flowchart LR
WD["출금 Domain"]
subgraph ORDER["주문 Domain"]
CONTRACT["공개 인터페이스<br/><br/>판매자 ID<br/>주문 금액<br/>주문 시간<br/>포인트 유형"]
subgraph INNER["🔒 내부 구현"]
T1["order"]
T2["order_detail"]
T3["point_usage"]
T4["…"]
end
CONTRACT --> INNER
end
WD -->|"공개된 계약만 사용"| CONTRACT
style CONTRACT fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style INNER fill:#f5f5f5,stroke:#999,stroke-dasharray: 5 5,color:#1a1a1a
출금 도메인은 이 네 가지만 알면 된다.
내부에서 몇 개의 테이블을 JOIN했는지는
알 필요가 없다.
이런 역할을 Data Provider라고 부르기도 한다.
다만 DDD의 표준 용어는 아니다.
핵심은 이름이 아니라
내부 데이터 구조와
외부 공개 계약을 분리한다.
는 원칙이다.
3. API만이 유일한 방법은 아니다
도메인 간 데이터를 전달한다고 해서
항상 HTTP API만 사용해야 하는 것은 아니다.
상황에 따라 여러 방법을 사용할 수 있다.
API
Domain Event
Message Broker
CDC
Data Pipeline
Data Product
Read Model
중요한 것은 어떤 기술을 사용하느냐보다
누가 생산자이고
누가 소비자이며
데이터의 의미와 책임이 어디에 있는가
가 명확해야 한다는 것이다.
4. 중간 시스템이 있다고 잘못된 구조는 아니다
데이터가 반드시 생산자에서 소비자로
직접 전달되어야 하는 것은 아니다.
예를 들어 다음 구조도 충분히 가능하다.
flowchart LR
n0["주문 Domain"] --> n1["Kafka"] --> n2["출금 Domain"]
또는
flowchart LR
n0["운영 DB"] --> n1["CDC"] --> n2["데이터 플랫폼"] --> n3["분석용 Data Product"]
도 가능하다.
문제는 Kafka나 파이프라인 자체가 아니다.
문제는 이런 구조다.
flowchart LR
n0["원본 DB"] --> n1["ETL"] --> n2["공통 DB"] --> n3["또 다른 ETL"] --> n4["중간 DB"] --> n5["소비 시스템"]
style n2 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style n4 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
이쯤 되면 소비 시스템 쪽에서 이런 질문이 나온다.
그래서 이 데이터의 주인이 누구지?
중간 시스템 때문에
데이터 출처와 의미와 소유권이 흐려지는 것이 문제다.
따라서 정확한 원칙은 다음과 같다.
중간 시스템을 쓰지 말라는 것이 아니라
중간 시스템 때문에 데이터 소유권과 의미가
사라지게 만들지 말자.
5. 소비자가 사용하기 좋은 데이터를 제공한다
내부 테이블을 그대로 공개하는 것보다
소비자가 필요한 데이터 모델을 제공하는 것이 좋다.
예를 들어 출금에서는
판매자 ID
주문 금액
포인트 유형
출금 가능 여부
가 중요할 수 있다.
반면 분석에서는
날짜
판매자
구매자
주문 금액
주문 시간
이 필요할 수 있다.
따라서 하나의 원천에서
여러 형태의 데이터가 나올 수 있다.
flowchart TD
d["주문 Domain"] --> a["분석용 Data"]
d --> b["실적용 Data"]
d --> c["집계용 Data"]
하지만 소비자마다
모든 요구를 별도 모델로 만들어주는 것도 좋지 않다.
생산자가 소비자 요구에
지나치게 끌려다닐 수 있기 때문이다.
따라서
재사용성과
소비 편의성
사이의 균형이 필요하다.
6. 타 도메인 DB 직접 접근은 무조건 금지인가?
원칙적으로 비즈니스 로직에서
출금 → 주문 내부 테이블 직접 수정
같은 구조는 피하는 것이 좋다.
도메인 경계를 무너뜨리기 쉽기 때문이다.
하지만
다른 도메인 테이블을
어떤 상황에서도 읽으면 안 된다.
는 절대 법칙은 아니다.
예를 들어
분석,
통계,
CQRS Read Model,
Materialized View
처럼 여러 도메인의 데이터를
결합해야 하는 목적이 있을 수 있다.
따라서 더 정확한 원칙은
도메인의 핵심 비즈니스 로직이
다른 도메인의 내부 구현에 직접 의존하지 않게 한다.
라고 이해하는 것이 좋다.
7. 도메인 안은 강하게, 도메인 사이는 느슨하게
지금까지 배운 원칙을
가장 간단하게 표현하면 다음과 같다.
flowchart TD
subgraph d1["주문 Domain · 내부는 높은 응집도"]
a1["주문 규칙"]
a2["주문 Application"]
a3["주문 Data"]
end
subgraph d2["출금 Domain · 내부는 높은 응집도"]
b1["출금 규칙"]
b2["출금 Application"]
b3["출금 Data"]
end
d1 -- "명확한 계약" --> d2
즉,
경계 안은 밀접하게 만들고
경계를 넘을 때는 느슨하게 만든다.
이 원칙이 DDD와 데이터 도메인을
관통하는 핵심이다.
8. 7장 정리
세 가지만 기억하면 된다.
내부 데이터 모델과 외부 공개 계약을 나눈다.
다른 도메인은 계약만 보고, 내부에 몇 개의 테이블이 있는지는 모른다.
그래야 내부를 바꿔도 밖이 깨지지 않는다.
계약이 반드시 API인 것은 아니다.
API, 도메인 이벤트, 메시지 브로커, CDC,
데이터 파이프라인, 데이터 제품 모두 계약이 될 수 있다.
중요한 것은 기술이 아니라 누가 생산자이고 의미를 누가 책임지는가다.
“남의 DB는 절대 읽지 마라“가 원칙은 아니다.
분석이나 조회 모델처럼 여러 도메인을 결합해야 하는 목적이 있다.
정확한 원칙은 이것이다.
도메인의 핵심 비즈니스 로직이
다른 도메인의 내부 구현에 직접 의존하지 않게 한다.
여기까지가 2부다
4장부터 7장까지를 하나로 이으면 다음과 같다.
flowchart TB
S1["문제<br/>──────────<br/>서비스가 성장하며 시스템과 데이터가 얽히고<br/>변경 하나의 영향 범위를 알 수 없게 된다"]
S2["원리<br/>──────────<br/>함께 변하는 것은 함께 두고<br/>남의 내부를 알아야 하는 연결은 줄인다"]
S3["경계 긋기<br/>──────────<br/>기술이 아니라 비즈니스 문제로 나눈다<br/>Domain · Bounded Context · 유비쿼터스 언어"]
S4["책임 정하기<br/>──────────<br/>각 도메인이 자기 데이터의<br/>의미와 품질을 책임진다"]
S5["경계 넘기<br/>──────────<br/>API · Event · Data Product 같은<br/>명시적인 계약으로 연결한다"]
S1 --> S2 --> S3 --> S4 --> S5
style S1 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style S2 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S3 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S4 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style S5 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
2부에서 가장 중요한 것은
시스템을 많이 쪼개는 기술이 아니다.
세 가지를 명확하게 만드는 것이다.
무엇을 책임지는가
어떤 데이터를 책임지는가
다른 영역과 어떤 계약으로 연결되는가
그래서 데이터 도메인이란
DB를 기준으로 데이터를 나누는 것이 아니라
비즈니스 책임을 기준으로 경계를 만들고
각 영역이 자신의 데이터에 책임을 가지게 하는 것
이다.
하나의 DB를 쓴다고 도메인 중심 설계를 못 하는 것이 아니고,
마이크로서비스를 수십 개로 나눴다고 좋은 설계가 되는 것도 아니다.
여기에 도메인의 자율성과 전사 공통 거버넌스가 더해질 때
규모가 커져도 감당할 수 있는 구조가 된다.
이 부에서 나온 용어는 부록 C 「용어집」의
「경계와 도메인」 항목에 정리해 두었다.
다음 부에서는 여기서 정한 계약을
무엇으로 구현할 것인가를 본다.
8장. API로 연결하기
3부 · 연결 — 경계를 어떻게 넘는가
8장 · 9장 · 10장 · 11장 · 12장
현대 시스템은 하나의 프로그램만으로 동작하지 않는다.
회원, 주문, 결제, 배송, 정산처럼
서로 다른 기능이 데이터를 주고받으며
하나의 서비스를 만든다.
시스템이 작을 때는 서로의 DB를 직접 조회하거나
내부 함수를 호출하는 방식으로도 충분할 수 있다.
하지만 규모가 커지면 문제가 생긴다.
어떤 시스템이 어떤 데이터를 소유하는지,
누가 변경할 수 있는지,
다른 시스템은 어떤 방식으로 접근해야 하는지가
점점 불분명해진다.
이 문제를 해결하는 핵심 도구가 서비스와 API이다.
이번 장에서는 API의 기본 개념에서 시작해
SOA와 ESB, REST, API Gateway까지 살펴본다.
서비스를 어떻게 나누고 조회를 어떻게 최적화할지는
9장에서 이어진다.
기술 이름을 모두 외우는 것이 목표는 아니다.
이번 장의 핵심은 다음 한 문장으로 정리할 수 있다.
각 도메인은 자신의 비즈니스 로직과 데이터를 책임하고,
다른 도메인은 명확하게 정의된 인터페이스를 통해 사용한다.
1. 데이터와 애플리케이션은 함께 움직인다
데이터 아키텍처를 공부하다 보면
DB와 데이터 모델에만 집중하기 쉽다.
하지만 실제 데이터는 DB에 가만히 있지 않다.
애플리케이션이 데이터를 생성하고,
다른 애플리케이션이 그 데이터를 조회하고,
또 다른 시스템으로 전달한다.
예를 들어 주문 시스템을 생각해보자.
flowchart LR
n0["사용자"] --> n1["주문"] --> n2["결제"] --> n3["배송"]
주문은 결제와 연결되어야 하고,
결제가 완료되면 배송과 연결될 수 있다.
따라서 실제 시스템에서는
데이터
+
애플리케이션
+
서비스
+
API
가 함께 움직인다.
데이터 아키텍처와
애플리케이션 아키텍처를
완전히 별개의 문제로 볼 수 없는 이유이다.
분석 시스템도 마찬가지다.
운영 시스템은 작은 단위를 빠르고 정확하게 처리하고
분석 시스템은 많은 데이터를 읽어 계산한다.
요구사항은 다르지만 결국 같은 비즈니스 데이터를 쓴다.
둘을 안전하게 잇는 방법 가운데 하나가 API다.
두 영역의 경계가 어떻게 흐려지고 있는지는
12장 「무엇으로 연결할 것인가」에서 다룬다.
2. API란 무엇인가
API는
Application Programming Interface
의 약자이다.
쉽게 말하면
프로그램이 다른 프로그램의 기능이나 데이터를
사용할 수 있도록 정해 놓은 인터페이스
이다.
예를 들어 회원 정보를 조회하는 API가 있다고 하자.
GET /users/100
응답은 다음과 같을 수 있다.
{
"id": 100,
"name": "홍길동"
}
API를 사용하는 쪽에서는
회원 시스템 내부가 어떻게 구현되었는지 알 필요가 없다.
PHP인지
Go인지
MariaDB인지
Redis를 사용하는지
몰라도 된다.
Consumer가 알아야 할 것은
무엇을 요청하면 되는가?
어떤 형식으로 결과가 오는가?
이다.
이것이 API가 제공하는 중요한 가치이다.
3. API는 내부 구현을 숨긴다
결제 시스템 내부가 다음처럼 복잡하다고 생각해보자.
flowchart TD
n0["결제 시스템"]
n1["PG 연동"]
n2["데이터베이스"]
n3["Redis"]
n4["쿠폰"]
n5["포인트"]
n6["결제 정책"]
n0 --> n1
n0 --> n2
n0 --> n3
n0 --> n4
n0 --> n5
n0 --> n6
다른 시스템이 이 구조를 전부 알아야 한다면
결제 시스템을 변경하기 매우 어렵다.
대신 외부에는 다음과 같은 인터페이스만 제공한다.
POST /payments
그러면 내부에서
PHP → Go
DB 구조 변경
PG사 변경
이 일어나더라도
외부 계약이 유지되는 한
Consumer의 변경을 최소화할 수 있다.
이렇게 내부 복잡성을 감추는 것을
추상화 또는 캡슐화라고 볼 수 있다.
4. 서비스 간 통신은 동기와 비동기로 나뉜다
서비스끼리 통신하는 방법은 크게
동기식과 비동기식으로 나누어 생각할 수 있다.
동기식 통신
동기식 통신은 요청한 쪽이
응답을 기다리는 방식이다.
flowchart LR
n0["요청"] --> n1["처리"] --> n2["응답"]
예를 들어 결제 요청은
성공했는지 실패했는지 바로 알고 싶다.
flowchart LR
n0["사용자"] --> n1["결제 요청"] --> n2["결제 시스템"] --> n3["성공 / 실패"]
이런 경우에는 동기식 요청-응답 방식이 자연스럽다.
비동기식 통신
반대로 즉시 결과를 기다릴 필요가 없는 작업도 있다.
예를 들어 주문이 완료된 이후
랭킹 반영
통계 적재
알림 발송
추천 데이터 반영
이 필요하다고 하자.
주문 서비스가 이 작업을 모두 기다릴 필요는 없다.
flowchart LR
d["주문 완료"] --> e["이벤트 발행"] --> b["Message Broker"]
b --> r["랭킹"]
b --> s["통계"]
b --> n["알림"]
이처럼 요청자가
후속 작업의 완료를 직접 기다리지 않는 방식이
비동기 통신이다.
5. Publish / Subscribe
비동기 시스템에서 자주 사용하는 방식이
Publish / Subscribe,
줄여서 Pub/Sub이다.
예를 들어 주문 서비스가
OrderCompleted
라는 이벤트를 발행한다고 하자.
flowchart LR
s["Order Service"] --> e["OrderCompleted"] --> b["Message Broker"]
b --> r["Ranking"]
b --> t["Stats"]
b --> n["Notification"]
주문 서비스는
누가 이 이벤트를 사용할지 모두 알 필요가 없다.
각 Consumer가 자신에게 필요한 이벤트를 구독하고
자기 역할을 수행한다.
이 방식은 서비스 간 직접 의존성을 줄이는 데
도움이 된다.
6. SOA: 서비스를 중심으로 시스템을 나누다
SOA는
Service-Oriented Architecture
즉, 서비스 지향 아키텍처이다.
핵심 아이디어는
시스템 기능을 서비스 단위로 제공하고,
명확한 인터페이스를 통해 서로 사용하게 하자.
이다.
예를 들어 거대한 쇼핑몰 시스템을
회원 서비스
상품 서비스
주문 서비스
결제 서비스
배송 서비스
처럼 나눌 수 있다.
서비스를 사용하는 쪽을
Service Consumer
라고 하고,
서비스를 제공하는 쪽을
Service Provider
라고 한다.
flowchart LR
n0["웹 애플리케이션"] --> n1["회원 API"] --> n2["회원 서비스"]
이 경우 웹 애플리케이션은 Consumer이고
회원 서비스는 Provider이다.
7. 느슨한 결합
서비스 아키텍처에서 매우 중요한 목표가
느슨한 결합이다.
서비스 A가 서비스 B의 DB를 직접 조회한다고 하자.
flowchart LR
n0["Service A"] --> n1["Service B DB"]
B의 테이블 구조가 바뀌면
A도 영향을 받을 수 있다.
반면 다음처럼 API를 사용하면
flowchart LR
n0["Service A"] --> n1["Service B API"] --> n2["Service B"]
B의 내부 구현이 바뀌더라도
외부 API 계약을 유지하면
A의 변경을 줄일 수 있다.
이것이 느슨한 결합의 핵심이다.
8. REST와 리소스 중심 API
현대 웹 API에서 자주 사용하는 방식이 REST이다.
REST는
Representational State Transfer
라는 이름의 아키텍처 스타일이다.
REST는 단순히
GET
POST
PUT
DELETE
를 사용하는 규칙만을 의미하지 않는다.
REST에는
Client-Server
Stateless
Cacheable
Uniform Interface
Layered System
등 여러 제약이 포함된다.
다만 실무에서 RESTful HTTP API를 이해할 때는
먼저 리소스(Resource) 개념부터 보는 것이 쉽다.
리소스란 무엇인가
시스템에서 다루는 대상을 리소스로 볼 수 있다.
회원
주문
상품
결제
배송
예를 들어 URI를 다음처럼 만들 수 있다.
/users/100
/orders/500
/products/30
그리고 HTTP Method를 이용해
어떤 동작을 원하는지 표현한다.
실무에서 흔히 다음처럼 대응한다.
생성 → POST
조회 → GET
수정 → PUT / PATCH
삭제 → DELETE
예를 들어
POST /orders
는 주문 생성을,
GET /orders/100
은 주문 조회를 표현할 수 있다.
다만 이것은 REST 전체의 정의라기보다
RESTful HTTP API에서 흔히 사용하는 설계 관례이다.
9. REST와 CRUD는 완전히 같은 개념이 아니다
REST를 처음 배우면
REST = CRUD
라고 이해하기 쉽다.
하지만 실제 비즈니스는
CRUD만으로 표현하기 어려운 경우도 있다.
예를 들어 주문 취소는 단순한 DELETE가 아닐 수 있다.
flowchart TD
n0["주문 취소"]
n1["결제 취소"]
n2["재고 복구"]
n3["쿠폰 복구"]
n4["상태 변경"]
n0 --> n1
n0 --> n2
n0 --> n3
n0 --> n4
따라서 상황에 따라
PATCH /orders/100
로 상태를 변경할 수도 있고,
취소를 별도 리소스로 모델링해서
POST /orders/100/cancellations
처럼 설계할 수도 있다.
실무에서는
POST /orders/100/cancel
같은 액션형 API도 흔히 볼 수 있다.
중요한 것은 CRUD에 억지로 맞추는 것이 아니라
API의 의미를 명확하고 일관성 있게 표현하는 것이다.
10. EAI와 ESB
기업에는 오래된 시스템과
새로운 시스템이 함께 존재하는 경우가 많다.
ERP
CRM
결제
회원
회계
레거시 시스템
이 시스템들은 서로 다른 기술과
데이터 형식을 사용할 수 있다.
이런 기업 애플리케이션들을 통합하는 분야를
EAI
Enterprise Application Integration
이라고 한다.
전통적인 EAI 환경에서 중요한 역할을 했던 것이
ESB(Enterprise Service Bus) 이다.
ESB의 역할
서비스들이 서로 직접 연결되면 관계가 빠르게 복잡해진다.
flowchart LR
A["A"] <--> B["B"]
A <--> C["C"]
A <--> D["D"]
B <--> C
B <--> D
C <--> D
넷일 때 연결이 여섯 개다.
시스템이 늘어날수록 연결은 그보다 빠르게 는다.
그래서 중앙의 통합 계층을 둔다.
flowchart LR
a["A"] <--> esb["ESB"]
b["B"] <--> esb
c["C"] <--> esb
d["D"] <--> esb
style esb fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
이제 각 시스템은 ESB 하나만 알면 된다.
ESB는 다음과 같은 역할을 수행할 수 있다.
메시지 라우팅
데이터 형식 변환
프로토콜 변환
서비스 연결
오케스트레이션
11. SOAP, WSDL, XSD
전통적인 SOA 환경에서는
SOAP과 XML 기반 기술이 많이 사용되었다.
SOAP은 XML을 이용한 메시징 프로토콜이다.
<Envelope>
<Body>
<GetUser>
<UserId>100</UserId>
</GetUser>
</Body>
</Envelope>
WSDL은
Web Services Description Language
로,
웹 서비스가 제공하는 기능과 인터페이스를
기계가 읽을 수 있는 형태로 정의한다.
SOAP 기반 웹 서비스에서 특히 널리 사용되었다.
XSD는
XML Schema Definition
으로,
XML 문서의 데이터 구조와 타입을 정의한다.
User에는 Id가 있어야 한다.
Id는 숫자다.
Name은 문자열이다.
같은 규칙을 표현할 수 있다.
12. REST/JSON이 널리 사용된 이유
SOAP은 강력한 표준이지만
웹과 모바일 환경에서는 다소 복잡하게 느껴질 수 있다.
반면
HTTP
+
REST 스타일
+
JSON
조합은 웹 기술과 자연스럽게 연결되고
비교적 단순하게 사용할 수 있다.
그래서 일반적인 웹 API에서는
REST/JSON 방식이 매우 널리 사용되고 있다.
그렇다고 SOAP이 사라진 것은 아니다.
기업 내부 통합이나 레거시 환경에서는
여전히 SOAP 기반 시스템이 존재한다.
즉,
SOAP → 과거 기술이라서 폐기
REST → 무조건 최신 정답
이라고 이해하면 안 된다.
각 기술은 사용 환경과 목적이 다르다.
13. 서비스 애그리게이션과 오케스트레이션
여러 서비스를 결합하는 방법도 다양하다.
Service Aggregation
여러 서비스의 결과를 모아
하나의 응답으로 만드는 방식이다.
flowchart TD
hub["하나의 응답"]
s0["회원"] --> hub
s1["주문"] --> hub
s2["쿠폰"] --> hub
s3["포인트"] --> hub
예를 들어 마이페이지 화면을 만드는 데 사용할 수 있다.
Service Orchestration
여러 서비스의 실행 순서와 조건을
중앙에서 제어한다.
flowchart TD
o["Orchestrator"] --> a["결제"]
o --> b["재고"]
o --> c["배송"]
예를 들어
1. 결제한다.
2. 성공하면 재고를 차감한다.
3. 배송을 등록한다.
같은 흐름을 중앙의 Orchestrator가 알고 있다.
오케스트라의 지휘자와 비슷하다.
14. 서비스 코레오그래피
오케스트레이션과 대비되는 방식이
Service Choreography
이다.
여기에는 중앙 지휘자가 없다.
flowchart TD
n0["OrderCreated"] --> n1["Payment Service"] --> n2["PaymentCompleted"] --> n3["Inventory Service"] --> n4["InventoryReserved"] --> n5["Delivery Service"]
각 서비스가 이벤트를 보고
자신이 해야 할 행동을 수행한다.
쉽게 비교하면
- 오케스트레이션 — 중앙 지휘자가 전체 흐름을 안다.
- 코레오그래피 — 각 서비스가 이벤트에 반응하며 움직인다.
이다.
둘 중 하나가 항상 좋은 것은 아니다.
실무에서는 두 방식을 섞어 사용하는 경우도 많다.
예를 들어 핵심 거래 흐름은 오케스트레이션으로 관리하고,
flowchart LR
n0["결제"] --> n1["재고"] --> n2["주문 완료"]
주문 완료 이후의 부가 기능은 이벤트로 처리할 수 있다.
flowchart TD
n0["OrderCompleted"]
n1["알림"]
n2["통계"]
n3["추천"]
n4["로그"]
n0 --> n1
n0 --> n2
n0 --> n3
n0 --> n4
15. 중앙 ESB가 너무 커질 때의 문제
ESB 자체가 나쁜 기술은 아니다.
문제는 모든 책임을 ESB에 넣기 시작할 때다.
라우팅
변환
업무 규칙
상태 관리
오케스트레이션
프로세스 관리
가 모두 중앙으로 모이면 이렇게 된다.
flowchart LR
A["A"] <--> ESB
B["B"] <--> ESB
C["C"] <--> ESB
D["D"] <--> ESB
ESB["ESB<br/>──────────<br/>라우팅 · 변환<br/>업무 규칙 · 상태 관리<br/>오케스트레이션 · 프로세스"]
style ESB fill:#fff4f4,stroke:#d9534f,stroke-width:3px,color:#1a1a1a
연결은 단순해졌는데
중앙 통합 계층이 가장 복잡한 시스템이 됐다.
또한 특정 기능의 소유자가 불명확해지고
변경 영향 범위가 커질 수 있다.
ESB를 고가용성으로 구성하면
물리적인 단일 장애점을 줄일 수 있다.
따라서 정확한 문제는
ESB 자체가 반드시 단일 장애점이라는 것이 아니라,
지나치게 많은 논리적 책임과 의존성을 중앙에 모으면
장애와 변경의 영향 범위가 커질 수 있다는 것이다.
라고 이해하는 것이 좋다.
16. 공통 데이터 모델의 장점과 한계
과거 SOA에서는 여러 시스템이
공통 데이터 모델을 사용하는 방식도 널리 사용했다.
이를
Canonical Data Model
이라고 한다.
예를 들어 서로 다른 시스템이 회원을
user_id
memberNo
customerId
처럼 다르게 표현한다면
통합 과정이 복잡해진다.
그래서 공통 모델을 만들 수 있다.
memberId
memberName
이 방식은 제한된 통합 영역에서는
여전히 유용할 수 있다.
문제는 회사 전체의 모든 의미를
하나의 초대형 모델에 넣으려고 할 때다.
각 팀의 요구사항이 계속 추가되면서
flowchart LR
n0["모두를 위해 만든 모델"] --> n1["너무 거대하고 복잡한 모델"]
이 될 수 있다.
따라서 표준 모델 자체가 나쁜 것이 아니라
범위를 지나치게 넓히는 것이 문제이다.
17. 중앙집중에서 도메인 책임으로
현대적인 아키텍처에서는
중앙 시스템이 모든 것을 소유
하는 방식보다
각 도메인이 자기 영역을 책임
지는 방식을 중요하게 본다.
예를 들어
flowchart LR
subgraph c["Commerce Domain"]
c1["Business Logic"]
c2["Data"]
c3["API"]
end
subgraph m["Member Domain"]
m1["Business Logic"]
m2["Data"]
m3["API"]
end
subgraph d["Delivery Domain"]
d1["Business Logic"]
d2["Data"]
d3["API"]
end
처럼 구성할 수 있다.
이 구조에서는 각 도메인의 소유권이 명확하다.
18. API Gateway
현대적인 API 환경에서 자주 등장하는 것이
API Gateway이다.
flowchart LR
c["Client"] --> g["API Gateway"]
g --> m["Member"]
g --> o["Commerce"]
g --> d["Delivery"]
API Gateway는 보통 다음과 같은 공통 기능을 담당한다.
라우팅
인증
인가
Rate Limit
TLS
로깅
모니터링
또한 상황에 따라
간단한 응답 변환이나 Aggregation을 수행할 수도 있다.
하지만 핵심 비즈니스 규칙을
Gateway에 집중시키는 것은 피하는 것이 좋다.
예를 들어
포인트 차감 우선순위
환불 가능 여부
결제 승인 정책
은 Gateway가 아니라
해당 도메인이 판단해야 한다.
따라서 쉽게 말하면
- API Gateway — 요청을 통제하고 전달
- Domain — 비즈니스 판단
이라고 이해하면 된다.
19. API를 제품으로 관리한다
API는 단순한 HTTP Endpoint가 아니다.
API에도 사용자가 있다.
웹
모바일
다른 개발팀
외부 파트너
따라서 API도 하나의 제품처럼 관리할 수 있다.
이를 흔히
API as a Product
관점이라고 부른다.
API 제품에는 다음과 같은 요소가 필요하다.
Owner
문서
버전
보안
모니터링
호환성 정책
Lifecycle
SLA 또는 SLO
즉,
API 개발 완료
→ 끝
이 아니다.
API도 지속적으로 운영하고 관리해야 한다.
20. API Contract
Provider와 Consumer 사이에는
명확한 약속이 필요하다.
이를 API Contract라고 한다.
예를 들어
GET /users/{id}
라는 API의 계약에는
URL
HTTP Method
Request
Response
Status Code
Error
인증 방법
버전
등이 포함될 수 있다.
Provider가 마음대로 응답 구조를 바꾸면
기존 Consumer가 깨질 수 있다.
따라서 API 계약은
도메인 간 결합을 안정적으로 관리하는 핵심 요소이다.
21. OpenAPI
HTTP API의 인터페이스를 문서화하는
대표적인 표준 중 하나가
OpenAPI Specification이다.
OpenAPI에서는
Endpoint
Method
Parameter
Request Schema
Response Schema
Authentication
등을 정의할 수 있다.
이를 기반으로
API 문서
Mock Server
Client SDK
Validation
테스트
등을 자동화할 수 있다.
다만
OpenAPI = API 계약의 모든 것
이라고 보면 안 된다.
실제 계약에는
SLA
Rate Limit 정책
호환성 정책
비즈니스 전제조건
처럼 OpenAPI 문서만으로 충분히 표현하기 어려운 내용도 있다.
따라서 OpenAPI는
API Contract를 표현하고 관리하는 대표적인 수단 중 하나
라고 이해하면 된다.
22. Composite Service
여러 API의 결과를 조합해
하나의 API로 제공할 수도 있다.
예를 들어 마이페이지에서
회원 정보
보유 포인트
최근 결제
배송 정보
가 필요하다고 하자.
flowchart TD
n0["Client"]
n1["MyPage Composite API"]
n2["Member API"]
n3["Point API"]
n4["Payment API"]
n5["Delivery API"]
n1 --> n2
n1 --> n3
n1 --> n4
n1 --> n5
n0 --> n1
Client는 여러 API를 각각 호출할 필요가 없다.
하지만 Composite API가
각 도메인의 핵심 비즈니스 규칙까지 소유하기 시작하면
새로운 중앙집중 시스템이 될 수 있다.
따라서 Composite는 주로
호출
결과 결합
표현 변환
에 집중하고,
비즈니스 판단은
각 도메인이 담당하는 것이 좋다.
23. API 탐색 가능성과 메타데이터
API가 몇 개 없을 때는
개발자가 기억할 수 있다.
하지만 API가 수백 개로 늘어나면 어렵다.
회원 조회 API가 어디 있지?
누가 관리하지?
최신 버전은 뭐지?
이 API 아직 사용 중인가?
이 문제를 해결하기 위해
Service Registry
API Catalog
Developer Portal
등을 사용할 수 있다.
API 자체뿐 아니라
API에 대한 정보도 관리해야 한다.
이를 API Metadata라고 볼 수 있다.
API 이름
설명
Owner
도메인
버전
Endpoint
인증 방법
Deprecated 여부
의존 관계
등이 메타데이터에 포함될 수 있다.
24. 8장 정리
네 가지만 기억하면 된다.
API는 내부 구현을 숨기고 계약만 노출한다.
언어를 바꾸든 DB 구조를 바꾸든
외부 계약이 유지되면 소비자는 영향을 받지 않는다.
REST는 CRUD가 아니다.
주문 취소처럼 CRUD로 표현하기 어려운 업무가 많다.
중요한 것은 규칙에 억지로 맞추는 것이 아니라
API의 의미를 명확하고 일관되게 표현하는 것이다.
중앙 통합 계층에 책임을 몰면 그것이 가장 복잡한 시스템이 된다.
ESB 자체가 문제가 아니라
라우팅·변환·업무 규칙·상태 관리를 모두 중앙에 모으는 것이 문제다.
API도 제품이다.
Owner, 문서, 버전, 보안, 호환성 정책, 수명주기가 필요하다.
다음 장에서는 서비스를 어떻게 나누고
조회를 어떻게 최적화할지 본다.
9장. 서비스 경계와 조회 모델
3부 · 연결 — 경계를 어떻게 넘는가
8장 · 9장 · 10장 · 11장 · 12장
서비스를 잘게 나눴다.
그랬더니 화면 하나를 그리는 데
API를 일곱 번 호출하게 됐다.
응답은 느려지고,
그중 하나만 실패해도 화면 전체가 비어 버린다.
8장에서 API 계약을 봤다.
이 장에서는 서비스를 어떻게 나눌지,
그리고 조회를 어떻게 최적화할지 본다.
마이크로서비스, Service Mesh, BFF, GraphQL, CQRS가 나오지만
기술 이름보다 중요한 것은 하나다.
작게 나누는 것이 목표가 아니라
적절한 경계를 찾는 것이 목표다.
1. 마이크로서비스
마이크로서비스는
애플리케이션을 비교적 작은 서비스 단위로 나누고
각 서비스의 자율성과 독립적인 운영을 높이는
아키텍처 접근 방식
이다.
SOA와
서비스 단위 구성
느슨한 결합
인터페이스 통신
이라는 철학을 공유하지만,
마이크로서비스를
단순히 SOA의 새로운 버전이라고 볼 수는 없다.
마이크로서비스는 특히
독립적인 배포
작은 책임 범위
팀 자율성
자동화된 운영
분산된 데이터 소유권
등을 강하게 강조한다.
2. 마이크로서비스의 핵심은 작기가 아니라 경계다
마이크로서비스라는 이름 때문에
작을수록 좋다
라고 생각하기 쉽다.
하지만 중요한 것은 코드 크기가 아니다.
이 서비스가 어떤 비즈니스 책임을 가지는가?
가 더 중요하다.
서비스를 너무 잘게 나누면
flowchart LR
n0["A"] --> n1["B"] --> n2["C"] --> n3["D"]
모든 작업이 네트워크 호출이 되어
지연
장애 가능성
배포 복잡성
운영 복잡성
이 증가할 수 있다.
따라서
가능한 한 작게 나누는 것이 아니라
적절한 도메인 경계를 찾는 것이 중요하다.
라고 이해해야 한다.
3. 데이터 소유권과 물리 DB는 다르다
마이크로서비스에서 흔히
각 서비스는 자신의 데이터를 가진다.
라고 말한다.
하지만 이것이 반드시
서비스 하나
=
물리 DB 서버 하나
를 의미하지는 않는다.
같은 DB 인스턴스를 사용하면서도
테이블 소유권 분리
스키마 분리
다른 서비스의 직접 접근 금지
같은 규칙을 적용할 수 있다.
중요한 것은
누가 데이터를 변경하고 책임지는지가 명확한가?
이다.
4. Service Mesh
마이크로서비스가 많아지면
서비스 간 네트워크 통신이 복잡해진다.
각 서비스가 모두 직접
TLS
인증
재시도
로드밸런싱
트래픽 제어
모니터링
을 구현하면 부담이 커진다.
이러한 통신 기능을
인프라 계층에서 처리하는 접근이
Service Mesh이다.
쉽게 비교하면
flowchart LR
Client["외부 사용자"] <-->|"North-South<br/>외부 ↔ 내부"| Gateway["API Gateway"]
Gateway --> A
subgraph Mesh["Service Mesh"]
A["Service A"] <-->|"East-West<br/>내부 서비스 간"| B["Service B"]
B <-->|"East-West"| C["Service C"]
end
style Gateway fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
라고 생각할 수 있다.
다만 이것은 대표적인 역할 구분이지
절대적인 경계는 아니다.
API Gateway를 내부 API에 사용할 수도 있고,
Service Mesh에도 ingress/egress 기능이 있을 수 있다.
5. Control Plane과 Data Plane
서비스 메시를 이해할 때
자주 등장하는 개념이다.
Control Plane은
라우팅 정책
보안 정책
트래픽 정책
등을 정의한다.
Data Plane은
실제 요청과 트래픽을 처리한다.
쉽게 표현하면
- Control Plane — 교통 정책을 정한다.
- Data Plane — 실제 차량이 다니는 도로다.
라고 이해할 수 있다.
6. 내부 API와 외부 API는 다르다
회사 내부 시스템끼리 사용하는 API와
외부 파트너에게 제공하는 API는
요구사항이 다르다.
내부 API는 상대적으로 빠르게 변경할 수 있지만,
외부 API는
강한 인증
Rate Limit
DDoS 대응
감사 로그
문서화
안정적인 버전 정책
등이 더 중요하다.
따라서 내부 API를
외부에 그대로 공개하는 것은 주의해야 한다.
내부 구현이 외부 계약으로 굳어지면
나중에 내부 구조를 변경하기 어려워질 수 있다.
7. Experience API와 BFF
사용자 화면에 맞게 API를 구성할 수도 있다.
예를 들어 모바일 홈 화면에서
회원 정보
보유 포인트
상품 목록
추천
알림
이 필요하다고 하자.
모바일 앱이 모든 API를 직접 호출하는 대신
flowchart LR
n0["Mobile"] --> n1["Mobile API"] --> n2["여러 Domain API"]
형태로 구성할 수 있다.
이러한 소비자 경험 중심의 계층을
Experience API라고 부르기도 한다.
비슷한 목적의 대표적인 패턴이
BFF(Backend for Frontend) 이다.
Web BFF
Mobile BFF
Admin BFF
처럼 프론트엔드별로
전용 Backend를 둘 수 있다.
Experience API와 BFF는 비슷한 문제를 해결하지만
완전히 같은 개념이라고 볼 필요는 없다.
BFF는 특히
특정 프론트엔드 전용 Backend라는 의미가 강하다.
8. GraphQL
GraphQL은 Client가
필요한 필드를 직접 지정해 요청할 수 있는
API Query Language이자 실행 방식이다.
예를 들어
query {
user(id: 100) {
name
profileImage
}
}
처럼 원하는 데이터만 요청할 수 있다.
REST API에서 하나의 응답이 너무 많은 데이터를 내려주는
Over-fetching 문제나,
하나의 화면을 위해 여러 API를 호출해야 하는
Under-fetching 문제를 줄이는 데 도움이 될 수 있다.
하지만 GraphQL을 사용한다고 해서
자동으로 성능이 좋아지는 것은 아니다.
복잡한 Nested Query
N+1 Query
쿼리 비용 관리
권한 제어
같은 문제를 따로 고려해야 한다.
9. GraphQL은 REST 위에서만 동작하는 것이 아니다
GraphQL을 다음처럼 사용할 수 있다.
flowchart LR
n0["Client"] --> n1["GraphQL"] --> n2["REST API"]
하지만 이것은 하나의 구현 방법일 뿐이다.
GraphQL Resolver는
DB
REST API
gRPC
다른 GraphQL 서비스
Cache
외부 API
등 다양한 데이터 소스를 사용할 수 있다.
또한 GraphQL 역시
도메인 소유권을 무너뜨리면 안 된다.
하나의 거대한 GraphQL 서버가
회사 전체 데이터를 직접 소유하기 시작하면
스키마 비대화
소유권 불명확
변경 영향 증가
가 생길 수 있다.
10. API 메타데이터와 의존 관계
서비스와 API가 많아지면
누가 누구를 사용하는지 추적해야 한다.
예를 들어
flowchart LR
n0["Mobile BFF"] --> n1["Member API"] --> n2["Identity API"]
라는 구조가 있다고 하자.
Identity API에 장애가 발생하면
flowchart LR
n0["Identity"] --> n1["Member"] --> n2["Mobile"]
까지 영향을 받을 수 있다.
API 메타데이터와 Dependency 정보를 잘 관리하면
이런 영향 범위를 파악하기 쉬워진다.
또한
v1 API를 아직 누가 사용하고 있는가?
이 서비스를 삭제해도 되는가?
어떤 API가 Deprecated 상태인가?
같은 Lifecycle 관리에도 도움이 된다.
11. 읽기 지향 API
모든 API가 데이터를 변경할 필요는 없다.
데이터 제품이나 분석 서비스라면
읽기만 제공하는 API가 유용할 수 있다.
GET /reports/sales
GET /rankings
GET /products/active
이러한 API는
Consumer가 데이터베이스를 직접 조회하지 않아도
필요한 데이터를 사용할 수 있게 해준다.
12. CQRS
읽기와 쓰기의 요구사항이 크게 다르다면
두 책임을 분리할 수 있다.
이를
CQRS
Command Query Responsibility Segregation
이라고 한다.
핵심은 매우 단순하다.
- Command — 상태를 변경
- Query — 상태를 읽음
그리고
Command Model
≠
Query Model
로 설계할 수 있다.
13. CQRS가 반드시 DB 두 개를 의미하는 것은 아니다
CQRS를 설명할 때 흔히 다음 구조를 본다.
flowchart LR
n0["Command"] --> n1["Write Model"] --> n2["Write DB"]
flowchart LR
n0["Query"] --> n1["Read Model"] --> n2["Read DB"]
하지만 이것은 CQRS의 한 구현 방법이다.
CQRS의 핵심은
읽기 책임
≠
쓰기 책임
을 분리하는 것이지,
반드시 물리적으로 DB를 두 개 만들어야 한다는 것은 아니다.
같은 DB를 사용하면서
Command Model과 Query Model만 분리할 수도 있다.
14. CQRS와 결과적 일관성
Write Store와 Read Store를 별도로 만들고
비동기 이벤트로 동기화한다면
flowchart LR
n0["Write"] --> n1["Event"] --> n2["Read Model"]
짧은 시간 동안 데이터 차이가 발생할 수 있다.
예를 들어
포인트 차감
Write Store
900
Read Store
아직 1000
인 순간이 생길 수 있다.
시간이 지나면서 Read Store도 900으로 반영된다면
이를 결과적 일관성(Eventual Consistency) 이라고 한다.
하지만 중요한 점은
CQRS 자체가 결과적 일관성을 의미하지는 않는다.
는 것이다.
같은 저장소를 사용하거나
동기식 처리를 한다면 이런 문제가 없을 수도 있다.
15. CQRS와 Event Sourcing도 별개다
초보자가 자주 혼동하는 개념이다.
CQRS
≠
Event Sourcing
둘을 함께 사용하는 시스템이 많을 뿐
서로 다른 패턴이다.
CQRS는
Command와 Query의 책임 분리
가 핵심이고,
Event Sourcing은
현재 상태 자체가 아니라
상태를 만든 이벤트의 기록을 저장
하는 방식이다.
16. CQRS는 성능 최적화만을 위한 것이 아니다
CQRS를
조회가 느림
→ CQRS 적용
정도로만 이해하면 부족하다.
CQRS의 근본적인 목적은
읽기와 쓰기가 서로 다른 모델과 책임을 가질 수 있다는 점을
아키텍처에 명확하게 표현하는 것
이다.
물론 이를 이용하면
- Write — 정합성 중심
- Read — 검색/조회 성능 중심
으로 각각 최적화할 수 있다.
예를 들어
- Write — MariaDB
- Read — Redis / Elasticsearch / Read Replica
같은 구조도 가능하다.
하지만 시스템이 단순하다면
굳이 CQRS를 적용할 필요는 없다.
17. 데이터 제품과 API
6장에서 소개한 데이터 제품과
이번 장의 API는 밀접하게 연결된다.
예를 들어 주문 도메인이
주문 데이터를 다른 도메인에 제공한다고 하자.
flowchart LR
n0["Order Domain"] --> n1["Order Data Product"] --> n2["Read API"] --> n3["다른 Domain"]
이렇게 하면 다른 도메인이
Order DB 직접 조회
를 하지 않아도 된다.
즉, 데이터 제품을 제공하는 인터페이스로
API를 사용할 수 있다.
물론 도메인 간 데이터 공유가
항상 동기 API여야 하는 것은 아니다.
다음과 같은 방법도 가능하다.
API
이벤트
메시지
공식 데이터 제품
중요한 것은
다른 도메인이 상대 도메인의 내부 DB나 구현에
직접 결합하지 않는 것
이다.
18. 도메인 내부와 외부를 구분한다
도메인 내부에서는
상대적으로 구현 변경이 자유롭다.
Commerce Domain
Order
Payment
Refund
하지만 도메인 밖으로 나가는 인터페이스는
더 안정적이어야 한다.
flowchart LR
n0["Commerce"] --> n1["API Contract"] --> n2["Settlement"]
따라서
- 도메인 내부 — 구현 자유도
- 도메인 외부 — 계약 안정성
을 구분하는 것이 중요하다.
19. API 이름에도 비즈니스 언어를 사용한다
비즈니스에서는 “주문“이라고 부르는데
코드와 API에서는
PointGrantTransferTransaction
같은 전혀 다른 용어를 사용한다면
의사소통이 어려워진다.
가능하면
비즈니스 언어
=
도메인 언어
=
API 언어
를 맞추는 것이 좋다.
예를 들어
POST /orders
GET /orders/{id}
처럼 의미가 쉽게 드러나게 만들 수 있다.
이것은 DDD에서 말하는
보편 언어(Ubiquitous Language) 와도 연결된다.
20. 도메인 자율성과 공통 거버넌스
각 도메인이 API를 책임한다고 해서
각 팀이 마음대로 API를 만든다.
는 뜻은 아니다.
조직 전체적으로 필요한 최소한의 기준은
공통으로 정할 수 있다.
예를 들어
API Naming
HTTP Method 사용 원칙
에러 응답 형식
인증 방식
버전 정책
OpenAPI 작성 규칙
로깅
보안 기준
같은 것이다.
즉,
도메인의 자율성
+
조직 공통 거버넌스
를 함께 가져가는 것이다.
이 철학은 앞에서 배운
데이터 메시의 연합형 거버넌스와도 닮아 있다.
21. 기술보다 문제를 먼저 본다
이번 장에는 많은 기술이 등장했다.
SOA
REST
ESB
API Gateway
Microservices
Service Mesh
GraphQL
BFF
CQRS
하지만 이 기술들은 서로 대체 관계가 아니다.
각각 해결하려는 문제가 다르다.
- REST / GraphQL — API 인터페이스와 데이터 접근 방식
- API Gateway — API 진입점과 공통 정책
- Service Mesh — 서비스 간 네트워크 통신
- Microservices — 서비스와 조직의 경계
- BFF — 특정 프론트엔드에 맞는 Backend
- CQRS — Command와 Query의 책임 분리
따라서 모든 시스템에
이 기술들을 전부 적용할 필요는 없다.
작은 시스템이라면
모놀리스
+
REST API
+
MariaDB
만으로 충분할 수 있다.
규모와 문제에 따라
API Gateway
Message Broker
BFF
Service Mesh
CQRS
등을 추가하면 된다.
좋은 아키텍처는
기술을 많이 사용하는 아키텍처가 아니라
현재 문제를 가장 단순한 방법으로 해결하면서
앞으로의 변경도 감당할 수 있는 구조
이다.
22. 9장 정리
네 가지만 기억하면 된다.
작게 나누는 것이 목표가 아니다.
마이크로서비스의 기준은 크기가 아니라 경계다.
잘못 그은 경계는 Service Mesh가 고쳐 주지 않는다.
물리 DB와 데이터 소유권은 다른 문제다.
DB를 나눠야만 소유권이 생기는 것이 아니고,
DB를 합쳤다고 소유권이 사라지는 것도 아니다.
CQRS는 DB 두 개를 뜻하지 않는다.
읽기와 쓰기의 책임을 나누는 것이고,
같은 DB 안에서도 할 수 있다.
Event Sourcing과도 별개다.
조회를 최적화하되 경계를 흐리지 않는다.
BFF와 GraphQL은 화면이 편해지는 만큼
누가 무엇을 책임지는지 흐려지기 쉽다.
기술 이름보다 먼저 답해야 할 질문은 이것들이다.
누가 이 기능을 책임지는가?
누가 이 데이터를 소유하는가?
어떤 경계를 외부에 공개할 것인가?
다른 도메인은 어떤 계약으로 사용할 것인가?
좋은 구조에서는 각 도메인의 책임이 이렇게 보인다.
flowchart LR
subgraph da["Domain A"]
a1["Business Logic"]
a2["Data"]
a3["API / Event"]
end
subgraph db["Domain B"]
b1["Business Logic"]
b2["Data"]
b3["API / Event"]
end
da -- "명확한 계약" --> db
다른 도메인의 DB와 내부 구조를 직접 쓰는 대신
공식적으로 제공되는 API, Event, Message, Data Product를 쓴다.
도메인이 자신의 기능과 데이터를 책임지고,
다른 도메인은 명확하게 정의된 인터페이스로 사용한다.
8장과 9장이 함께 답한 것이 이 한 문장이다.
다음 장에서는 요청과 응답이 아니라
이미 일어난 일을 알리는 방식, 즉 이벤트를 본다.
10장. 이벤트로 연결하기
3부 · 연결 — 경계를 어떻게 넘는가
8장 · 9장 · 10장 · 11장 · 12장
이벤트의 생성부터 전달·처리·저장·운영까지
이벤트 기반 아키텍처를 처음 접하면
보통 Kafka나 메시지 큐부터 떠올리기 쉽다.
하지만 이벤트 기반 아키텍처는
특정 제품이나 기술을 의미하지 않는다.
핵심은 다음과 같다.
시스템에서 발생한 일을
이벤트라는 데이터로 표현하고,
필요한 시스템이 그 이벤트에 반응하도록
시스템을 연결하는 설계 방식이다.
예를 들어 결제가 완료됐다고 해보자.
기존에는 결제 서비스가 직접
flowchart LR
n0["결제 서비스"]
n1["포인트 서비스 호출"]
n2["알림 서비스 호출"]
n3["통계 서비스 호출"]
n0 --> n1
n0 --> n2
n0 --> n3
할 수 있다.
이벤트 기반으로 바꾸면
flowchart TD
n0["결제 서비스"]
n1["PaymentCompleted"]
n2["이벤트 시스템"]
n3["포인트 서비스"]
n4["알림 서비스"]
n5["통계 서비스"]
n0 --> n1
n2 --> n3
n2 --> n4
n2 --> n5
n1 --> n2
처럼 만들 수 있다.
결제 서비스는
“결제가 완료됐다.”
라는 사실만 알린다.
누가 그 정보를 사용하는지는
알 필요가 없다.
이것이 이벤트 기반 아키텍처를 이해하는
가장 중요한 출발점이다.
1. 이벤트란 무엇인가
이벤트(Event)는
이미 발생한 사실
을 의미한다.
예를 들어 다음은 모두 이벤트가 될 수 있다.
회원이 가입했다.
결제가 완료됐다.
상품이 주문됐다.
주문이 완료됐다.
배송이 시작됐다.
고객 정보가 변경됐다.
프로그램에서는 보통 다음처럼 표현할 수 있다.
UserRegistered
PaymentCompleted
OrderCreated
OrderCompleted
DeliveryStarted
CustomerUpdated
이벤트 이름을 과거형으로 표현하는 경우가 많은 것도
이미 발생한 사실을 나타내기 때문이다.
2. Event, Command, Query를 구분하자
메시지라고 해서 전부 이벤트는 아니다.
처음부터 세 개의 차이를 알아두는 것이 좋다.
Event
이미 일어난 사실이다.
PaymentCompleted
OrderCompleted
UserRegistered
의미는
"결제가 완료됐다."
"주문이 완료됐다."
"회원이 가입했다."
이다.
Command
무엇인가를 수행하라는 요청이다.
CreatePayment
CancelOrder
DeductPoint
의미는
"결제해라."
"주문을 취소해라."
"포인트를 차감해라."
이다.
Query
정보를 달라는 요청이다.
GetPayment
GetOrderHistory
GetPointBalance
Query는 일반적으로 시스템 상태를 변경하지 않는다.
정리하면 다음과 같다.
Event
= 이미 발생한 사실
Command
= 무엇인가를 수행하라는 요청
Query
= 정보를 요청
이 세 가지를 명확하게 구분하면
이벤트 기반 시스템의 설계가 훨씬 이해하기 쉬워진다.
3. 요청/응답 구조와 이벤트 기반 구조
전통적인 서비스 통신은
다른 서비스를 직접 호출하는 경우가 많다.
예를 들어:
flowchart LR
n0["주문 서비스"] --> n1["랭킹 서비스 API 호출"] --> n2["알림 서비스 API 호출"] --> n3["통계 서비스 API 호출"]
이 구조의 장점은 흐름이 명확하다는 것이다.
하지만 주문 서비스가
랭킹 서비스
알림 서비스
통계 서비스
를 모두 알고 있어야 한다.
시스템이 커질수록 서비스 사이의 연결도 증가한다.
이벤트 기반에서는 다르게 접근한다.
flowchart TD
n0["주문 서비스"]
n1["OrderCompleted"]
n2["Event Broker"]
n3["랭킹 서비스"]
n4["알림 서비스"]
n5["통계 서비스"]
n0 --> n1
n2 --> n3
n2 --> n4
n2 --> n5
n1 --> n2
주문 서비스는
주문이 완료됐다.
는 사실만 알린다.
랭킹, 알림, 통계 서비스는
각자 필요한 일을 수행한다.
이렇게 서로 직접 알지 않아도 되는 관계를
느슨한 결합(Loose Coupling)
이라고 한다.
4. 동기 통신과 비동기 통신
이벤트 기반 시스템을 이해하려면
동기와 비동기의 차이를 알아야 한다.
동기 통신
서비스 A가 B에게 요청을 보내고
응답이 올 때까지 기다린다.
서비스 A
↓ 요청
서비스 B
↓ 처리
서비스 A
↑ 응답
대표적으로 HTTP API가 있다.
장점은 단순하다는 것이다.
하지만 B가 느리면
A도 기다려야 한다.
B에 장애가 발생하면
A까지 영향을 받을 수도 있다.
비동기 통신
요청 또는 이벤트를 전달한 뒤
바로 다음 작업을 진행할 수 있다.
flowchart TD
n0["서비스 A"]
n1["이벤트 발행"]
n2["메시지 시스템"]
n3["서비스 B"]
n4["서비스 C"]
n5["서비스 D"]
n0 --> n1
n1 --> n2
n2 --> n3
n2 --> n4
n2 --> n5
A는 B, C, D의 처리 완료를
즉시 기다리지 않아도 된다.
이벤트 기반 아키텍처에서는
이런 비동기 통신을 많이 활용한다.
5. 이벤트 알림 방식
이벤트를 만들 때 중요한 설계 문제가 있다.
이벤트에 변경 사실만 넣을 것인가,
필요한 상태까지 함께 넣을 것인가?
대표적으로 두 가지 접근이 있다.
먼저 변경 사실만 알리는 쪽부터 보자.
가장 작은 정보만 전달한다.
예를 들어:
{
"customerId": 100
}
의 의미는
"고객 100의 정보가 변경됐다."
정도이다.
Consumer가 자세한 정보가 필요하다면
고객 서비스에 다시 요청한다.
flowchart LR
n0["CustomerUpdated"] --> n1["Consumer"] --> n2["Customer API"] --> n3["최신 고객 정보 조회"]
장점
이벤트 크기가 작다.
불필요한 개인정보 전파도 줄일 수 있다.
단점
추가 API 호출이 필요하다.
원본 서비스가 장애 상태라면
정보를 가져오지 못할 수 있다.
6. 상태를 함께 전달하는 방식
이벤트 안에 Consumer가 필요한 데이터까지
같이 전달할 수도 있다.
이를 흔히
Event-Carried State Transfer
라고 한다.
예를 들어:
{
"customerId": 100,
"name": "Kim",
"city": "Busan"
}
처럼 보낼 수 있다.
Consumer는 별도 API 호출 없이
이벤트만으로 필요한 데이터를 사용할 수 있다.
flowchart LR
n0["CustomerUpdated"] --> n1["Consumer"] --> n2["자체 데이터 저장"]
7. 상태 전송의 장단점
장점은 Consumer의 독립성이 높아진다는 것이다.
하지만 데이터가 여러 시스템으로 복제되므로
데이터 중복
개인정보 관리
삭제 처리
스키마 변경
정합성 관리
같은 문제가 발생한다.
따라서 다음 트레이드오프가 있다.
이벤트에 데이터를 많이 포함
→ API 의존성 감소
→ 데이터 관리 복잡성 증가
정답은 하나가 아니다.
업무 특성에 따라 결정해야 한다.
8. Producer와 Consumer
이벤트를 만드는 쪽을
Producer
라고 한다.
flowchart LR
n0["주문 서비스"] --> n1["OrderCompleted"]
이벤트를 받아 사용하는 쪽을
Consumer
라고 한다.
flowchart LR
n0["OrderCompleted"]
n1["랭킹"]
n2["정산"]
n3["알림"]
n4["통계"]
n0 --> n1
n0 --> n2
n0 --> n3
n0 --> n4
Producer는 일반적으로
Consumer가 몇 개인지 몰라도 된다.
이것이 이벤트 기반 구조가
서비스 간 결합도를 줄이는 중요한 이유이다.
9. 메시지 큐
이벤트나 작업 메시지를 전달하는
대표적인 방식이 메시지 큐이다.
메시지를 잠시 줄 세워 놓는
대기열이라고 생각하면 된다.
flowchart LR
n0["Producer"] --> n1["Queue"] --> n2["Consumer"]
Producer가 순간적으로 많은 작업을 만들어도
Consumer가 처리할 때까지 큐에 보관할 수 있다.
10. 메시지 큐가 유용한 경우
메시지 큐는 다음 상황에서 유용하다.
작업이 순간적으로 몰릴 때
처리 속도가 서로 다를 때
작업을 여러 Worker에게 분산할 때
재처리가 필요할 때
예를 들어:
flowchart LR
n0["결제 완료"] --> n1["Queue"] --> n2["영수증 생성 Worker"]
영수증 시스템이 잠시 느려져도
결제 시스템 전체가 같이 느려질 필요는 없다.
11. 이벤트 브로커
서비스 사이에서 이벤트를 전달하는 중개자를
Event Broker라고 부른다.
flowchart TD
n0["서비스 A"]
n1["Event Broker"]
n2["서비스 B"]
n3["서비스 C"]
n4["서비스 D"]
n1 --> n2
n1 --> n3
n1 --> n4
n0 --> n1
Broker를 사용하면 Producer가 Consumer에게
직접 연결될 필요가 없다.
12. 메시지 큐와 이벤트 스트림
이벤트 전달 기술이 모두 같은 역할을 하는 것은 아니다.
Message Queue
Event Stream
Event Router
Stream Processing / Aggregation
이 중 가장 헷갈리는 둘을 먼저 비교해 보자.
두 개는 특히 자주 비교된다.
메시지 큐
작업을 분배하는 데 초점이 있다.
flowchart TD
n0["Producer"]
n1["Queue"]
n2["Worker A"]
n3["Worker B"]
n4["Worker C"]
n0 --> n1
n1 --> n2
n1 --> n3
n1 --> n4
하나의 작업을 여러 Worker 중 하나가
처리하는 구조가 대표적이다.
이벤트 스트림
시간 순으로 발생한 이벤트 기록을
일정 기간 유지하면서
여러 Consumer가 각자의 위치에서
독립적으로 읽을 수 있다.
flowchart TD
n0["Producer"]
n1["Event Stream"]
n2["Consumer A"]
n3["Consumer B"]
n4["Consumer C"]
n1 --> n2
n1 --> n3
n1 --> n4
n0 --> n1
Kafka 같은 시스템을 떠올리면 쉽다.
다만 실제 메시징 제품들은 기능이 많이 겹치므로
제품 이름만 보고 완전히 구분하면 안 된다.
13. 이벤트 라우터
이벤트의 내용이나 조건을 보고
목적지를 결정하는 방식이다.
flowchart LR
e["Event"] --> r["Router"]
r -- "payment" --> a["결제 처리"]
r -- "order" --> b["주문 처리"]
r -- "delivery" --> c["배송 처리"]
복잡한 서비스 연결 관계를
중간에서 정리할 때 활용할 수 있다.
14. Fan-out
하나의 이벤트를
여러 Consumer가 독립적으로 사용하는 패턴이다.
flowchart LR
p["Producer"] --> ev["Event"]
ev --> a["Consumer A"]
ev --> b["Consumer B"]
ev --> c["Consumer C"]
예를 들어 OrderCompleted 이벤트를
랭킹
정산
통계
알림
분석
시스템이 각각 사용할 수 있다.
15. 단순 이벤트 처리
이벤트를 어떻게 다루느냐에 따라
처리 방식을 셋으로 나눠 볼 수 있다.
단순 이벤트 처리
스트림 처리
복합 이벤트 처리
가장 단순한 것부터 보자.
하나의 이벤트를 받아
바로 특정 작업을 수행한다.
flowchart LR
n0["OrderCompleted"] --> n1["주문 알림 전송"]
이벤트 하나만 보고 판단하기 때문에
가장 단순한 처리 방식이다.
16. 스트림 처리
계속 들어오는 이벤트의 흐름을
실시간으로 처리한다.
flowchart LR
e["끊임없이 들어오는 Event"] --> sp["Stream Processing"]
예를 들어 최근 1분 동안 발생한 주문을 모아
총 주문 금액
평균 주문 금액
주문 횟수
를 계산할 수 있다.
17. 복합 이벤트 처리
CEP(Complex Event Processing) 는
여러 이벤트 사이의 관계나 패턴을 분석한다.
예를 들어:
flowchart LR
n0["로그인 실패 반복"] --> n1["새로운 지역에서 로그인"] --> n2["비밀번호 변경"] --> n3["고액 결제"]
가 짧은 시간 안에 연속해서 발생했다면
이상 거래 의심
으로 판단할 수 있다.
CEP와 일반적인 스트림 처리는
실제 기술이나 제품에서는 영역이 겹칠 수 있다.
따라서 다음 정도로 이해하면 충분하다.
단순 처리
= 개별 이벤트
스트림 처리
= 이벤트의 연속적인 흐름
CEP
= 여러 이벤트 사이의 복잡한 패턴
18. 윈도우
스트림은 끝없이 들어온다.
따라서
어느 범위를 계산할 것인가?
를 정해야 한다.
이를 Window라고 한다.
Tumbling Window
겹치지 않는 고정 구간이다.
10:00 ~ 10:01
10:01 ~ 10:02
10:02 ~ 10:03
예:
1분 단위 주문 금액 집계
Sliding Window
구간이 서로 겹친다.
10:00 ~ 10:05
10:01 ~ 10:06
10:02 ~ 10:07
예:
매분 최근 5분 평균 방문자 계산
Session Window
사용자의 활동 흐름을 기준으로 구간을 만든다.
클릭
클릭
구매
이후 일정 시간 활동이 없다면
하나의 세션이 끝났다고 볼 수 있다.
19. 애플리케이션에서 직접 이벤트 생성
이벤트는 반드시 애플리케이션 코드에서만 생성할 필요는 없다.
애플리케이션에서 직접 생성
Polling
DB Trigger
CDC
네 가지를 차례로 보자.
가장 자연스러운 방법이다.
flowchart LR
n0["주문 처리"] --> n1["DB 저장"] --> n2["OrderCompleted 생성"] --> n3["Broker 전송"]
하지만 문제가 있다.
flowchart LR
n0["DB 저장 성공"] --> n1["이벤트 전송 실패"]
한다면
DB에는 정상 처리됐지만
이벤트를 받아야 할 시스템은 알지 못한다.
이런 문제를 해결하기 위해
Transactional Outbox Pattern 같은 방식을 사용하기도 한다.
20. Polling
별도의 프로그램이 DB를
주기적으로 확인한다.
10:00 DB 조회
10:01 DB 조회
10:02 DB 조회
예를 들어:
SELECT *
FROM orders
WHERE updated_at > :last_checked_time;
같은 방식이다.
구현은 비교적 쉽다.
하지만 조회 주기가 너무 짧으면
DB 부하가 증가한다.
반대로 조회 주기가 길면
이벤트 전달도 늦어진다.
21. DB Trigger
DB 데이터가 변경되는 순간
추가 로직을 자동 실행하는 방식이다.
flowchart LR
n0["orders INSERT"] --> n1["Trigger"] --> n2["event_outbox INSERT"]
즉각적인 처리가 가능하지만
비즈니스 로직이 DB Trigger에 많이 들어가면
로직 추적
장애 분석
성능 관리
DB 종속성
이 복잡해질 수 있다.
22. CDC
Change Data Capture는
데이터베이스의 변경 내용을 감지하여
다른 시스템으로 전달하는 기술
이다.
MySQL/MariaDB 환경에서는
binlog 기반 CDC가 대표적인 방식이다.
flowchart LR
n0["Application"] --> n1["Database"] --> n2["Transaction Log"] --> n3["CDC Connector"] --> n4["Event Stream"]
Debezium 같은 도구가 대표적이다.
단, CDC 전체가 반드시
트랜잭션 로그 방식만을 의미하는 것은 아니다.
23. CDC 이벤트와 비즈니스 이벤트는 다르다
이 차이는 반드시 알아야 한다.
예를 들어 데이터베이스에서
balance
1000 → 900
으로 변경됐다고 하자.
CDC가 발견한 것은
잔액 데이터가 변경됐다.
는 사실이다.
하지만 비즈니스 의미는
주문으로 100을 사용했다.
일 수도 있고
관리자가 잔액을 조정했다.
일 수도 있다.
따라서
DB Change Event
≠ Business Event
이다.
CDC만으로 모든 비즈니스 의미를
표현할 수 있다고 생각하면 안 된다.
24. 레거시를 옮길 때도 쓸 수 있다
기존 시스템을 한 번에 걷어내지 않고
기능을 하나씩 새 서비스로 옮기는 방법이 있다.
이때 이벤트를 기존 시스템과 새 시스템 사이의
연결 수단으로 쓸 수 있다.
새 서비스가 기존 시스템의 이벤트를 구독하면
양쪽을 동시에 고치지 않아도 된다.
점진적으로 옮기는 방법은
23장 「실행 로드맵」에서 다룬다.
25. 이벤트를 저장해야 하는 이유
이벤트를 실시간 처리한 뒤
바로 폐기할 수도 있다.
하지만 장기간 저장하면
다른 가치를 만들 수 있다.
예를 들어 주문 이벤트를 저장하면
랭킹
통계
정산
과거 분석
이상 거래 탐지
추천 모델
등에 다시 사용할 수 있다.
26. 이벤트 저장소
이벤트를 저장하는 저장소를
넓은 의미에서 Event Store라고 부를 수 있다.
하지만 주의해야 할 것이 있다.
단순히 이벤트를 오래 보관한다고 해서
모두 Event Sourcing의 Event Store가 되는 것은 아니다.
일반적인 이벤트 보관소는
재처리나 분석을 위한 저장소일 수 있다.
Event Sourcing에서의 Event Store는
애플리케이션 상태를 구성하는 핵심 기록이라는
더 강한 의미를 갖는다.
27. Replay
이벤트를 저장해두면
과거 이벤트를 다시 처리할 수 있다.
이를 Replay라고 한다.
예를 들어 랭킹 계산에 버그가 있었다면
flowchart LR
n0["과거 주문 이벤트"] --> n1["수정된 계산 코드"] --> n2["랭킹 다시 생성"]
할 수 있다.
이벤트 저장의 큰 장점이다.
28. Event Sourcing
Event Sourcing은
현재 상태의 원천을
상태를 만들어낸 이벤트 기록으로 두는 방식
이다.
일반적인 방식에서는
balance = 700
처럼 현재 상태를 저장한다.
Event Sourcing에서는
PointCharged +1000
PointUsed -100
PointUsed -200
같은 이벤트를 기록한다.
현재 상태는
1000 - 100 - 200
= 700
으로 다시 만들 수 있다.
29. Event Sourcing은 현재 상태를 저장하면 안 되는가
그렇지 않다.
Event Sourcing에서 이벤트가
궁극적인 원천(Source of Truth)이지만
성능을 위해
Snapshot
Materialized View
Read Model
같은 현재 상태 데이터를
별도로 저장하는 경우도 많다.
예를 들어 이벤트가 백만 건 있다면
매번 처음부터 재생하는 것은 비효율적이다.
그래서 중간 상태를 Snapshot으로 저장할 수 있다.
flowchart LR
n0["Event 1 ~ 10000"] --> n1["Snapshot"] --> n2["10001 이후 이벤트만 적용"]
30. 이벤트와 CQRS
CQRS는 읽기와 쓰기에 서로 다른 모델을 사용하는 방식이다.
DB를 반드시 두 개 만드는 것은 아니라는 점을 포함해
자세한 내용은 9장 「서비스 경계와 조회 모델」에서 다뤘다.
이벤트를 이용하여
Read Model을 만들 수도 있다.
flowchart LR
n0["Command"] --> n1["Write Model"] --> n2["Domain Event"] --> n3["Read Model 갱신"]
예를 들어 쓰기 모델에서는
복잡한 정합성을 유지하고
조회 모델에서는
사용자별 주문 내역
판매자별 오늘 주문 금액
최근 상품 목록
처럼 조회 목적에 최적화된 데이터를 만들 수 있다.
31. 이벤트 데이터를 데이터 제품으로 활용하기
이벤트 데이터를 장기간 보관하면
데이터 분석에도 활용할 수 있다.
대표적으로 데이터 레이크나 Lakehouse에서는
flowchart LR
n0["Bronze"] --> n1["Silver"] --> n2["Gold"]
구조를 사용할 수 있다.
이를 흔히 Medallion Architecture라고 한다.
다만 이 구조는
이벤트 기반 아키텍처의 필수 요소가 아니라
데이터 플랫폼에서 사용할 수 있는 별도의 패턴
이다.
32. 스트리밍 분석
데이터가 발생할 때
바로 분석할 수도 있다.
flowchart LR
n0["Event"] --> n1["Streaming Analytics"] --> n2["Dashboard / Alert"]
예를 들어:
현재 매출
현재 접속자
최근 5분 오류율
현재 주문 금액
을 실시간으로 계산할 수 있다.
33. 데이터 보강
이벤트 자체에 필요한 정보가
전부 들어있지 않을 수도 있다.
예를 들어:
{
"userId": 100,
"amount": 5000
}
만 들어왔는데 분석에는
회원 등급
국가
가입일
정보가 필요할 수 있다.
이때 다른 데이터와 결합한다.
flowchart TD
n0["Event"]
n2["Reference Data"]
n3["Enriched Event"]
n0 --> n3
n2 --> n3
이를 Data Enrichment라고 한다.
34. 스트리밍 플랫폼은 DB와 다르다
Kafka 같은 시스템을
일반적인 데이터베이스와 똑같이 보면 안 된다.
이벤트 스트리밍 플랫폼은 주로
대규모 순차 이벤트 처리
Consumer별 독립적 소비
Replay
스트림 처리
에 강하다.
일반적인 데이터베이스는
특정 데이터 조회
조건 검색
인덱스
JOIN
트랜잭션
등에 강하다.
아주 단순화하면:
Event Stream
= 사건의 흐름
Database
= 상태의 저장과 조회
라고 이해할 수 있다.
물론 현대 시스템들은 서로의 기능 일부를 제공하기도 하므로
절대적인 구분은 아니다.
35. 내부 이벤트와 외부 공개 이벤트
시스템이 커지면
모든 이벤트를 다른 도메인에 공개해서는 안 된다.
크게 다음처럼 구분할 수 있다.
내부 이벤트
외부 계약용 이벤트
책이나 조직에 따라 이를
Internal Stream
Domain Stream
Business Stream
Integration Event
등 다양한 이름으로 부를 수 있다.
용어보다 경계를 이해하는 것이 중요하다.
36. 내부 이벤트
도메인 내부 구현을 위한 이벤트이다.
예를 들어:
OrderValidated
PointDeductionStarted
PointDeductionFinished
같은 이벤트이다.
다른 도메인이 이런 이벤트까지
직접 사용하면 내부 구현을 변경하기 어려워진다.
37. 외부 계약용 이벤트
다른 도메인이 사용하도록
명확하게 공개하는 이벤트이다.
예:
OrderCompleted
PaymentCompleted
DeliveryStarted
이 이벤트는 다른 팀과 시스템이 사용하므로
스키마
의미
버전
호환성
소유자
를 계약처럼 관리해야 한다.
쉽게 비교하면:
Internal Event
≈ private interface
공개 Domain Event
≈ public API
라고 생각할 수 있다.
38. 이벤트 거버넌스
이벤트가 수백 개, 수천 개로 늘어나면
기술보다 관리가 더 어려워질 수 있다.
다음 질문에 답할 수 있어야 한다.
이 이벤트의 소유자는 누구인가?
누가 사용하고 있는가?
스키마는 어디에 있는가?
현재 버전은 무엇인가?
이 필드를 삭제해도 되는가?
얼마나 오래 보관하는가?
개인정보가 포함되어 있는가?
이것을 체계적으로 관리하는 것이
이벤트 거버넌스이다.
39. 이벤트의 소유권
일반적으로 이벤트를 발행하는 도메인이
그 이벤트의 소유자가 된다.
예:
OrderCompleted
Owner
= Order Domain
소유자는 보통 다음을 책임진다.
이벤트 의미
스키마
문서
버전
호환성
품질
즉 이벤트를 외부에 공개했다는 것은
단순히 메시지 하나를 보낸 것이 아니라
다른 시스템과 계약을 만든 것
이라고 이해해야 한다.
40. Schema Registry
이벤트의 스키마와 버전을 관리하기 위해
Schema Registry를 사용할 수 있다.
기존 이벤트가:
{
"userId": 100,
"amount": 5000
}
이라고 하자.
그런데 Producer가 갑자기:
{
"memberId": 100,
"price": 5000
}
로 바꾸면 기존 Consumer가 깨질 수 있다.
Schema Registry와 호환성 정책을 사용하면
필드 삭제
타입 변경
필수 필드 변경
스키마 버전
등을 검사할 수 있다.
단,
Registry가 있다고 자동으로 안전해지는 것은 아니다.
CI/CD 과정에서 스키마 호환성을 검증하고
조직의 변경 정책을 함께 적용해야 한다.
41. Contract-First
이벤트가 많아질수록
구현 전에 계약을 먼저 정의하는 것이 좋다.
좋지 않은 흐름:
flowchart LR
n0["코드 구현"] --> n1["이벤트 생성"] --> n2["나중에 문서 작성"]
Contract-First 방식:
flowchart LR
n0["이벤트 의미 정의"] --> n1["스키마 정의"] --> n2["호환성 검토"] --> n3["Producer 구현"] --> n4["Consumer 구현"]
REST API의 API-First와
비슷한 사고방식이다.
42. AsyncAPI
이벤트 기반 인터페이스를 문서화하는 데
AsyncAPI 같은 표준을 사용할 수 있다.
초보자 관점에서는 다음과 같이 이해하면 된다.
- HTTP REST API — OpenAPI
- 이벤트/메시지 기반 API — AsyncAPI
이를 통해
채널
메시지
Payload
Schema
Producer
Consumer
등을 문서화할 수 있다.
OpenAPI와 완전히 동일한 역할은 아니지만
비슷한 목적의 계약 문서라고 이해하면 된다.
43. 셀프서비스와 플랫폼 팀
조직이 커지면
중앙 플랫폼 팀이 모든 이벤트를 직접 관리하기 어렵다.
그래서 플랫폼 팀은
이벤트 플랫폼
Schema Registry
Event Catalog
모니터링
보안 정책
배포 자동화
등을 제공한다.
각 도메인 팀은 그 위에서
이벤트 생성
스키마 등록
배포
소비
를 스스로 할 수 있다.
이런 구조를 셀프서비스 방식이라고 볼 수 있다.
44. 셀프서비스에는 가드레일이 필요하다
셀프서비스는
아무렇게나 만들 수 있다.
는 뜻이 아니다.
다음과 같은 검사를 자동화하는 것이 좋다.
이벤트 이름 규칙
스키마 호환성
소유자 등록
보안 검사
보존 기간
개인정보 여부
즉,
개발자가 빠르게 작업할 수 있도록 하되
위험한 변경은 자동으로 막는 것
이 좋은 플랫폼의 역할이다.
이 생각을 조직 전체로 넓히면
22장 「플랫폼과 조직」의 이야기가 된다.
45. 10장 정리
네 가지만 기억하면 된다.
이벤트는 이미 발생한 사실이다.
무엇을 해달라는 Command,
정보를 달라는 Query와 구분해야 한다.
Producer는 Consumer가 누구인지 몰라도 된다.
이것이 이벤트가 결합도를 낮추는 이유다.
이벤트에 무엇을 담을지가 설계의 핵심이다.
변경 사실만 알릴 것인가,
필요한 상태까지 함께 보낼 것인가에 따라
API 의존성과 데이터 관리 부담이 반대로 움직인다.
내부 이벤트와 공개 이벤트를 나눠야 한다.
공개한 이벤트는 메시지 하나가 아니라
다른 시스템과 맺은 계약이다.
여기까지는 이벤트를 만들고 전달하는 이야기였다.
다음 장에서는 만든 다음에 찾아오는 문제,
즉 운영을 본다.
11장. 이벤트를 운영한다는 것
3부 · 연결 — 경계를 어떻게 넘는가
8장 · 9장 · 10장 · 11장 · 12장
이벤트를 도입하고 한 달이 지났다.
같은 알림이 두 번 갔다는 문의가 들어오고,
어떤 정산은 순서가 뒤바뀐 채 처리됐다.
처리에 실패한 메시지가 어디로 갔는지도
아무도 모른다.
10장에서 이벤트를 설계하고 전달하는 방법을 봤다.
하지만 이벤트 기반 시스템의 어려움은
대부분 만든 다음에 찾아온다.
이 장에서는 운영에서 마주치는 문제를 다룬다.
중복과 순서, 실패와 재처리,
쌓이는 메시지, 스키마 변경, 보존 기간이다.
이벤트 기반 아키텍처가 공짜가 아닌 이유가 여기 있다.
1. 이벤트의 불변성
이벤트는 이미 발생한 사건이다.
따라서 기본적으로
Immutable
하게 취급하는 것이 좋다.
예를 들어:
OrderCompleted
이 잘못된 이벤트였다면
기존 이벤트를 수정하는 것이 아니라
OrderCancelled
또는
OrderCorrected
같은 새로운 이벤트를 발생시키는 방식이다.
즉:
과거의 사건을 수정 X
새로운 사건을 추가 O
라고 생각하면 된다.
2. 결과적 일관성
이벤트 기반 시스템은
여러 시스템이 동시에 갱신되지 않는 경우가 많다.
예를 들어:
10:00:00 결제 완료
10:00:01 통계 반영
10:00:03 정산 반영
10:00:02 시점에는
결제 시스템
= 반영 완료
정산 시스템
= 아직 미반영
일 수 있다.
하지만 새로운 변경이 없고
이벤트 전달과 재처리가 정상적으로 계속된다면
결국 같은 상태로 수렴할 수 있다.
이를 Eventual Consistency,
결과적 일관성이라고 한다.
3. 강한 일관성
강한 일관성이 필요한 시스템도 있다.
단순하게 말하면
성공한 최신 변경을
이후의 읽기에서 일관되게 볼 수 있도록 하는 강한 보장
이다.
예를 들어 중요한 잔액 데이터라면
flowchart LR
n0["1000"] --> n1["300 사용"] --> n2["700"]
이라는 결과가 즉시 중요할 수 있다.
분산 시스템에서 강한 일관성을 구현하려면
노드 간 추가적인 조정이 필요하다.
그 결과
지연 증가
처리량 감소 가능성
가용성과의 트레이드오프
가 발생할 수 있다.
중요한 것은
강한 일관성
= 무조건 모든 노드를 Lock
이 아니라는 것이다.
구현에는 Consensus, Quorum 등
여러 방식이 사용될 수 있다.
4. 데이터마다 일관성 요구는 다르다
모든 데이터를
같은 수준으로 처리할 필요는 없다.
예:
실시간 인기 랭킹
→ 몇 초 지연 가능
→ 결과적 일관성 가능
반면:
결제 승인
잔액 차감
재고 확정
같은 영역은 더 강한 정합성이
필요할 수 있다.
따라서
업무의 중요도와 요구사항에 따라
일관성 모델을 선택한다.
가 중요하다.
5. 메시지 전달과 처리 보장
메시징 시스템에서는
At-most-once
At-least-once
Exactly-once
라는 표현이 자주 등장한다.
여기서 중요한 것은
어떤 범위에서 무엇을 보장하는가?
를 반드시 확인하는 것이다.
Broker 수준의 전달과
외부 DB까지 포함한 전체 비즈니스 처리는
다른 문제일 수 있기 때문이다.
6. At-most-once
최대 한 번 처리되는 방식이다.
0번 또는 1번
재전송하지 않는다면
메시지가 유실될 수 있다.
대신 중복 가능성은 줄어든다.
7. At-least-once
최소 한 번은 처리하도록
재전송하는 방식이다.
1번 이상
따라서 같은 이벤트가
여러 번 들어올 수 있다.
실무에서는 매우 흔한 방식이다.
8. 멱등성
At-least-once 환경에서는
Consumer의 멱등성이 중요하다.
Idempotency란
같은 작업을 여러 번 수행해도
최종 결과가 한 번 수행한 것과 동일하도록 만드는 것
이다.
예를 들어:
event_id = 100
이라는 주문 이벤트가 두 번 전달됐다고 하자.
잘못된 처리:
100 지급
100 지급
→ 총 200
멱등하게 처리하면:
flowchart TD
n0["event_id=100 처리"]
n1["다시 event_id=100 수신"]
n2["이미 처리됨"]
n3["무시"]
n0 --> n2
n1 --> n2
n2 --> n3
할 수 있다.
9. Exactly-once
Exactly-once는 이름 그대로
유실 없이
중복 효과 없이
정확히 한 번
을 목표로 한다.
하지만 분산 시스템 전체에서
End-to-End Exactly-once를 구현하는 것은 어렵다.
예를 들어:
flowchart LR
n0["Kafka 이벤트 읽음"] --> n1["DB UPDATE 성공"] --> n2["Kafka offset 저장 전 장애"]
가 발생하면
다시 실행된 Consumer가
같은 이벤트를 또 읽을 수 있다.
따라서 Kafka 자체의 트랜잭션 기능이 있다고 해서
Kafka
DB
외부 결제 API
메일 서비스
전체 작업이 자동으로 Exactly-once가 되는 것은 아니다.
현실에서는 흔히
At-least-once
+
멱등성
을 이용해
중복 효과를 방지한다.
10. 메시지 순서
이벤트는 순서가 중요할 수 있다.
예를 들어:
UserCreated
UserUpdated
UserDeleted
순서가 뒤집히면 문제가 발생할 수 있다.
분산 시스템에서는 병렬 처리가 많기 때문에
전체 이벤트의 순서를 보장하는 것은 비용이 크다.
11. Kafka와 메시지 순서
Kafka에서는 기본적으로
같은 Partition 내부에서 순서가 유지된다.
라고 이해해야 한다.
예를 들어 하나의 주문과 관련된 이벤트를
같은 Partition으로 라우팅하면
OrderCreated
PaymentCompleted
OrderCompleted
순서를 유지하기 쉬워진다.
흔히 Key를 이용해
같은 엔티티를 동일 Partition으로 라우팅한다.
하지만 정확한 표현은
같은 Key라서 순서가 보장된다.
가 아니라
동일 Partition 안에서 순서가 보장된다.
이다.
12. 전체 순서보다 엔티티 단위 순서
모든 이벤트를 하나의 Partition에 넣으면
전체 순서를 유지하기 쉽다.
하지만 병렬 처리 성능이 크게 떨어진다.
그래서 현실에서는
user_id
order_id
payment_id
delivery_id
같은 특정 Key 단위로
순서를 관리하는 경우가 많다.
13. Dead Letter Queue
처리를 계속 실패하는 메시지를
별도 공간으로 옮길 수 있다.
이를 Dead Letter Queue, DLQ라고 한다.
flowchart LR
n0["Main Queue"] --> n1["Consumer"] --> n2["실패"] --> n3["Retry"] --> n4["계속 실패"] --> n5["DLQ"]
예를 들어:
잘못된 메시지 형식
필수 데이터 누락
Consumer 버그
지원하지 않는 이벤트 버전
등으로 실패할 수 있다.
14. DLQ를 만들었다고 끝이 아니다
DLQ가 있는데 아무도 확인하지 않는다면
사실상 데이터 쓰레기통이 된다.
따라서 반드시
모니터링
알림
원인 분석
수정
재처리
과정이 필요하다.
DLQ는 기술 기능인 동시에
운영 프로세스가 필요한 영역이다.
15. Backlog와 Backpressure
Producer가 Consumer보다
훨씬 빠르게 데이터를 생성한다고 해보자.
Producer
초당 10,000건
Consumer
초당 3,000건
그러면 처리되지 못한 메시지가 계속 쌓인다.
이를 Backlog라고 볼 수 있다.
flowchart LR
n0["입력 > 처리량"] --> n1["Backlog 증가"] --> n2["지연 증가"] --> n3["저장 공간 증가"]
Backpressure란 무엇인가
Backpressure는 backlog 자체를 의미하는 것이 아니다.
Consumer나 하위 시스템의 처리 능력에 맞춰
상위 시스템의 데이터 생산 속도를 조절하는 메커니즘
이다.
예를 들어:
flowchart LR
n0["Consumer 처리 한계 감지"] --> n1["Producer 전송 속도 감소"]
처럼 흐름을 제어할 수 있다.
시스템에 따라
생산 속도 제한
Consumer 확장
버퍼링
Batch 처리
Load Shedding
등 다양한 대응 전략을 사용할 수 있다.
16. 직렬화
Java Object나 Go Struct를
그대로 네트워크에 보낼 수는 없다.
전송 가능한 데이터 형식으로 변환해야 한다.
이를 Serialization,
직렬화라고 한다.
flowchart LR
n0["Application Object"] --> n1["Serialization"] --> n2["Message"]
Consumer에서는 반대로
flowchart LR
n0["Message"] --> n1["Deserialization"] --> n2["Application Object"]
을 수행한다.
17. JSON
가장 익숙한 데이터 형식이다.
{
"userId": 100,
"amount": 5000
}
장점:
사람이 읽기 쉬움
개발하기 쉬움
언어 독립적
범용성이 높음
단점:
상대적으로 데이터 크기가 큼
스키마 강제가 약함
타입 표현이 제한적
이다.
18. Avro와 Protocol Buffers
대규모 이벤트 시스템에서는
Apache Avro
Protocol Buffers
Apache Thrift
같은 직렬화 기술도 사용된다.
이들은 명확한 스키마를 기반으로
데이터 타입과 구조를 관리하기 좋다.
예를 들어:
flowchart LR
n0["Schema 정의"] --> n1["Producer"] --> n2["Binary Message"] --> n3["Consumer"]
형태로 처리한다.
초보자 관점에서는
JSON
= 유연하고 쉬움
Avro / Protobuf
= 스키마를 강하게 관리하기 좋음
정도로 이해하면 충분하다.
19. 이벤트 스트림의 장기 보존
이벤트 스트리밍 플랫폼에
데이터를 장기간 보존할 수도 있다.
하지만 보존 기간이 늘어나면
저장 비용
운영 비용
개인정보 관리
삭제 정책
규제 준수
등을 고려해야 한다.
따라서 무조건
모든 이벤트 무기한 저장
하는 것이 좋은 것은 아니다.
20. Hot / Cold Storage 분리
최근 데이터와 오래된 데이터를
다른 저장소에 둘 수도 있다.
예:
- 최근 7일 이벤트 — Event Streaming Platform
- 7일 이전 — Object Storage / Data Lake
이렇게 하면
실시간 처리
= Streaming Platform
장기 분석
= Data Lake
처럼 역할을 나눌 수 있다.
21. 공통 플랫폼과 비즈니스 로직 분리
이벤트 플랫폼에는 가급적
범용적인 기능을 둔다.
예를 들어:
전송
저장
라우팅
스키마 검사
모니터링
보안
이다.
반면 다음 같은 비즈니스 규칙은
환불 가능 여부
주문 계산
출금 환산율
회원 등급
해당 도메인 안에 두는 것이 좋다.
플랫폼이 모든 비즈니스 규칙을 알기 시작하면
플랫폼 자체가 거대한 업무 시스템이 되기 때문이다.
22. 모든 것을 이벤트 기반으로 만들 필요는 없다
이벤트 기반 아키텍처는 강력하다.
하지만 다음과 같은 복잡성도 가져온다.
Broker
Schema 관리
Retry
DLQ
멱등성
순서 처리
모니터링
분산 추적
결과적 일관성
단순 CRUD 시스템에 이 모든 것을 도입하면
얻는 가치보다 운영 비용이 더 클 수 있다.
따라서 질문은
"이벤트 기반으로 만들 수 있는가?"
가 아니라
"이벤트 기반으로 만들 가치가 있는가?"
여야 한다.
23. 이벤트 기반 아키텍처가 잘 맞는 경우
다음과 같은 상황이라면
EDA가 큰 장점을 줄 수 있다.
하나의 사건에 여러 시스템이 반응해야 한다.
서비스 간 직접 의존성을 줄이고 싶다.
비동기 처리가 필요하다.
실시간 데이터 처리가 중요하다.
대량의 이벤트가 발생한다.
과거 이벤트를 다시 처리해야 한다.
여러 분석 시스템에 데이터를 제공해야 한다.
반대로 단순한 내부 관리 시스템이라면
일반적인 API 구조가 더 적합할 수도 있다.
24. 11장 정리
네 가지만 기억하면 된다.
이벤트는 중복될 수 있다고 가정한다.
At-least-once가 현실적인 기본값이고,
그래서 Consumer를 여러 번 처리해도 괜찮게 만든다.
Exactly-once는 조건이 붙는 보장이다.
순서는 전체가 아니라 필요한 단위만 보장한다.
모든 메시지의 전역 순서를 지키려 하면 처리량을 잃는다.
같은 주문, 같은 회원처럼 엔티티 단위면 대개 충분하다.
실패한 메시지는 어디론가 가야 하고, 누군가 봐야 한다.
DLQ를 만들어 두는 것과 그것을 들여다보는 것은 다른 일이다.
아무도 보지 않는 DLQ는 쓰레기통이다.
Kafka를 쓴다고 이벤트 기반 아키텍처가 되는 것은 아니다.
설계, 소비, 스키마, 중복, 순서, 장애 처리까지가 EDA다.
이벤트의 수명주기
이벤트는 만들고 끝나는 것이 아니다.
flowchart TB
S1["만든다<br/>──────────<br/>사건이 발생하면 Application · CDC · Polling으로<br/>이벤트를 만든다"]
S2["보낸다<br/>──────────<br/>Queue · Broker · Stream · Router로 전달한다"]
S3["쓴다<br/>──────────<br/>단순 처리와 스트림 처리를 거쳐<br/>랭킹 · 알림 · 정산 · 통계가 소비한다"]
S4["쌓는다<br/>──────────<br/>Event Store에 보관하고<br/>Replay · 분석 · 머신러닝에 쓴다"]
S5["지킨다<br/>──────────<br/>재시도 · DLQ · 순서 · 멱등성<br/>백프레셔 · 모니터링"]
S6["다스린다<br/>──────────<br/>Owner · 스키마 · 버전<br/>계약 · 보안 · 보존 기간"]
S1 --> S2 --> S3 --> S4
S4 -.-> S5
S5 -.-> S6
style S1 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S2 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S3 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S4 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S5 fill:#f8fbff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style S6 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
위 넷은 10장에서, 아래 둘은 이 장에서 다뤘다.
만드는 것보다 지키고 다스리는 쪽이 어렵다.
새 이벤트를 설계할 때 던질 질문
이것은 정말 이벤트인가, 아니면 Command인가?
Producer는 누구이고 소유 도메인은 어디인가?
누가 Consumer인가?
어떤 데이터를 담을 것인가? 개인정보가 포함되는가?
중복 전달되어도 안전한가?
순서가 중요한가? 어느 단위까지 중요한가?
실패하면 어떻게 재시도하고, DLQ는 누가 보는가?
얼마나 오래 보관하고, 스키마 변경은 어떻게 관리하는가?
과거 이벤트를 Replay해야 하는가?
무엇을 모니터링할 것인가?
이 질문에 답할 수 있다면
운영에서 만날 문제를 상당 부분 미리 발견할 수 있다.
공짜가 아니다
이벤트로 서비스 간 결합은 줄일 수 있다.
대신 새로운 복잡성이 온다.
분산 시스템
비동기 처리
결과적 일관성
중복 처리
장애 복구
운영과 모니터링
그래서 좋은 설계의 기준은
최대한 많이 이벤트로 만드는 것이 아니다.
늘어나는 복잡성을 감수할 만큼
분명한 비즈니스 가치가 있는 곳에
이벤트 기반 구조를 쓰는 것.
다음 장에서는 API와 이벤트와 배치 가운데
무엇을 언제 고를지를 정리한다.
12장. 무엇으로 연결할 것인가
3부 · 연결 — 경계를 어떻게 넘는가
8장 · 9장 · 10장 · 11장 · 12장
8장과 9장에서는 API를,
10장과 11장에서는 이벤트를 따로 살펴봤다.
하나씩 볼 때는 분명해 보인다.
그런데 실제 시스템에서 둘 중 하나만 쓰는 경우는 드물다.
업무 하나를 처리하는 데도 API와 이벤트가 함께 등장하고,
아직 이름조차 꺼내지 않은 선택지가 하나 더 있다.
배치다.
이번 장의 질문은 하나다.
지금 이 연결에는 무엇이 맞는가?
API, 이벤트, 배치는 서로를 대체하는 기술이 아니다.
각각 잘 푸는 문제가 다르다.
그 차이를 정리하는 것이 이 장의 목적이다.
1. 하나의 업무에도 여러 방식이 함께 쓰인다
사용자가 10,000원짜리 상품을 주문한다고 해보자.
겉으로는 단순한 기능처럼 보인다.
하지만 실제로는 여러 시스템이 연결된다.
flowchart LR
u["사용자"]
o["주문 서비스"]
p["포인트 서비스"]
done["주문 완료"]
noti["알림"]
rank["랭킹"]
settle["정산"]
plat["데이터 플랫폼"]
dp["Data Product"]
bi["BI"]
an["분석"]
ml["ML"]
u --> o
o -- "포인트 차감 요청" --> p
p -- "차감 성공" --> done
done -- "Event" --> noti
done -- "Event" --> rank
done -- "Event" --> settle
done -- "Event" --> plat
plat --> dp
dp --> bi
dp --> an
dp --> ml
이 그림 하나에 세 가지 방식이 이미 섞여 있다.
포인트 차감은 결과를 바로 알아야 하므로 동기 API로 부른다.
주문이 끝난 뒤의 알림, 랭킹 반영, 정산, 분석 데이터 적재는
주문 요청 안에서 다 끝날 필요가 없다.
이런 일은 이벤트로 흘려보낸다.
오래 쌓아 두고 분석할 데이터는
다시 별도의 데이터 프로덕트로 제공한다.
그래서 중요한 질문은 “API가 좋은가, 이벤트가 좋은가“가 아니다.
지금 해결하려는 문제에
어떤 방식이 맞는가?
이 장은 그 답을 이렇게 찾아간다.
먼저 도메인을 어떤 창구로 이어야 하는지,
그리고 무엇을 위해 잇는지를 정리한다.
그다음 API·이벤트·배치를 차례로 보고
마지막에 선택 기준으로 모은다.
2. 도메인을 나눠도 통신은 해야 한다
회사 시스템을 회원·결제·상품·주문·배송·정산으로 나눴다고 하자.
각각 다른 책임을 갖지만,
주문 하나를 처리하려면 회원 정보와 포인트 잔액과 배송 상태가 모두 필요하다.
도메인을 나눈다는 것은 서로 단절시키겠다는 뜻이 아니다.
독립적인 책임을 유지하면서도 필요한 정보는 주고받을 수 있어야 한다.
이를 상호운용성(Interoperability) 이라고 한다.
문제는 주고받는 방법이다.
가장 간단한 방법은 남의 DB를 직접 조회하는 것이다.
SELECT *
FROM payment.payment_history
WHERE user_id = 100;
처음에는 편하다. 별도의 API도 필요 없다.
하지만 이런 접근이 쌓이면
결제팀이 테이블 하나를 바꿀 때마다
누가 그 테이블을 쓰는지 전부 찾아야 한다.
도메인은 나눴는데 실제로는 더 강하게 묶인 상태가 된다.
7장 「무엇을 공개하고 무엇을 감출 것인가」에서 본 문제다.
그래서 각 도메인은 내부 구현 대신 공개된 계약을 내놓는다.
flowchart LR
OTHER["다른 도메인"]
subgraph DOMAIN["결제 도메인"]
CONTRACT["외부 인터페이스<br/><br/>Payment API<br/>PaymentCompleted Event<br/>Payment Data Product"]
subgraph INNER["🔒 내부 구현"]
T1["payment"]
T2["payment_detail"]
T3["pg_log"]
end
CONTRACT --> INNER
end
OTHER -->|"공개된 계약만 사용"| CONTRACT
style CONTRACT fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style INNER fill:#f5f5f5,stroke:#999,stroke-dasharray: 5 5,color:#1a1a1a
여기서 초보자가 자주 오해하는 것이 하나 있다.
도메인을 나누려면
반드시 DB도 각각 분리해야 하는가?
그렇지 않다.
하나의 MariaDB를 쓰면서도
스키마로 소유권을 나누면 논리적인 경계를 만들 수 있다.
중요한 것은 물리적인 DB 개수가 아니라
누가 어떤 데이터에 접근할 책임을 가지고 있는가다.
flowchart LR
ORDER["Order Domain"]
COMMERCE["Commerce Domain"]
subgraph DB["하나의 MariaDB"]
OT[("order.*")]
CT[("commerce.*")]
ST[("settlement.*")]
MT[("member.*")]
end
ORDER --> OT
COMMERCE --> CT
ORDER -. "❌ 직접 접근 금지<br/>필요하면 Commerce 도메인에 요청" .-x CT
style DB fill:#fafafa,stroke:#999,color:#1a1a1a
즉,
물리적인 데이터베이스 분리와
논리적인 도메인 분리는 서로 다른 문제다.
정리하면 도메인끼리는 공개된 창구로만 잇는다.
그 창구의 형태가 바로 API, 이벤트, 배치다.
어떤 형태를 고를지는 무엇을 위해 잇는지에 따라 갈린다.
3. 운영 데이터와 분석 데이터
연결 방식을 고르기 전에
데이터가 두 세계를 오간다는 것을 알아 둘 필요가 있다.
하나는 실제 서비스를 처리하는 운영 영역이다.
로그인, 회원가입, 결제, 상품 구매, 주문, 배송 시작 같은 일이다.
여기서는 빠른 응답, 트랜잭션 처리, 현재 상태, 정합성이 중요하다.
흔히 OLTP라고 부른다.
다른 하나는 분석 영역이다.
월간 매출, 사용자 행동 분석, 상품별 주문 통계, 추천 모델, BI 같은 일이다.
전통적으로는 둘 사이를 이렇게 이었다.
flowchart LR
n0["운영 DB"]
n1["Data Warehouse"]
n2["BI / 분석 / ML"]
n0 -- "ETL" --> n1
n1 --> n2
한 방향이었다. 운영에서 분석으로만 흘렀다.
그런데 오늘날에는 이 경계가 흐려졌다.
추천 기능을 생각해보자.
사용자가 상품을 조회하면 행동 데이터가 쌓이고,
그 데이터로 만든 추천 결과가 다시 서비스 화면에 나타난다.
flowchart LR
o["운영"] -- "행동 데이터" --> a["분석"]
a -- "추천 결과" --> o
분석 데이터가 다시 운영으로 돌아온다.
그래서 애플리케이션 아키텍처와 데이터 아키텍처를
서로 다른 문제로 떼어 놓기 어려워졌다.
4. 데이터 배포와 애플리케이션 통합은 목적이 다르다
연결 방식을 고를 때 먼저 구분해야 할 것이 있다.
무엇을 위해 잇는가다.
데이터 배포의 목적은
데이터를 다른 곳에서 쓸 수 있게 만드는 것이다.
Batch, CDC, Data Streaming, Data Product, CQRS Read Model이 여기에 속한다.
애플리케이션 통합의 목적은
애플리케이션들이 서로 협력하게 만드는 것이다.
REST API, gRPC, Message Queue, Event, Command가 여기에 속한다.
flowchart LR
subgraph DIST["데이터 배포 — 데이터를 쓸 수 있게"]
D1["Batch"]
D2["CDC"]
D3["Data Streaming"]
D4["Data Product"]
end
subgraph INTEG["애플리케이션 통합 — 서로 협력하게"]
I1["REST API"]
I2["gRPC"]
I3["Message Queue"]
I4["Event"]
end
style DIST fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style INTEG fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
여기 나온 Data Product는
여러 팀이 반복해서 쓰는 데이터를 제품처럼 정리해 내놓는 것을 말한다.
지금은 데이터 배포 방식 중 하나로만 알아 두면 되고,
13장 「데이터 프로덕트」에서 자세히 다룬다.
둘은 목적이 다르지만 실제 시스템에서는 겹치기도 한다.
이벤트는 애플리케이션을 잇는 데도, 데이터를 나르는 데도 쓰인다.
그래도 “지금 나는 데이터를 넘기려는 것인가,
아니면 일을 시키려는 것인가“를 먼저 물으면
선택이 훨씬 쉬워진다.
5. API는 언제 쓰는가
API는 가장 익숙한 방법이다.
주문 서비스가 현재 포인트 잔액을 알고 싶다고 해보자.
flowchart LR
n0["주문 서비스"] -- "GET /points/balance" --> n1["포인트 서비스"]
n1 -- "잔액 반환" --> n0
요청하고 응답을 받는다.
현재 상태를 바로 확인하거나
처리 결과가 즉시 필요할 때 적합하다.
현재 잔액, 회원 상태, 구매 가능 여부, 결제 승인 결과 같은 것이다.
여기서 정확하게 알아둘 것이 하나 있다.
API 자체가 동기 통신을 뜻하는 것은 아니다.
요청-응답 API가 동기로 쓰이는 경우가 많을 뿐이다.
영상 처리 요청을 보냈다고 해보자.
POST /videos/process
서버는 처리가 끝날 때까지 기다리지 않고
202 Accepted
를 먼저 돌려줄 수 있다. 실제 처리는 뒤에서 비동기로 한다.
그래서 기준은 API냐 아니냐가 아니라 이렇게 잡는 것이 정확하다.
- 결과가 즉시 필요하다 — 동기 API를 우선 검토
- 나중에 처리해도 된다 — 비동기 API나 메시징을 검토
6. 동기 API를 써도 강한 일관성은 보장되지 않는다
또 하나 흔한 오해가 있다.
API를 썼으니 데이터가 항상 맞아떨어질 것이라는 생각이다.
그렇지 않다.
독립된 두 서비스가 있다고 하자.
flowchart LR
n0["주문 서비스 DB"] -- "API" --> n1["포인트 서비스 DB"]
다음 상황이 일어날 수 있다.
1. 포인트 차감 성공
2. 주문 저장 시도
3. 주문 DB 저장 실패
API 호출은 성공했는데 전체 업무는 깨진 상태로 남는다.
포인트만 빠져나갔다.
따라서 여러 시스템에 걸친 정합성은 따로 설계해야 한다.
Transaction, Idempotency, Saga, Compensation,
Transactional Outbox, Lock 같은 장치가 이때 쓰인다.
동기 API는 결과를 즉시 확인하기 좋은 방법이지,
여러 시스템의 강한 일관성을 자동으로 보장하는 기술이 아니다.
일관성 자체는 11장 「이벤트를 운영한다는 것」에서 자세히 다뤘다.
7. 이벤트는 언제 쓰는가
이벤트는 어떤 일이 이미 일어났다는 사실을 표현한다.OrderCompleted, PaymentCompleted 같은 이름을 쓴다.
명령과 구분하는 것이 중요하다.
"포인트 100을 차감해라" → Command
"포인트 100이 차감됐다" → Event
이벤트를 쓰면 생산자와 소비자의 결합이 느슨해진다.
주문 완료 이벤트에 처음에는 알림과 정산만 붙어 있었다고 하자.
나중에 랭킹이 필요해져도
주문 서비스는 거의 바꾸지 않고 소비자만 추가하면 된다.
flowchart LR
n0["OrderCompleted"]
n1["알림"]
n2["정산"]
n3["랭킹 (나중에 추가)"]
n0 --> n1
n0 --> n2
n0 -.-> n3
style n3 fill:#f2fbf4,stroke:#4caf50,stroke-dasharray: 5 5,color:#1a1a1a
주문 서비스는 누가 그 이벤트를 쓰는지 몰라도 된다.
여러 시스템이 같은 변경 사실을 나눠 쓸 때 특히 유용하다.
이벤트 설계 자체는 10장 「이벤트로 연결하기」에서 다뤘다.
여기서는 API·배치와 견주어 언제 고를지만 본다.
8. 이벤트는 공짜가 아니다
장점이 큰 만큼 복잡성도 함께 온다.
이벤트 중복, 순서, 유실, 재처리, 스키마 변경,
Consumer 장애, 관측성, 최종적 일관성.
전부 새로 고민해야 할 문제다.
같은 이벤트가 두 번 올 수 있다면
Consumer는 두 번 처리해도 괜찮게 만들어야 한다.
그래서 이벤트를 많이 쓸수록 좋은 아키텍처가 된다고 생각하면 안 된다.
모든 것을 이벤트로 만들 필요도 없다.
10,000원짜리 상품 주문을 전부 비동기로 설계했다고 해보자.
그런데 사용자는 지금 당장 알고 싶다.
잔액이 충분한가?
포인트 차감이 성공했는가?
주문이 성공했는가?
이런 핵심 결과를 즉시 보여줘야 한다면
이벤트만으로 처리하는 쪽이 오히려 복잡해진다.
그래서 보통은 이렇게 나눈다.
flowchart LR
n0["주문 요청"]
n1["포인트 차감"]
n2["주문 성공"]
n3["OrderCompleted"]
n4["알림"]
n5["랭킹"]
n6["통계"]
n0 -- "동기 · 핵심 업무" --> n1
n1 --> n2
n2 -- "비동기 · 후속 업무" --> n3
n3 --> n4
n3 --> n5
n3 --> n6
핵심 업무와 후속 업무를 가르는 것.
이것이 API와 이벤트를 조합하는 가장 흔한 형태다.
9. 배치는 여전히 좋은 선택이다
모든 데이터를 실시간으로 처리할 필요는 없다.
전날의 판매자별 실적을 계산한다고 해보자.
flowchart LR
n0["운영 데이터"] -- "매일 새벽" --> n1["Batch"]
n1 --> n2["일간 통계"]
몇 시간 늦게 나와도 문제가 없다면
복잡한 실시간 시스템을 만들 이유가 없다.
배치가 맞는 일은 이런 것들이다.
일간 통계
월간 정산
장기 리포트
대량 데이터 이동
ML 학습 데이터 생성
아카이빙
여기서 중요한 원칙이 하나 나온다.
실시간으로 만들 수 있다고 해서
반드시 실시간으로 만들어야 하는 것은 아니다.
실시간성을 높이면 비용, 운영 난이도, 장애 대응, 복잡성이 함께 올라간다.
그 값을 치를 이유가 있을 때만 치르면 된다.
10. 셋을 어떻게 고르는가
아주 단순화하면 이렇게 볼 수 있다.
| 상황 | 먼저 검토할 방식 |
|---|---|
| 지금 처리 결과가 필요하다 | 동기 API |
| 현재 상태를 조회한다 | API |
| 어떤 일이 발생했음을 알린다 | Event |
| 여러 소비자가 같은 변경을 이용한다 | Event |
| 대량 데이터를 주기적으로 처리한다 | Batch |
| 여러 소비자가 반복해서 데이터를 활용한다 | Data Product |
조회 부하 자체가 문제라면
변경 모델과 조회 모델을 나누는 CQRS도 선택지다.
9장 「서비스 경계와 조회 모델」에서 다뤘다.
다만 이 표는 정답표가 아니다.
실제 결정에서는 지연시간, 정합성, 트래픽,
소비자 수, 장애 처리, 운영 비용을 함께 봐야 한다.
표는 어디서 생각을 시작할지 알려 줄 뿐이고,
어디서 멈출지는 그 시스템의 사정이 정한다.
11. 호출이 실패할 때: Circuit Breaker
방식을 골랐다고 끝이 아니다.
고른 방식에는 저마다 운영상의 비용이 따라온다.
동기 API의 경우 그중 하나가 장애 전파다.
서비스 A가 서비스 B를 부르고 있다고 하자.
B가 장애인데도 A가 계속 요청을 보내면
실패한 요청이 A 쪽에 쌓인다.
결국 B뿐 아니라 A까지 무너진다.
이를 막는 대표적인 패턴이 Circuit Breaker다.
stateDiagram-v2
state "Half-Open" as HalfOpen
Closed --> Open : 실패 증가
Open --> HalfOpen : 일정 시간 경과
HalfOpen --> Closed : 성공
HalfOpen --> Open : 실패
전기 차단기와 같다.
문제가 생겼을 때 잠시 호출을 끊어
장애가 옆 시스템으로 번지는 것을 줄인다.
동기 API로 잇는다는 것은
상대의 장애를 그대로 넘겨받는다는 뜻이기도 하다.
연결 방식을 고를 때 함께 봐야 할 비용이다.
12. API Gateway는 어느 경계에 필요한가
서비스가 많아지면 외부 소비자가
각 서비스를 직접 찾아 부르기 어려워진다.
그래서 외부 클라이언트 앞에 API Gateway를 둔다.
flowchart LR
n0["외부 Client"]
n1["API Gateway"]
n2["회원"]
n3["결제"]
n4["주문"]
n5["배송"]
n0 --> n1
n1 --> n2
n1 --> n3
n1 --> n4
n1 --> n5
여기서 인증, 인가, 라우팅, Rate Limit,
로깅, TLS 처리, 공통 보안 정책을 한곳에서 처리할 수 있다.
하지만 내부 서비스끼리의 통신까지
전부 Gateway를 거쳐야 하는 것은 아니다.
상황에 따라 직접 호출, Service Discovery,
Service Mesh, 메시징이 더 나을 수 있다.
그래서 질문은 이렇게 바꾸는 편이 낫다.
“API Gateway를 쓰는 것이 좋은가“가 아니라
“어떤 경계에 Gateway가 필요한가”
Circuit Breaker와 API Gateway는 서로 다른 장치지만
묻는 것은 같다.
이 연결을 어디서 끊고, 어디서 모을 것인가다.
13. 원칙에도 예외는 있다
지금까지 정리한 것은 기본값이지 법이 아니다.
아키텍처 규칙을 절대적인 법칙으로 만들면
현실 문제를 못 푸는 경우가 생긴다.
전체 처리 시간을 100ms 이하로 맞춰야 하는데
중간 계층 때문에 도저히 못 맞춘다고 하자.
그러면 특정 통신 방식에 예외를 둘 수 있다.
다만 예외에도 근거가 있어야 한다.
❌ "그냥 직접 접근하는 게 편해서"
✅ "명확한 성능 요구사항 때문에
현재 표준 구조로는 SLA를 만족할 수 없다."
예외는 허용할 수 있지만
설명할 수 있는 이유가 있어야 한다.
그리고 하나의 예외가 모든 규칙을 없애지는 않는다.
API Gateway를 거치지 않는 예외를 허용했다고 해서
API 문서화, 보안, 스키마 관리, 데이터 품질, Owner까지
함께 사라지는 것은 아니다.
기술적인 구현 방법에는 예외가 있어도
데이터와 서비스에 대한 책임은 그대로 남는다.
14. 12장 정리
네 가지만 기억하면 된다.
API, 이벤트, 배치는 대체 관계가 아니다.
각각 푸는 문제가 다르다.
질문은 “무엇이 더 좋은가“가 아니라
“지금 문제에 무엇이 맞는가“다.
동기 API를 쓴다고 강한 일관성이 보장되지 않는다.
여러 시스템에 걸친 정합성은 따로 설계해야 한다.
실시간으로 만들 수 있다고 반드시 실시간일 필요는 없다.
실시간성을 높이면 비용과 운영 난이도도 함께 올라간다.
아키텍처 원칙에 예외는 있을 수 있다.
다만 “직접 접근하는 게 편해서“는 근거가 되지 않는다.
명확한 성능 요구처럼 설명할 수 있는 이유가 있어야 한다.
여기까지가 3부다.
경계를 넘는 방법은 정했다.
하지만 넘겨받은 데이터를 다른 팀이 실제로 쓰려면
그것만으로는 부족하다.
어디에 있는지, 무슨 뜻인지,
믿을 수 있는지, 누가 책임지는지를 알 수 있어야 한다.
4부에서는 데이터를 제품처럼 제공하는 방법을,
5부에서는 그 데이터를 믿을 수 있게 만드는 장치를 다룬다.
다음 장에서는 여러 팀이 반복해서 쓰는 데이터를
어떻게 제품처럼 제공할지 본다.
13장. 데이터 프로덕트
4부 · 제품 — 데이터를 어떻게 쓸 수 있게 하는가
13장 · 14장
데이터를 ‘저장’하는 데서 ‘제품처럼 제공’하는 단계로
데이터를 많이 가지고 있다고 해서
그 조직이 데이터를 잘 활용하는 것은 아니다.
중요한 것은 필요한 사람이 데이터를 쉽게 찾고,
그 의미를 이해하고, 신뢰하면서 사용할 수 있는가이다.
예를 들어 회사에 다음과 같은 테이블이 있다고 해보자.
order
point_usage
point_type
member
seller
product
payout_rate
주문 데이터를 분석하려는 사람에게
이 테이블들을 그대로 열어주면서 이렇게 말할 수도 있다.
필요한 테이블을 JOIN해서 사용하세요.
하지만 분석하는 사람은 곧 여러 질문에 부딪힌다.
어떤 주문 상태를 포함해야 하는가?
취소된 주문은 제외하는가?
테스트 계정은 어떻게 구분하는가?
point_amount의 단위는 무엇인가?
출금 환산율은 현재 값을 사용하는가,
주문 당시 값을 사용하는가?
어느 테이블이 가장 신뢰할 수 있는 원본인가?
데이터는 존재하지만
실제로 사용하기는 쉽지 않은 상태다.
데이터 프로덕트(Data Product) 는
이 문제를 해결하기 위한 사고방식이다.
1. 데이터 프로덕트란 무엇인가
데이터 프로덕트를 가장 쉽게 설명하면 다음과 같다.
다른 사람이 반복적으로 신뢰하여 사용할 수 있도록
데이터와 그 데이터에 필요한 설명·품질·접근 방법 등을
하나의 제품처럼 관리하는 것
여기서 중요한 점은
데이터 프로덕트가 단순한 DB 테이블이나 파일 하나를 의미하지 않는다는 것이다.
보통 다음과 같은 요소가 함께 관리된다.
데이터
+ 데이터의 의미
+ 스키마
+ 메타데이터
+ 품질 정보
+ 소유자
+ 갱신 주기
+ 접근 방법
+ 보안 정책
+ 버전 및 변경 정보
예를 들어 다음과 같은 데이터 프로덕트를 생각할 수 있다.
이름
Seller Daily Sales
설명
판매자별 일일 판매 실적을 제공한다.
주요 데이터
seller_id
date
total_amount
buyer_count
갱신 주기
5분
소유 도메인
주문 도메인
품질 목표
최근 10분 이내 데이터 유지
제공 방법
SQL / API / File
이 정도 정보가 갖춰지면
다른 팀은 주문 시스템의 내부 구현을 전부 공부하지 않아도 데이터를 사용할 수 있다.
2. 데이터 프로덕트의 정의는 하나로 고정되어 있지 않다
데이터 프로덕트라는 용어는
조직과 방법론에 따라 범위가 조금씩 다르다.
어떤 조직은 다음 정도로 본다.
데이터셋
+
메타데이터
+
품질 기준
+
접근 방법
반면 Data Mesh처럼 비교적 넓은 관점에서는
데이터
+
메타데이터
+
변환 코드
+
정책
+
인터페이스
+
필요한 인프라 구성
까지 하나의 독립적인 데이터 제품으로 볼 수 있다.
따라서 중요한 것은
우리 조직에서 무엇을 데이터 프로덕트라고 부를 것인지
먼저 정의하는 것
이다.
이 장에서는 데이터뿐 아니라
그 데이터를 이해하고 안정적으로 소비하는 데 필요한 요소까지 포함하는
비교적 넓은 관점으로 설명한다.
3. Data Product와 Data Mesh는 같은 것이 아니다
둘은 자주 함께 등장하지만 동일한 개념은 아니다.
Data Product는
데이터를 제품처럼 관리하는 개념이다.
반면 Data Mesh는
대규모 조직에서 데이터를 분산하여 소유하고 운영하는 하나의 아키텍처·조직 운영 방식이다.
Data Mesh가 중요하게 보는 네 가지 원칙은 3장에서 다뤘다.
즉 관계를 단순화하면 다음과 같다.
flowchart LR
dm["Data Mesh"] -- "핵심 구성 개념으로 사용" --> dp["Data Product"]
따라서 데이터 프로덕트를 만들기 위해
반드시 Data Mesh를 도입해야 하는 것은 아니다.
작은 조직에서도 데이터 프로덕트 개념만 따로 사용할 수 있다.
4. 왜 데이터 프로덕트가 필요한가
전통적인 데이터 조직에서는
중앙 데이터팀이 많은 요청을 처리한다.
flowchart LR
subgraph TEAMS["비즈니스 조직"]
P["기획팀"]
M["마케팅팀"]
F["재무팀"]
O["운영팀"]
end
DATA["중앙 데이터팀<br/>SQL 작성 · 데이터 가공"]
RESULT["결과 전달"]
P --> DATA
M --> DATA
F --> DATA
O --> DATA
DATA --> RESULT
style TEAMS fill:#fafafa,stroke:#bbb,color:#1a1a1a
style DATA fill:#fff0f0,stroke:#d9534f,stroke-width:3px,color:#1a1a1a
조직이 작다면 충분히 동작할 수 있다.
하지만 조직과 데이터가 커질수록
중앙 데이터팀이 모든 도메인의 비즈니스 규칙을 이해하기 어려워진다.
요청도 계속 증가한다.
그러면 데이터팀 자체가 병목이 될 수 있다.
데이터 프로덕트 관점에서는 생각을 바꾼다.
flowchart LR
d["주문 도메인"] --> dp["주문 데이터 프로덕트"]
dp --> a["분석"]
dp --> b["정산"]
dp --> c["랭킹"]
dp --> e["운영"]
데이터를 만드는 도메인이
다른 사람이 사용할 수 있는 형태로 제공하는 것이다.
5. 데이터를 제품처럼 생각한다
API를 제품처럼 제공한다고 생각해보자.
코드만 작성했다고 끝나지 않는다.
API
+
문서
+
사용 방법
+
버전
+
보안
+
모니터링
+
장애 대응
등이 필요하다.
데이터도 마찬가지다.
다음과 같은 방식은 좋은 데이터 프로덕트라고 보기 어렵다.
테이블 열어놨습니다.
필요하면 알아서 사용하세요.
이 경우 소비자가 직접 알아내야 하는 것이 너무 많다.
어떤 테이블을 써야 하는가?
컬럼의 의미는 무엇인가?
어떤 JOIN이 필요한가?
어떤 데이터를 제외해야 하는가?
언제 갱신되는가?
누가 관리하는가?
숫자가 틀리면 누구에게 문의해야 하는가?
좋은 데이터 프로덕트는
이 지식을 데이터와 함께 제공한다.
6. 메타데이터
데이터 프로덕트에서 매우 중요한 것이
메타데이터(Metadata) 다.
메타데이터란
데이터를 설명하는 데이터
다.
다음 값이 있다고 해보자.
point_amount = 1000
이 숫자만으로는 의미를 알기 어렵다.
충전한 포인트인가?
사용한 포인트인가?
주문한 포인트인가?
남은 포인트인가?
출금 대상 포인트인가?
따라서 다음과 같은 설명이 필요하다.
point_amount
의미
주문이 완료된 포인트 수량
단위
개
NULL
허용하지 않음
취소 데이터
포함하지 않음
이런 정보가 메타데이터다.
7. 논리적인 제품과 물리적인 구현은 다르다
데이터 프로덕트를 특정 DB 하나라고 생각하면 안 된다.
논리적으로는 Order Data Product 하나지만
실제 구현은 여러 형태일 수 있다.
flowchart LR
DP["Order Data Product<br/>논리적 정의"]
DP --> n1["MariaDB"]
DP --> n2["Data Warehouse"]
DP --> n3["S3 Parquet"]
DP --> n4["Kafka Topic"]
DP --> n5["API"]
style DP fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
소비자는 이 저장 기술들을 알 필요가 없다.
소비자에게 중요한 것은 이것뿐이다.
어떤 주문 데이터를
어떤 품질로
어떤 방식으로 쓸 수 있는가
메타데이터는 논리 쪽에 붙인다
이 구분은 메타데이터를 관리할 때 특히 중요해진다.
같은 데이터가 MariaDB, 웨어하우스, S3에 복제되어 있다고 하자.
복제본마다 의미와 Owner와 품질 기준을 따로 적어 두면
하나를 고칠 때 세 곳을 모두 고쳐야 한다.
그래서 메타데이터는 논리적 정의에 한 번만 붙인다.
flowchart LR
META["Metadata<br/>의미 · Owner · 품질 기준"]
DP2["Order Data Product<br/>논리적 정의"]
subgraph PHYS["물리적 저장 위치"]
DB[("MariaDB")]
S3[("S3")]
WH[("Data Warehouse")]
end
META -- "한 번만 정의한다" --> DP2
DP2 --> DB
DP2 --> S3
DP2 --> WH
style DP2 fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style PHYS fill:#fafafa,stroke:#bbb,color:#1a1a1a
정리하면 이렇게 나눌 수 있다.
| 무엇인가 | |
|---|---|
| 논리적 데이터 프로덕트 | 무엇을 제공하는가 |
| 물리적 구현 | 그것을 어떻게 저장하고 제공하는가 |
8. CQRS는 데이터 프로덕트의 필수 조건이 아니다
데이터 프로덕트를 설명할 때
CQRS가 자주 등장한다.
CQRS는
Command Query Responsibility Segregation
의 약자로,
데이터를 변경하는 모델과
데이터를 조회하는 모델의 책임을 분리하는 것
을 의미한다.
하지만 중요한 점이 있다.
모든 데이터 프로덕트에 CQRS가 필요한 것은 아니다.
운영 시스템의 쓰기 구조와
데이터 소비자의 조회 구조가 크게 다를 때
CQRS의 사고방식이 유용한 것이다.
CQRS 자체는 9장 「서비스 경계와 조회 모델」에서 다뤘다.
9. 운영 모델과 조회 모델
운영 시스템에서는 다음이 중요하다.
트랜잭션
정합성
빠른 INSERT / UPDATE
동시성 처리
예를 들어 주문 시스템에는 이런 테이블이 있을 수 있다.
order
point_usage
point_balance
order_item
하지만 분석 소비자가 원하는 것은 다를 수 있다.
판매자별 일일 주문 금액
회원별 월간 주문 금액
시간대별 주문 통계
그래서 별도의 조회 모델을 만들 수 있다.
seller_daily_sales
seller_id
date
total_amount
buyer_count
구조는 다음과 같다.
flowchart LR
n0["운영 시스템"]
n1["원천 데이터"]
n2["가공"]
n3["읽기 모델"]
n4["데이터 소비자"]
n0 -- "쓰기 모델" --> n1
n1 --> n2
n2 --> n3
n3 --> n4
이렇게 하면 소비자는
운영 DB의 복잡한 구조를 알 필요가 없다.
10. 읽기에 최적화한다
데이터 프로덕트는 소비 목적에 따라
읽기 편한 형태로 구성할 수 있다.
운영 DB에서는 정규화가 유리할 수 있다.
orders
order_items
products
customers
stores
하지만 분석할 때 매번 이 테이블을 JOIN해야 한다면 불편하다.
그래서 다음처럼 가공할 수 있다.
sales_analysis
date
customer_id
product_name
store_name
quantity
amount
즉 비정규화 자체가 나쁜 것이 아니다.
중요한 것은
- 운영 시스템 — 쓰기와 정합성 중심
- 데이터 프로덕트 — 소비와 조회 중심
처럼 목적에 맞게 설계하는 것이다.
11. 스타 스키마
조회 중심으로 설계한다고 했는데,
그럼 구체적으로 어떤 모양인가.
분석용 데이터 프로덕트에서 가장 많이 쓰이는 모양이
Star Schema다.
왜 이런 모양이 나왔나
분석에서 나오는 질문은 끝이 없다.
이번 달 주문 금액은 얼마인가?
판매자별로는?
상품 카테고리별로는?
판매자별 × 월별로는?
질문이 나올 때마다 테이블을 새로 만들 수는 없다.
그래서 질문을 두 조각으로 쪼갠다.
- 무엇을 재는가 — 주문 금액, 주문 수량
- 어떤 기준으로 나눠 보는가 — 판매자별, 월별, 상품별
재는 값은 가운데 테이블 하나에 모으고,
나눠 보는 기준은 각각 별도 테이블로 뺀다.
앞엣것을 Fact, 뒤엣것을 Dimension이라고 부른다.
구조
flowchart TD
DU["dim_user<br/>──────────<br/>user_id<br/>가입일 · 등급"]
DS["dim_seller<br/>──────────<br/>seller_id<br/>판매자명 · 등급"]
DP["dim_product<br/>──────────<br/>product_id<br/>상품명 · 카테고리"]
DD["dim_date<br/>──────────<br/>date_id<br/>날짜 · 월 · 분기"]
F["fact_order<br/>──────────<br/>user_id · seller_id · product_id · date_id<br/><br/>주문 수량 · 주문 금액"]
DU --> F
DS --> F
DP --> F
DD --> F
style F fill:#e8f4ff,stroke:#4a90e2,stroke-width:3px,color:#1a1a1a
style DU fill:#fafafa,stroke:#bbb,color:#1a1a1a
style DS fill:#fafafa,stroke:#bbb,color:#1a1a1a
style DP fill:#fafafa,stroke:#bbb,color:#1a1a1a
style DD fill:#fafafa,stroke:#bbb,color:#1a1a1a
fact_order에는 숫자와 연결 키만 들어간다.
행 하나가 주문 하나다. 수천만 건이 쌓인다.
dim_*에는 그 키가 무엇인지 설명하는 값이 들어간다.
판매자 수만큼, 상품 수만큼만 있으므로 훨씬 작다.
예를 들어 fact_order에는 seller_id = 37만 있고,
그 판매자의 이름과 등급과 가입일은 dim_seller에 있다.
가운데 Fact 하나를 Dimension들이 둘러싸는 모양이라
별(Star) 스키마라고 부른다.
그래서 무엇이 좋아지나
질문이 바뀌어도 테이블 구조는 그대로다.
어떤 Dimension을 붙이느냐만 달라진다.
-- 판매자별 × 월별 주문 금액
SELECT s.seller_name, d.month, SUM(f.order_amount)
FROM fact_order f
JOIN dim_seller s ON f.seller_id = s.seller_id
JOIN dim_date d ON f.date_id = d.date_id
GROUP BY s.seller_name, d.month;
상품 카테고리별로 보고 싶으면dim_seller를 dim_product로 바꾸기만 하면 된다.
새로운 분석 기준이 필요하면
Dimension 테이블을 하나 더 붙인다.fact_order는 건드리지 않는다.
판매자 이름이 바뀌어도 dim_seller 한 행만 고치면 된다.
앞 절에서 본 넓은 테이블이었다면
수천만 행을 전부 고쳐야 했을 것이다.
언제 쓰나
집계와 조합이 많은 환경에서 유용하다.
월별·상품별·판매자별처럼 기준이 계속 바뀌는 분석이 대표적이다.
다만 모든 데이터 프로덕트가 이 모양일 필요는 없다.
기준 조합이 거의 고정되어 있고 조회가 단순하다면
앞 절처럼 넓은 테이블 하나로 충분할 때도 많다.
12. Data Vault
스타 스키마에도 약점이 있다.
원천 시스템이 바뀌면 흔들린다는 점이다.
주문에 새 속성이 생기거나, 판매자 등급 체계가 바뀌거나,
시스템 하나가 통째로 교체되면
Fact와 Dimension을 다시 설계해야 하는 일이 생긴다.
“작년 3월 시점에 이 판매자의 등급은 무엇이었나“처럼
과거 시점을 되짚는 질문에도 약하다.
이런 문제를 다루려고 나온 모델링 방법이 Data Vault다.
세 가지로 나누는 이유
핵심 발상은 하나다.
변하는 것과 변하지 않는 것을 섞지 않는다.
그래서 테이블을 세 종류로 나눈다.
| 요소 | 담는 것 | 성질 |
|---|---|---|
| Hub | 비즈니스 키 (user_id, order_id) | 거의 변하지 않는다 |
| Link | 객체 사이의 관계 (회원 ↔ 주문) | 관계가 늘어난다 |
| Satellite | 속성과 그 변경 이력 (주소, 등급, 금액) | 계속 변한다 |
flowchart LR
HU["hub_user<br/>──────────<br/>user_id<br/>변하지 않는 키"]
HO["hub_order<br/>──────────<br/>order_id<br/>변하지 않는 키"]
LNK["link_user_order<br/>──────────<br/>user_id · order_id<br/>관계"]
SU["sat_user<br/>──────────<br/>주소 · 등급<br/>+ 변경 시각<br/>변하는 것"]
SO["sat_order<br/>──────────<br/>금액 · 상태<br/>+ 변경 시각<br/>변하는 것"]
HU --> LNK
HO --> LNK
HU --> SU
HO --> SO
style HU fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style HO fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style LNK fill:#fafafa,stroke:#bbb,color:#1a1a1a
style SU fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
style SO fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
무엇이 좋아지나
바뀔 때 고치지 않고 붙인다.
주문에 새 속성이 생기면 Satellite를 하나 더 만든다.
기존 Hub와 Link와 Satellite는 그대로 둔다.
새로운 원천 시스템이 들어와도
같은 Hub에 Satellite를 하나 더 붙이면 된다.
그리고 Satellite에는 값과 함께 변경 시각이 쌓인다.
덮어쓰지 않으므로 과거 어느 시점의 상태든 되짚을 수 있다.
감사 추적이 필요한 영역에서 특히 쓸모가 있다.
스타 스키마와 무엇이 다른가
둘 중 하나를 고르는 문제가 아니다.
푸는 문제가 다르고, 실제로는 함께 쓰는 경우가 많다.
| Data Vault | Star Schema | |
|---|---|---|
| 목적 | 원천 데이터를 통합하고 이력을 남긴다 | 분석 질문에 빠르게 답한다 |
| 최적화 대상 | 적재와 변경 수용 | 조회와 집계 |
| 읽기 편한가 | 어렵다. 조인이 많다 | 쉽다 |
| 놓이는 위치 | 안쪽 통합 계층 | 바깥쪽 소비 계층 |
flowchart LR
SRC["원천 시스템"]
DV["Data Vault<br/>──────────<br/>통합 · 이력 보존"]
STAR["Star Schema<br/>──────────<br/>분석 · 집계"]
USER["분석가 · BI"]
SRC --> DV --> STAR --> USER
style DV fill:#e8f4ff,stroke:#4a90e2,color:#1a1a1a
style STAR fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
안쪽에 Data Vault로 원본과 이력을 쌓아 두고,
바깥쪽에 Star Schema로 분석용 모델을 만들어 내놓는 식이다.
지금 당장 필요한가
대부분은 아니다.
Data Vault는 원천 시스템이 여럿이고, 자주 바뀌고,
이력과 감사 추적이 중요할 때 값을 한다.
그렇지 않다면 관리할 테이블만 몇 배로 늘어난다.
지금은 변하는 것과 변하지 않는 것을 섞지 않는다는
발상만 기억해 두면 충분하다.
이 생각 자체는 Data Vault를 쓰지 않아도 쓸모가 있다.
13. 유비쿼터스 언어는 ‘전사 공통 언어’와 조금 다르다
5장에서 본 유비쿼터스 언어를
데이터 관점에서 다시 보자.
흔한 오해는 이것이다.
회사 전체에서
모든 단어의 의미를 하나로 통일한다.
서로 다른 Bounded Context라면
같은 단어가 서로 다른 의미를 가질 수도 있다.
커머스 Context의 회원
배송 Context의 회원
정산 Context의 회원
이 반드시 동일한 모델일 필요는 없다.
데이터 프로덕트를 만들 때 중요한 것은 다음이다.
- Context 내부 — 언어와 의미를 일관되게 유지
- Context 사이 — 데이터 계약과 매핑을 명확하게 정의
14. 의미적 일관성
같은 데이터 프로덕트나 같은 Context 안에서
같은 이름은 같은 의미를 가져야 한다.
다음과 같은 컬럼은 좋지 않을 수 있다.
amount
왜냐하면 이것이 무엇을 의미하는지 불분명하기 때문이다.
결제 금액인가?
주문 포인트 수인가?
출금 금액인가?
수수료인가?
차라리 다음처럼 의미를 명확히 드러내는 편이 좋다.
payment_amount
point_amount
payout_amount
fee_amount
15. NULL, 기본값, 데이터 타입
데이터 값이 없는 경우에도
그 의미를 명확하게 정의해야 한다.
예를 들어:
birthday = NULL
이 값이 의미하는 것이 무엇인가?
사용자가 입력하지 않음
정보를 알 수 없음
수집 실패
해당 없음
여러 해석이 가능하다.
따라서 데이터 계약에서 의미를 정해야 한다.
데이터 타입도 마찬가지다.
회원 시스템
user_id BIGINT
결제 시스템
user_id VARCHAR
분석 시스템
user_id INT
처럼 제각각이면 계속 변환이 필요해진다.
가능한 범위에서 공통 타입 규칙을 갖는 것이 좋다.
16. 속성의 원자성
하나의 필드에는
가능하면 하나의 의미를 담는다.
좋지 않은 예:
user_info =
"홍길동/010-1234-5678/부산"
더 나은 형태:
user_name
phone_number
address
원자성을 유지하면
검색
필터링
JOIN
검증
마스킹
이 훨씬 쉬워진다.
17. 원천 데이터를 무조건 직접 읽어야 하는 것은 아니다
데이터 계보를 단순하게 유지하려면
권위 있는 원천 데이터를 사용하는 것이 좋다.
하지만
모든 데이터 프로덕트가 반드시 운영 원천 DB를 직접 읽어야 한다
는 뜻은 아니다.
다음 구조도 충분히 가능하다.
flowchart LR
n0["운영 시스템"] --> n1["Source-aligned Data Product"] --> n2["Consumer-oriented Data Product"]
예를 들어 주문 도메인이
신뢰할 수 있는 Order Data Product를 제공한다면,
정산 데이터 프로덕트가 운영 DB를 다시 직접 읽지 않고
이 데이터 프로덕트를 입력으로 사용할 수도 있다.
중요한 원칙은 다음과 같다.
불필요한 중간 의존성을 만들지 말고,
권위 있는 원천 또는 신뢰할 수 있는 상위 데이터 프로덕트를 사용한다.
18. Data Lineage
데이터가 어디에서 왔고
어떤 과정을 거쳤는지 추적하는 것을
Data Lineage라고 한다.
예:
flowchart LR
n0["order"] --> n1["취소 주문 제외"] --> n2["테스트 계정 제외"] --> n3["판매자별 집계"] --> n4["seller_daily_sales"]
최종 숫자가 이상할 경우
원천 데이터 문제인가?
수집 과정에서 누락됐는가?
필터 조건이 잘못됐는가?
집계 로직이 잘못됐는가?
를 역으로 추적할 수 있다.
19. 13장 정리
세 가지만 기억하면 된다.
데이터 프로덕트는 테이블이나 파일 하나가 아니다.
데이터에 의미·스키마·품질 기준·소유자·갱신 주기·접근 방법이
함께 붙어 있어야 한다.
논리적인 제품과 물리적인 구현을 분리한다.
하나의 데이터 프로덕트가
DB, 웨어하우스, 객체 스토리지, 스트림, API로
동시에 제공될 수 있다.
소비자는 그 전부를 알 필요가 없다.
소비 목적에 맞는 읽기 모델을 따로 두면 도움이 된다.
운영 시스템은 쓰기와 정합성이 중심이고
데이터 프로덕트는 조회가 중심이기 때문이다.
다음 장에서는 이렇게 만든 데이터 프로덕트를
어떻게 믿을 수 있게 만드는지 본다.
14장. 데이터 프로덕트를 신뢰할 수 있게 만들기
4부 · 제품 — 데이터를 어떻게 쓸 수 있게 하는가
13장 · 14장
분석팀에 데이터를 열어 줬다.
돌아온 첫 질문은 기능에 대한 것이 아니었다.
“이 숫자 믿어도 되나요?”
13장에서 데이터 프로덕트가 무엇인지 봤다.
만드는 것과 믿게 만드는 것은 다른 문제다.
이 장에서는 신뢰를 만드는 요소를 다룬다.
품질과 테스트, 이력 관리, 수집과 제공 방식,
보안, 그리고 이것들을 떠받치는 플랫폼이다.
1. 데이터 품질
데이터 프로덕트는
데이터가 존재하는 것만 책임지는 것이 아니다.
신뢰할 수 있는 상태인지도 관리해야 한다.
대표적인 품질 기준은 다음과 같다.
| 품질 항목 | 의미 |
|---|---|
| 정확성 | 실제 사실과 맞는가 |
| 완전성 | 필요한 데이터가 빠지지 않았는가 |
| 유일성 | 중복이 없는가 |
| 일관성 | 관련 데이터와 의미가 맞는가 |
| 최신성 | 약속한 시간 안에 갱신되는가 |
예를 들어 주문 데이터에는 다음 규칙을 적용할 수 있다.
order_id 중복 금지
seller_id NULL 금지
point_amount > 0
created_at이 미래 시간이면 오류
2. 데이터에도 테스트가 필요하다
소프트웨어에는 테스트가 있다.
Unit Test
Integration Test
데이터 파이프라인도 테스트할 수 있다.
Schema Test
NULL Test
Unique Test
Range Test
Freshness Test
Reconciliation
예를 들어 다음처럼 구성한다.
flowchart LR
n0["데이터 수집"] --> n1["스키마 검사"] --> n2["NULL 검사"] --> n3["중복 검사"] --> n4["품질 검사"] --> n5["저장 / 공개"]
문제가 발생하면
배포 중단
알림
격리
재처리
같은 정책을 적용할 수 있다.
3. 데이터 대사
Reconciliation은
원천과 결과가 맞는지 비교하는 것이다.
예를 들어:
운영 DB
어제 주문 1,000,000건
그런데 데이터 프로덕트에는
999,950건
만 존재한다고 하자.
50건이 누락된 이유를 찾아야 한다.
건수뿐 아니라 금액도 비교할 수 있다.
원천 SUM(point_amount)
vs
데이터 프로덕트 SUM(point_amount)
이런 비교를 자동화하면
데이터 파이프라인의 신뢰성을 높일 수 있다.
4. 데이터의 불변성은 상황에 따라 적용한다
데이터 프로덕트에서는
과거 사실이 임의로 바뀌지 않도록 하는 것이 중요하다.
하지만
모든 데이터를 절대로 수정하면 안 된다
라고 이해하면 안 된다.
예를 들어 거래 원장, 감사 로그, 이벤트 로그처럼
과거 사실의 재현이 중요한 데이터는
Append-only
Versioning
History
방식이 적합하다.
반면 현재 상태만 중요한 데이터는
기존 값을 갱신하는 것도 가능하다.
즉,
- 감사 / 이력 중요 — 불변성 적극 활용
- 현재 상태 중요 — 갱신 가능
처럼 데이터 특성에 따라 결정한다.
5. 이력 관리 방식
대표적인 이력 관리 방식을 살펴보자.
SCD Type 1
현재값만 중요하다면
기존 값을 덮어쓴다.
기존
grade = A
변경
grade = B
과거 등급이 A였던 사실은 남지 않는다.
SCD Type 2
과거 상태까지 보관해야 한다면
새로운 행을 만든다.
| seller_id | grade | start | end |
|---|---|---|---|
| 100 | A | 2025-01-01 | 2026-05-31 |
| 100 | B | 2026-06-01 | NULL |
이렇게 하면 특정 시점의 상태를 조회할 수 있다.
SCD는 원래 Dimension 속성의 변화 이력을 관리하기 위한 기법이다.
모든 종류의 이력을 반드시 SCD로 관리하는 것은 아니다.
6. Snapshot
특정 시점의 전체 상태를 저장할 수도 있다.
2026-09-14 Snapshot
2026-09-15 Snapshot
2026-09-16 Snapshot
장점은 특정 시점 상태를 복원하기 쉽다는 것이다.
하지만 바뀌지 않은 데이터도 계속 저장하므로
저장량이 커질 수 있다.
7. Append-only
기존 데이터를 수정하지 않고
새로운 사실을 계속 추가하는 방식이다.
예를 들어:
OrderCreated
OrderCancelled
OrderRefunded
처럼 이벤트를 기록한다.
모든 변경 사실을 추적해야 하는 경우 유용하다.
8. CDC
Change Data Capture는
DB에서 발생한 변경을 감지하는 방식이다.
flowchart LR
n0["OLTP Database"] --> n1["CDC"] --> n2["Change Stream"]
INSERT, UPDATE, DELETE 등의 변경을 감지하여
다른 데이터 시스템으로 전달할 수 있다.
실시간 데이터 파이프라인에서 많이 활용된다.
9. 이력 방식에는 하나의 정답이 없다
데이터의 성격에 따라 조합한다.
| 무엇이 중요한가 | 쓰는 방식 |
|---|---|
| 현재 상태만 중요 | Type 1 |
| 과거 속성 변화 중요 | Type 2 |
| 시점 전체 상태 중요 | Snapshot |
| 모든 변경 사실 중요 | Append-only |
| 실시간 변경 전달 필요 | CDC |
하나의 시스템에서도
여러 방식을 함께 사용할 수 있다.
10. Raw Data는 필요 없다는 뜻이 아니다
좋은 데이터 프로덕트는
DB Dump 있으니 알아서 사용하세요.
라고 하지 않는다.
하지만 Raw Data 자체가 쓸모없다는 뜻은 아니다.
Raw 데이터는 다음과 같은 상황에서 매우 중요하다.
재처리
장애 복구
감사
새로운 변환 로직 적용
과거 데이터 재계산
따라서 올바른 이해는 다음과 같다.
Raw Data만 제공하면서 소비자용 데이터 프로덕트라고 해서는 안 된다.
Raw는 내부 처리 계층으로 충분히 가치가 있다.
11. 데이터 수집 방식
데이터를 가져오는 방법에도
하나의 정답은 없다.
대표적으로 다음과 같은 방식이 있다.
Batch
정해진 시간마다 가져온다.
1시간마다
매일
매주
실시간성이 높지 않은 데이터에 적합하다.
Event / Streaming
데이터가 발생할 때 전달한다.
flowchart LR
n0["주문 완료"] --> n1["OrderCompleted"] --> n2["Kafka"]
실시간 랭킹이나 모니터링 같은 기능에 적합하다.
API
외부 서비스나 SaaS에서
API를 통해 데이터를 가져올 수도 있다.
외부 서비스
↑
REST API
↑
Data Pipeline
실제 환경에서는
Batch, Event, API를 혼합하는 경우가 많다.
12. Bronze / Silver / Gold
데이터 처리 구조에서 자주 등장하는 패턴이
Medallion Architecture다.
대표적으로 다음 단계로 나눈다.
flowchart LR
n0["Bronze"] --> n1["Silver"] --> n2["Gold"]
Bronze는 원천에 가까운 데이터다.
Raw Data
Silver는 정제된 데이터다.
중복 제거
타입 정리
NULL 처리
표준화
Gold는 비즈니스 소비에 적합한 데이터다.
판매자 일별 주문 집계
월별 매출
정산 데이터
예를 들어:
flowchart LR
n0["MariaDB order"] --> n1["Bronze"] --> n2["정제"] --> n3["Silver"] --> n4["판매자별 집계"] --> n5["Gold"] --> n6["Order Data Product"]
다만 중요한 점이 있다.
Bronze/Silver/Gold는 널리 사용되는 구현 패턴 중 하나이지
데이터 프로덕트나 Data Mesh의 필수 구조는 아니다.
13. 데이터 제공 방식
소비자가 필요한 방식도 다양하다.
SQL
API
File
Event
Streaming
Dashboard
Cache
Replica
예를 들면:
| 요구사항 | 적합한 방식의 예 |
|---|---|
| 일일 통계 | Batch / File |
| BI 분석 | SQL |
| 외부 시스템 연동 | API |
| 실시간 랭킹 | Event / Streaming |
| 고빈도 조회 | Cache / Read Model |
데이터 프로덕트는
소비자의 요구에 적합한 출력 인터페이스를 제공해야 한다.
14. Input Port와 Output Port
데이터 프로덕트를 하나의 서비스처럼 생각하면
입력과 출력을 구분할 수 있다.
flowchart LR
n0["Source"] --> n1["Input Port"] --> n2["Data Product"] --> n3["Output Port"] --> n4["Consumer"]
Input Port는 데이터를 받아들이는 계약이고,
Output Port는 소비자가 데이터를 사용하는 계약이다.
이렇게 내부 구현과 외부 계약을 분리하면
데이터 저장 기술이 바뀌어도 소비자 영향을 줄이기 쉽다.
15. 데이터 보안
데이터 프로덕트에는
보안도 포함되어야 한다.
대표적인 방식으로 다음이 있다.
Row Level Security
특정 행만 조회
Column Level Security
특정 컬럼 조회 제한
Masking
민감 데이터 일부 숨김
Metadata Tag
PII, Financial 등의 태그 기반 정책
예를 들어 판매자 A에게는
seller_id = A
인 행만 보이게 할 수 있다.
분석팀에는
phone_number
email
같은 개인 식별 정보가 보이지 않도록 할 수 있다.
16. 도메인이 데이터 의미를 책임진다
데이터를 가장 잘 이해하는 것은
대개 데이터를 만드는 도메인이다.
| 데이터 | 책임 도메인 |
|---|---|
| 회원 데이터 | 회원 도메인 |
| 결제 데이터 | 결제 도메인 |
| 주문 데이터 | 주문 도메인 |
중앙 데이터팀이
모든 비즈니스 규칙을 완벽하게 이해하는 것은 현실적으로 어렵다.
따라서 도메인이
데이터 의미
품질 기준
변경 규칙
소유권
을 책임지는 방향이 도움이 된다.
17. 새로운 데이터에는 새로운 소유권이 생길 수 있다
원천 데이터를 가공하면
새로운 비즈니스 의미가 만들어질 수 있다.
예를 들어:
flowchart TD
n0["주문 데이터"]
n2["출금 정책"]
n4["수수료 정책"]
n6["정산 규칙"]
n7["판매자 예상 정산금"]
n0 --> n7
n2 --> n7
n4 --> n7
n6 --> n7
판매자 예상 정산금은
단순한 주문 데이터가 아니다.
새로운 규칙이 적용된 새로운 데이터다.
따라서
원천 데이터 소유자
≠
가공 데이터 소유자
일 수 있다.
데이터 프로덕트마다
최종 책임자를 명확하게 하는 것이 중요하다.
18. Single Source of Truth는 단순히 ‘숫자 하나’라는 뜻이 아니다
이 표현은 1장에서 다뤘다.
여기서는 데이터 프로덕트 관점에서 한 걸음 더 들어가 본다.
다음과 같은 상황이 있다고 하자.
| 팀 | 매출 |
|---|---|
| 운영팀 | 100억 |
| 재무팀 | 98억 |
| 분석팀 | 102억 |
숫자가 다르다고 해서
무조건 하나만 맞는 것은 아니다.
예를 들어 각각 다음을 의미할 수 있다.
PG 승인 금액
회계 인식 매출
환불 제외 순매출
모두 올바른 데이터일 수 있다.
따라서 중요한 것은
비즈니스 사실별로 어떤 정의를 사용하며
어떤 데이터가 그 정의의 권위 있는 출처인지 명확하게 하는 것
이다.
무조건 회사 전체에 숫자 하나만 존재하게 만드는 것이 목적은 아니다.
19. 하지만 도메인마다 마음대로 만들면 안 된다
앞의 세 절은 도메인이 데이터의 의미를 책임진다는 이야기였다.
그렇다고 분산 소유권이
각 팀이 원하는 기술을
아무 규칙 없이 선택한다.
는 뜻은 아니다.
그렇게 하면 다음 문제가 생긴다.
ID 규칙 불일치
스키마 불일치
보안 수준 불일치
중복 인프라
높은 운영비
통합 어려움
그래서 조직 전체의 최소한의 공통 규칙이 필요하다.
20. Federated Governance
앞 절의 균형 — 공통 규칙은 필요한데 중앙이 다 정할 수는 없다 —
이것을 다루는 방식이 Federated Governance다.
핵심은 하나다.
무엇을 전사가 정하고
무엇을 도메인이 정하는지를 나눈다.
| 전사가 정한다 | 도메인이 정한다 |
|---|---|
| 개인정보 분류 기준 | 어떤 데이터 프로덕트를 만들지 |
| 식별자와 이름 규칙 | 내부 데이터 모델 |
| 스키마 호환성 정책 | 컬럼의 비즈니스 의미 |
| 품질의 최소 기준 | 그 위의 품질 목표 |
| 접근 통제 방식 | 갱신 주기 |
왼쪽은 최소한이어야 한다.
목록이 길어질수록 중앙집중으로 되돌아간다.
Federated는 연방이라는 뜻이다.
주(州)가 자기 법을 갖되 연방 헌법은 함께 지키는 구조를 떠올리면 된다.
거버넌스 조직과 역할은 16장 「거버넌스」에서 자세히 다룬다.
21. Self-Service Data Platform
앞 절이 무엇을 지킬지를 정했다면
이 절은 어떻게 지키게 할지의 문제다.
규칙은 정해 놓아도 지키기 어려우면 지켜지지 않는다.
도메인마다 다음을 각자 직접 만든다고 해보자.
수집 시스템
Kafka
ETL
Scheduler
Catalog
Security
Monitoring
CI/CD
팀이 다섯이면 다섯 벌이 생긴다.
비용도 문제지만 더 큰 문제가 있다.
팀마다 보안 설정과 카탈로그 등록 방식이 달라진다.
앞 절에서 정한 규칙이 실제로는 지켜지지 않는다.
그래서 공통 플랫폼이 이 기능들을 셀프서비스로 제공한다.
flowchart LR
subgraph PLAT["Data Platform"]
P1["수집 · 저장 · 변환"]
P2["카탈로그 · 접근 통제"]
P3["품질 검사 · 배포"]
end
PLAT --> M["회원 Data Product"]
PLAT --> C["결제 Data Product"]
PLAT --> O["주문 Data Product"]
style PLAT fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
여기서 중요한 것은 플랫폼이 규칙을 대신 지켜 준다는 점이다.
플랫폼으로 데이터 프로덕트를 만들면
카탈로그 등록과 접근 통제와 품질 검사가 기본으로 딸려 온다.
애써 지키지 않아도 지켜진다.
이것을 가드레일이라고 부른다.
10장 「이벤트로 연결하기」에서 본 것과 같은 생각이다.
역할은 이렇게 갈린다.
| 묻는 것 | 책임 | |
|---|---|---|
| 플랫폼팀 | 어떻게 만들 것인가 | 도구와 기반 |
| 도메인팀 | 무슨 데이터이고 왜 필요한가 | 의미와 품질 |
플랫폼팀이 데이터의 의미까지 책임지기 시작하면
다시 중앙 데이터팀 병목으로 돌아간다.
22. 데이터를 찾을 수 있게 만든다
데이터 프로덕트가 많아지면
어떤 데이터가 있는지 찾는 것 자체가 어려워진다.
그래서 Data Catalog를 사용한다.
카탈로그에서는 보통 다음을 찾을 수 있다.
데이터 이름
설명
Owner
Schema
갱신 주기
품질 상태
보안 등급
접근 방법
Lineage
쉽게 말하면
조직 내부 데이터를 위한 검색 엔진
이라고 생각할 수 있다.
좋은 데이터 환경에서는
사용자가 데이터팀에 매번 물어볼 필요가 없다.
기존:
“판매자별 주문 데이터 어디 있나요?”
셀프서비스:
flowchart LR
n0["Data Catalog 검색"] --> n1["Seller Daily Sales 발견"] --> n2["설명 / 품질 확인"] --> n3["권한 요청"] --> n4["사용"]
이것을 Self-Service Discovery라고 부른다.
앞 절의 플랫폼이 만들기를 셀프서비스로 만든다면,
카탈로그는 찾기를 셀프서비스로 만든다.
카탈로그와 메타데이터는 15장 「메타데이터와 데이터 지도」에서 자세히 다룬다.
23. 데이터 변환도 코드처럼 관리한다
데이터 변환 로직도
애플리케이션 코드처럼 관리할 수 있다.
예:
flowchart LR
n0["SQL / dbt"] --> n1["Git"] --> n2["Test"] --> n3["CI/CD"] --> n4["Deploy"]
변경할 때 다음을 자동으로 검사할 수도 있다.
Schema Compatibility
Data Quality
Metadata
Dependency
Test
이렇게 하면 데이터 구조 변경으로
소비자 시스템이 갑자기 깨지는 위험을 줄일 수 있다.
24. 데이터 복제는 성능과 독립성을 얻는 대신 관리 비용을 만든다
모든 소비자가
원본 데이터 프로덕트를 직접 사용할 필요는 없다.
예를 들어:
flowchart LR
n0["Order Data Product"] --> n1["Consumer Replica"] --> n2["분석 시스템"]
처럼 소비자 쪽에 복제본을 둘 수도 있다.
또는:
flowchart LR
n0["Order Data Product"] --> n1["Redis"] --> n2["Ranking Service"]
처럼 캐시를 둘 수도 있다.
장점은 다음과 같다.
조회 지연 감소
원본 부하 감소
소비자 장애 격리
소비 목적에 맞는 저장 구조 사용
하지만 복제는 새로운 문제를 만든다.
원본과 동기화됐는가?
삭제가 전파됐는가?
누가 복제본을 관리하는가?
개인정보 삭제 요청도 반영됐는가?
따라서 복제는 단순한 기술 선택이 아니라
거버넌스 문제이기도 하다.
25. 데이터 프로덕트 아키텍처에는 하나의 정답이 없다
어떤 조직은 중앙 플랫폼 의존도가 높을 수 있다.
다른 조직은 도메인 자율성이 더 높을 수도 있다.
다음 두 극단을 생각할 수 있다.
완전 중앙집중
────────────────────────
표준화 쉬움
중복 적음
하지만
중앙팀 병목 가능
반대편은 다음과 같다.
완전 분산
────────────────────────
도메인 자율성 높음
빠른 변경 가능
하지만
기술 난립
중복 비용 증가
통합 어려움
현실적으로는 그 중간에서 균형을 찾는다.
26. 데이터 프로덕트 도입은 작게 시작한다
처음부터 다음을 만들려고 하면
프로젝트가 너무 커지기 쉽다.
전사 Data Mesh
전사 Data Catalog
전사 Streaming Platform
전사 Governance
보다 현실적인 방식은 작은 성공 사례를 만드는 것이다.
예를 들어:
flowchart LR
n0["주문 도메인"] --> n1["Seller Daily Sales"]
하나부터 시작한다.
여기에
Owner
Schema
Metadata
Quality
Lineage
Security
Access
Refresh Cycle
을 제대로 적용한다.
실제 소비자가 사용해보고 문제가 없는지 확인한다.
그 후 좋은 패턴을 다른 도메인으로 확장한다.
flowchart LR
n0["주문"] --> n1["결제"] --> n2["회원"] --> n3["출금"] --> n4["배송"]
이런 점진적인 확장이 훨씬 현실적이다.
27. 데이터 프로덕트 전체 흐름
이 장의 내용을 하나로 연결하면 다음과 같다.
flowchart TB
S1["문제<br/>──────────<br/>데이터가 여러 시스템에 흩어져 있고<br/>중앙 데이터팀만으로는 감당하기 어려워진다"]
S2["책임<br/>──────────<br/>데이터를 만드는 도메인이 책임을 갖는다"]
S3["제품<br/>──────────<br/>Raw Data를 그대로 던지지 않고<br/>소비 목적에 맞는 데이터 프로덕트를 만든다<br/>데이터 · 메타데이터 · 품질 · 계약을 함께 낸다"]
S4["신뢰<br/>──────────<br/>이력 · 계보 · 품질을 관리한다"]
S5["제공<br/>──────────<br/>Batch · API · Event · Streaming으로 내보내고<br/>필요하면 CQRS와 읽기 모델을 쓴다"]
S6["기반<br/>──────────<br/>공통 기술은 Self-Service Platform이 제공하고<br/>도메인 자율성과 조직 표준의 균형을 유지한다"]
S1 --> S2 --> S3 --> S4 --> S5 --> S6
style S1 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style S2 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S3 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style S4 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S5 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S6 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
28. 초보자가 특히 구분해야 하는 것
이 장을 공부하면서 다음 개념들을 서로 같은 것으로 혼동하지 않는 것이 중요하다.
Data Product
≠
Database Table
Data Product
≠
Data Mesh
Data Mesh
≠
Bronze / Silver / Gold
CQRS
≠
Data Product의 필수 조건
Raw Data
≠
쓸모없는 데이터
Single Source of Truth
≠
회사 전체 숫자를 무조건 하나로 통일
Ubiquitous Language
≠
전사에서 모든 용어를 하나로 강제
이 구분만 명확하게 이해해도
13~14장의 내용 대부분을 정확하게 이해한 것이다.
29. 14장 정리
이 장에서 가장 중요한 것은
특정 제품이나 기술 이름을 외우는 것이 아니다.
Kafka, dbt, S3, Data Vault, Star Schema,
Bronze/Silver/Gold 같은 기술과 패턴은
상황에 따라 얼마든지 바뀔 수 있다.
더 중요한 것은 사고방식이다.
데이터를 DB에서 우연히 생기는 부산물이 아니라
누군가가 사용하는 하나의 제품으로 생각한다.
그리고 그 제품에 대해 다음 질문에 답할 수 있어야 한다.
이 데이터는 무엇인가?
누가 책임지는가?
어디서 왔는가?
어떻게 만들어졌는가?
얼마나 믿을 수 있는가?
언제 갱신되는가?
과거 데이터는 어떻게 관리되는가?
어떻게 사용할 수 있는가?
누가 사용할 수 있는가?
변경되면 소비자에게 어떤 영향을 주는가?
이 질문에 명확하게 답할 수 있다면
그 데이터는 단순한 테이블이나 파일을 넘어
좋은 데이터 프로덕트에 가까워진다.
13~14장의 핵심 문장
데이터 프로덕트란 명확한 소유자가 데이터의 의미와 품질을 책임지고,
소비자가 별도의 도움 없이도 쉽게 찾고 이해하고 신뢰하여 사용할 수 있도록 제공하는 데이터 제품이다.
그리고 조직 차원에서는 다음 원칙으로 정리할 수 있다.
도메인은 데이터의 의미와 품질을 책임지고,
공통 플랫폼은 데이터 프로덕트를 쉽게 만들고 운영할 수 있는 기술과 표준을 제공한다.
이 두 문장을 이해했다면
13~14장의 가장 중요한 내용을 이해한 것이다.
이 장에서 나온 용어는 부록 C 「용어집」의
「데이터 제품과 모델링」 항목에 정리해 두었다.
15장. 메타데이터와 데이터 지도
5부 · 신뢰 — 찾고, 믿고, 안전하게 쓰려면
15장 · 16장 · 17장 · 18장
데이터 카탈로그와 계보에서 데이터 민주화까지
데이터 시스템이 작을 때는
개발자 몇 명이 구조를 대부분 기억할 수 있다.
어떤 테이블에 어떤 데이터가 있고,
누가 만들었으며 어디에서 사용하는지
코드나 DB를 보면 어느 정도 파악할 수 있다.
하지만 서비스가 커지면 상황이 달라진다.
회원 DB
결제 DB
배송 DB
Kafka
Redis
S3
Data Warehouse
BI
ML
외부 API
수많은 시스템에 데이터가 흩어지기 시작한다.
그러면 단순히 데이터를 저장하는 것만으로는
데이터를 제대로 관리하기 어려워진다.
사람들은 이런 질문을 하기 시작한다.
이 데이터는 무슨 뜻이지?
누가 관리하지?
어디에서 만들어졌지?
어디에서 사용하고 있지?
지금 믿고 사용해도 되는 데이터인가?
이 컬럼을 변경하면
어떤 시스템까지 영향을 받을까?
이런 질문에 답하기 위해 필요한 것이
메타데이터(Metadata) 다.
이번 장에서는 메타데이터가 무엇인지부터 시작해
flowchart LR
a["메타데이터"] --> b["메타모델"] --> c["데이터 모델"] --> d["데이터 계보"] --> e["데이터 품질"] --> f["데이터 카탈로그"] --> g["데이터 민주화"]
가 어떻게 연결되는지 알아본다.
1. 메타데이터란 무엇인가?
메타데이터를 가장 쉽게 표현하면
데이터를 설명하는 데이터
다.
예를 들어 다음 값이 있다고 하자.
amount = 10000
이것만 봐서는 10000이 무엇을 의미하는지 알기 어렵다.
하지만 다음 정보가 함께 있다면 이해할 수 있다.
테이블
order
컬럼
amount
의미
주문에 사용된 금액
데이터 타입
BIGINT
소유자
주문 서비스팀
생성 시스템
주문 서비스
사용 시스템
정산 / 통계 / 랭킹
이런 정보가 바로 메타데이터다.
즉,
실제 데이터
= 10000
메타데이터
= 이 10000이 무엇을 의미하는지 설명하는 정보
라고 이해하면 된다.
2. 메타데이터가 왜 필요한가?
데이터가 많아질수록
데이터 자체보다 데이터를 이해하기 위한 정보가 중요해진다.
예를 들어 다음과 같은 컬럼이 있다고 하자.
status
이름만 보면 정확한 의미를 알 수 없다.
회원 상태인가?
결제 상태인가?
주문 상태인가?
정산 상태인가?
또 값이 2라고 하더라도
2 = 완료?
2 = 취소?
2 = 정지?
인지 알 수 없다.
그래서 데이터와 함께
의미
정의
소유자
출처
품질
사용처
변경 이력
등을 관리해야 한다.
메타데이터는 결국
회사 데이터 전체를 이해하기 위한 지도
역할을 한다.
3. 비즈니스 메타데이터
메타데이터를 분류하는 방법에 절대적인 표준은 없다.
조직이나 제품에 따라 조금씩 다르게 나눈다.
다만 실무에서는 다음 다섯 영역으로 나누어 보면 이해하기 쉽다.
| 영역 | 답하는 질문 |
|---|---|
| 비즈니스 | 업무적으로 무엇을 뜻하는가 |
| 기술 | 기술적으로 어떻게 생겼는가 |
| 운영 | 지금 정상으로 만들어지고 있는가 |
| 사용·협업 | 사람들이 어떻게 쓰고 있는가 |
| 품질 | 믿고 써도 되는가 |
하나씩 보자.
비즈니스 메타데이터는
데이터가 업무적으로 무엇을 의미하는지
설명한다.
예를 들어
활성 사용자란 무엇인가?
주문 금액은 어떤 금액인가?
결제 완료는 언제 완료로 보는가?
환불 금액에 수수료가 포함되는가?
같은 질문에 답한다.
예를 들어
용어
활성 사용자
정의
최근 30일 안에
1회 이상 로그인한 회원
처럼 정의할 수 있다.
대표적으로 다음 정보가 포함될 수 있다.
비즈니스 용어
용어 정의
업무 규칙
데이터 소유자
사용 목적
관련 도메인
핵심은
사람들이 같은 용어를
같은 의미로 사용하도록 만드는 것이다.
4. 기술 메타데이터
기술 메타데이터는
데이터가 기술적으로 어떻게 구성되어 있는지
설명한다.
예를 들어
DB
스키마
테이블
컬럼
데이터 타입
PK
FK
파일 포맷
암호화 여부
등이다.
table
payment
column
amount
type
BIGINT
nullable
false
같은 정보가 대표적인 기술 메타데이터다.
개발자와 데이터 엔지니어가
데이터 구조를 이해할 때 많이 사용한다.
5. 운영 메타데이터
운영 메타데이터는
데이터가 실제 시스템에서 어떻게 처리되고 있는지
설명한다.
예를 들어
최근 배치 실행 시간
배치 성공 여부
처리 건수
데이터 갱신 시간
파이프라인 실행 시간
오류 여부
등이다.
정산 배치
실행 시각
03:00
최근 결과
성공
처리 건수
1,200,000건
같은 정보다.
운영 메타데이터를 보면
데이터가 지금 정상적으로 만들어지고 있는가?
를 판단할 수 있다.
6. 사용·협업 메타데이터
데이터를 사람들이 어떻게 이용하는지도
중요한 메타데이터가 될 수 있다.
예를 들어
조회 수
즐겨찾기
댓글
리뷰
평점
태그
사용 설명
등이다.
어떤 데이터에 다음 설명이 붙어 있다고 하자.
이 데이터는 실시간 데이터가 아닙니다.
매일 오전 4시 이후 사용하세요.
정산팀에서 관리합니다.
이런 정보는 자동으로 생성된
DB 스키마 정보보다 실제 사용자에게
더 유용할 수도 있다.
7. 데이터 품질도 메타데이터다
데이터가 존재한다고 해서
무조건 믿고 사용할 수 있는 것은 아니다.
예를 들어 다음 데이터가 있다고 하자.
sales_summary
그런데 상태가 다음과 같다면 어떨까?
최근 갱신
3일 전
최근 배치
실패
NULL 비율
20%
데이터는 존재하지만
분석에 사용하기에는 위험하다.
따라서 다음과 같은 품질 정보도
메타데이터로 관리할 수 있다.
정확성
완전성
최신성
일관성
유효성
예를 들어
member.phone_number
NULL 비율
0.1%
형식 오류
0.03%
마지막 갱신
5분 전
처럼 관리할 수 있다.
8. 메타모델이란?
메타데이터를 단순히 모으는 것만으로는 부족하다.
중요한 것은
각 메타데이터가 어떤 관계를 가지는가
이다.
이 관계의 구조를 정의한 것이
메타모델(Metamodel) 이다.
쉽게 표현하면
메타데이터 관계의 설계도
다.
예를 들어 다음 정보가 있다고 하자.
회원 데이터
회원 도메인
회원 서비스
회원팀
회원 DB
회원 API
이 정보들이 따로 존재한다면
가치가 제한적이다.
하지만 다음처럼 연결하면 달라진다.
flowchart LR
d["회원 데이터"]
d -- "속한다" --> a["회원 도메인"]
d -- "소유된다" --> b["회원팀"]
d -- "저장된다" --> c["회원 DB"]
d -- "사용된다" --> e["회원 서비스"]
d -- "제공된다" --> f["회원 API"]
이제 데이터를 중심으로
업무와 기술의 관계를 탐색할 수 있다.
9. 메타모델은 데이터 지도를 만든다
메타모델을 잘 구성하면 다음 질문에
답할 수 있게 된다.
이 데이터는 어느 도메인에 속하는가?
누가 책임지는가?
어느 애플리케이션에서 사용하는가?
어느 DB에 저장되어 있는가?
어떤 비즈니스 용어와 연결되는가?
어떤 데이터 프로덕트의 일부인가?
그래서 메타모델은
조직 전체 데이터 생태계의 지도
라고 생각하면 이해하기 쉽다.
10. 논리적인 데이터와 물리적인 데이터를 구분하자
같은 의미의 데이터가
여러 시스템에 존재할 수 있다.
예를 들어 비즈니스 관점에서는
고객 데이터
하나지만 실제 시스템에는
MariaDB.customer
S3/customer.parquet
BigQuery.customer
customer.csv
처럼 여러 형태로 존재할 수 있다.
따라서
flowchart LR
n0["논리적인 데이터 개념"] --> n1["실제 물리적인 데이터"]
를 구분해서 관리하면 좋다.
예를 들어
flowchart LR
n0["고객 데이터셋"]
n1["MariaDB.customer"]
n2["S3/customer.parquet"]
n3["BigQuery.customer"]
n0 --> n1
n0 --> n2
n0 --> n3
처럼 표현할 수 있다.
이렇게 하면
같은 데이터가
어디에 어떤 형태로 존재하는가?
를 알 수 있다.
11. 데이터 도메인
데이터 도메인은 단순히
DB를 나누는 기준이 아니다.
특정 업무와 관련된 데이터, 규칙, 책임을 묶은 영역
이라고 이해하는 것이 좋다.
예를 들면
회원
커머스
결제
배송
주문
정산
같은 영역이다.
데이터 도메인에는 보통
데이터
업무 규칙
사람
프로세스
기술
책임
등이 함께 존재한다.
12. 데이터 프로덕트
데이터 프로덕트가 무엇인지는 13장에서 다뤘다.
메타데이터 관점에서 기억할 것은
데이터 프로덕트 자체도 관리 대상이라는 점이다.
판매자별 일별 주문 통계
라는 데이터 프로덕트가 있다면
정의
소유자
갱신 주기
품질 기준
사용 방법
관련 API
관련 데이터
접근 권한
등을 메타데이터로 함께 관리할 수 있다.
13. 데이터 모델의 세 단계
데이터 모델은 보통 다음 세 단계로 나눠 설명한다.
flowchart LR
n0["개념적 데이터 모델"] --> n1["논리적 데이터 모델"] --> n2["물리적 데이터 모델"]
쉽게 기억하면 된다.
개념 모델
= 무엇이 존재하는가?
논리 모델
= 어떤 구조와 관계인가?
물리 모델
= 실제 기술 환경에서 어떻게 구현하는가?
14. 개념적 데이터 모델
개념적 데이터 모델은
가장 높은 수준의 모델이다.
기술 구현보다
비즈니스 개념에 집중한다.
예를 들어 커머스라면
회원
상품
주문
결제
환불
정도를 표현한다.
회원
↓ 주문한다
주문
↓ 포함한다
상품
주문
↓ 결제된다
결제
이 단계에서는
BIGINT
VARCHAR
INDEX
PK
같은 구현 정보는 중요하지 않다.
개념 모델은
비즈니스 세계의 지도
라고 보면 된다.
15. 논리적 데이터 모델
논리 모델에서는
개념 모델을 좀 더 구체화한다.
주요 속성과 관계가 들어간다.
flowchart LR
M["회원<br/>──────────<br/>회원번호<br/>이름 · 가입일"]
O["주문<br/>──────────<br/>주문번호<br/>회원번호 · 주문금액"]
M -- "1 : N" --> O
style M fill:#fafafa,stroke:#bbb,color:#1a1a1a
style O fill:#fafafa,stroke:#bbb,color:#1a1a1a
이렇게
1:1
1:N
N:M
등을 표현한다.
하지만 아직 반드시
특정 DBMS의 세부 구현까지 정할 필요는 없다.
16. 물리적 데이터 모델
물리 모델에서는
실제 시스템에 데이터를 어떻게 저장할지 결정한다.
예를 들어
CREATE TABLE orders
(
order_id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL,
amount DECIMAL(12, 2) NOT NULL,
created_at DATETIME NOT NULL
);
같은 수준이다.
여기서는 실제 환경에 맞춰
데이터 타입
키
인덱스
파티셔닝
암호화
저장 방식
성능
등을 결정한다.
관계형 DB라면 PK나 FK를 사용할 수 있고,
NoSQL이나 분산 저장소라면
전혀 다른 형태의 물리 설계가 사용될 수도 있다.
17. 세 모델을 연결하면
전체 흐름을 보면 다음과 같다.
비즈니스 세계
회원
주문
결제
↓
개념 모델
회원 → 주문 → 결제
↓
논리 모델
회원번호
주문번호
결제금액
↓
물리 모델
users
orders
payments
↓
실제 DB
메타데이터 시스템에서는
이 관계가 연결되어 있으면 매우 유용하다.
예를 들어
“주문 금액“이라는 비즈니스 용어가
실제 어떤 DB의 어떤 컬럼인가?
를 추적할 수 있다.
18. 비즈니스 용어집
회사에서는 같은 용어를
서로 다르게 이해하는 경우가 많다.
예를 들어
활성 사용자
라고 했을 때
최근 7일 로그인 사용자
최근 30일 로그인 사용자
최근 결제 사용자
탈퇴하지 않은 사용자
등 여러 의미가 가능하다.
그래서 비즈니스 용어에는
가능하면 다음과 같은 정보를 함께 관리해야 한다.
용어
정의
적용 범위
도메인
소유자
관련 데이터
관련 용어
특히 같은 단어라도
도메인에 따라 의미가 달라질 수 있다.
회원팀의 고객
= 가입 회원
결제팀의 고객
= 결제 경험이 있는 사용자
영업팀의 고객
= 계약 대상 기업
따라서 용어는
용어
+
도메인
+
맥락
을 함께 관리하는 것이 중요하다.
19. 메타데이터는 가능한 부분부터 자동 수집한다
대규모 시스템에서 모든 메타데이터를
사람이 직접 작성하는 것은 현실적이지 않다.
예를 들어 회사에
테이블 10,000개
컬럼 100,000개
가 있다면 일일이 등록하기 어렵다.
따라서 기술 메타데이터는
가능하면 자동으로 가져온다.
flowchart LR
n0["MariaDB"] --> n1["Metadata Scanner"] --> n2["Data Catalog"]
스캐너를 이용해
DB
테이블
컬럼
데이터 타입
스키마
등을 자동으로 가져올 수 있다.
20. 자동 수집만으로는 부족하다
자동 스캐너는 다음 정보는 쉽게 알 수 있다.
컬럼
amount
타입
BIGINT
NULL
허용하지 않음
하지만
이 amount가 결제금액인가?
주문 금액인가?
환불 전 금액인가?
는 자동으로 정확하게 알기 어렵다.
따라서 현실적인 방식은
자동 수집
+
사람의 보완
이다.
자동화는 기술 구조를 가져오고,
사람은
비즈니스 의미
주의사항
소유자
업무 규칙
등을 보완한다.
21. 데이터 계보란?
메타데이터에서 매우 중요한 것이
데이터 계보(Data Lineage) 다.
데이터 계보는
데이터가 어디에서 만들어지고
어떤 변환을 거쳐
어디로 이동하는지를 나타내는 정보
다.
예를 들어
flowchart LR
n0["결제 DB"] --> n1["ETL"] --> n2["Data Warehouse"] --> n3["일별 매출"] --> n4["월별 매출"] --> n5["경영 Dashboard"]
가 하나의 데이터 계보다.
22. 데이터 계보가 중요한 이유
예를 들어 경영 대시보드의
매출 수치가 이상하다고 하자.
계보가 없다면
Dashboard 문제인가?
집계 테이블 문제인가?
ETL 문제인가?
원본 데이터 문제인가?
를 하나씩 조사해야 한다.
하지만 계보가 있다면
Dashboard
↑
monthly_sales
↑
daily_sales
↑
ETL
↑
payment
순서로 원인을 추적할 수 있다.
23. 변경 영향도 분석
계보는 변경 작업에도 중요하다.
예를 들어 개발자가
payment.amount
컬럼을 변경하려고 한다.
계보를 확인하면
flowchart LR
n0["payment.amount"] --> n1["매출 집계"] --> n2["정산"] --> n3["재무 Report"] --> n4["CEO Dashboard"]
까지 연결되어 있다는 것을 알 수 있다.
그러면 변경 전에
어떤 시스템이 영향을 받는가?
를 파악할 수 있다.
이를 영향도 분석(Impact Analysis) 이라고 한다.
24. 계보 자동화에도 한계가 있다
계보도 가능한 부분은 자동으로 수집할 수 있다.
예를 들어
SQL 분석
ETL 분석
Spark Job 분석
API 연동
등을 이용할 수 있다.
하지만 모든 시스템과 모든 변환을
자동으로 완벽하게 파악할 수 있는 것은 아니다.
도구마다 지원 범위가 다르기 때문이다.
따라서 중요한 계보는
자동 수집
+
수동 보완
을 함께 사용할 수 있다.
또한
테이블 수준
컬럼 수준
프로세스 수준
중 어디까지 관리할지도 정해야 한다.
깊이가 세밀해질수록
관리 비용도 증가한다.
25. 데이터 카탈로그
메타데이터를 모아 놓았다면
사용자가 쉽게 검색할 수 있어야 한다.
이를 위한 대표적인 도구가
데이터 카탈로그(Data Catalog) 다.
쉽게 말하면
회사 데이터용 검색 포털
이라고 보면 된다.
예를 들어
주문
을 검색하면
주문 데이터 프로덕트
주문 관련 테이블
관련 API
데이터 소유자
관련 Dashboard
데이터 품질
데이터 계보
등을 확인할 수 있다.
26. 데이터 카탈로그의 핵심 목적
데이터 카탈로그의 중요한 역할은
세 가지 질문에 쉽게 답하도록 만드는 것이다.
무엇인가?
어디에 있는가?
믿고 사용해도 되는가?
여기에
누가 관리하는가?
어디에서 사용하는가?
까지 알 수 있다면 더욱 좋다.
27. 데이터 민주화
이런 환경의 궁극적인 목표 중 하나가
데이터 민주화(Data Democratization) 다.
데이터 민주화는
모든 직원에게
모든 DB 권한을 준다
는 뜻이 아니다.
정확하게는
필요한 사람이
필요한 데이터를 쉽게 찾고,
의미를 이해하고,
품질을 판단하고,
적절한 권한을 받아
스스로 활용할 수 있도록 만드는 것
이다.
예를 들어 기획자가
최근 30일
판매자별 주문 데이터를 보고 싶다.
고 했을 때
매번 개발자에게 질문하는 것이 아니라
flowchart LR
n0["검색"] --> n1["데이터 발견"] --> n2["정의 확인"] --> n3["품질 확인"] --> n4["소유자 확인"] --> n5["권한 신청"] --> n6["사용"]
하는 것이 목표다.
28. 데이터 민주화와 보안은 반대 개념이 아니다
데이터 민주화를
모든 데이터를 공개하는 것
으로 이해하면 안 된다.
예를 들어
개인정보
결제정보
인사정보
재무정보
등에는 반드시 접근 통제가 필요하다.
따라서 좋은 데이터 민주화는
셀프서비스 + 적절한 거버넌스
를 함께 제공한다.
29. 데이터 계약
데이터를 제공하는 팀과 사용하는 팀 사이의 약속을
데이터 계약(Data Contract) 이라고 한다.
스키마, 갱신 주기, 가용성 목표, 변경 통보 기간 같은
내용을 정해 둔다.
데이터 계약은 16장 「거버넌스」에서 다룬다.
메타데이터 관점에서 중요한 것은
계약 내용도 카탈로그에서 확인할 수 있어야 한다는 점이다.
30. AI와 메타데이터
메타데이터가 잘 정리되어 있으면
AI를 활용하기도 쉬워진다.
예를 들어 사용자가
최근 30일 동안
판매자별 주문 금액을 볼 수 있는
데이터를 찾아줘.
라고 질문할 수 있다.
시스템에 다음 관계가 있다면
| 비즈니스 용어 | 실제 데이터 |
|---|---|
| 판매자 | 셀러 |
| 주문 | order |
| 주문 금액 | order.amount |
AI가 관련 데이터 프로덕트를
찾는 데 도움을 줄 수 있다.
또한 AI와 ML을 이용해
자동 분류
태그 추천
관련 데이터 추천
품질 이상 탐지
메타데이터 보완 후보 생성
등을 구현할 수도 있다.
31. AI가 모든 의미를 자동으로 알아내는 것은 아니다
이 부분은 중요하다.
예를 들어
cust_no
라는 컬럼을 보고 AI가
고객 식별자일 가능성이 높다.
라고 추천할 수는 있다.
하지만 항상 정확한 것은 아니다.
따라서 현실적으로는
flowchart TD
n0["컬럼명"]
n1["설명"]
n2["샘플 데이터"]
n3["계보"]
n4["관련 테이블"]
n5["비즈니스 용어"]
n6["AI"]
n7["의미 / 분류 후보 추천"]
n8["필요한 경우 사람 검증"]
n0 --> n6
n1 --> n6
n2 --> n6
n3 --> n6
n4 --> n6
n5 --> n6
n6 --> n7
n7 --> n8
형태가 안전하다.
특히 개인정보나 보안 분류처럼
중요한 영역은 사람의 검증이 필요할 수 있다.
32. 처음부터 모든 데이터를 관리하려 하지 말자
메타데이터 프로젝트에서
흔히 발생하는 실수가 있다.
모든 DB
모든 테이블
모든 컬럼
모든 API
모든 서비스
모든 비즈니스 용어
를 한 번에 관리하려는 것이다.
범위가 지나치게 커지면
구축도 어렵고 유지도 어렵다.
좋은 접근은
flowchart LR
n0["핵심 도메인 선정"] --> n1["핵심 데이터 프로덕트 선정"] --> n2["중요 테이블과 컬럼"] --> n3["소유자 / 정의 / 품질"] --> n4["계보"] --> n5["점진적인 확대"]
다.
33. 중앙 조직과 도메인의 역할
회사 전체 메타데이터를
중앙팀 하나가 직접 관리하는 것도 어렵다.
따라서 다음과 같이 역할을 나눌 수 있다.
flowchart LR
subgraph CENTRAL["중앙이 맡는 것"]
C1["공통 메타모델"]
C2["표준"]
C3["플랫폼"]
C4["정책"]
end
subgraph DOMAIN["각 도메인이 맡는 것"]
D1["실제 데이터"]
D2["정의와 품질"]
D3["소유권"]
end
style CENTRAL fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style DOMAIN fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
예를 들어 중앙에서
데이터 프로덕트란 무엇인가?
Owner는 어떻게 지정하는가?
품질을 어떻게 표현하는가?
계보를 어떤 방식으로 연결하는가?
를 정한다.
각 도메인은 이 기준에 따라
회원
커머스
배송
정산
데이터를 관리한다.
34. 데이터 오너십
메타데이터 관리에서 특히 중요한 것은
누가 책임지는 데이터인가?
를 명확하게 하는 것이다.
예를 들어
payment_transaction
Owner
커머스팀
품질 담당
커머스 데이터 담당자
처럼 관리할 수 있다.
소유자가 없다면
설명이 오래되어도 아무도 수정하지 않고
품질 문제가 발생해도 책임자가 없으며
문의할 사람도 찾기 어렵다.
좋은 메타데이터 관리에는
명확한 오너십이 필요하다.
35. 메타데이터도 낡는다
메타데이터도 데이터다.
시간이 지나면 틀릴 수 있다.
예를 들어
담당팀 변경
테이블 삭제
API 버전 변경
비즈니스 정의 변경
데이터 파이프라인 변경
등이 발생한다.
따라서 메타데이터 역시
모니터링
검증
갱신
피드백
이 필요하다.
36. 피드백 루프
예를 들어 사용자가
이 데이터 설명이 잘못됐습니다.
라고 신고했다고 하자.
좋은 시스템이라면
flowchart LR
n0["문제 발견"] --> n1["담당자 알림"] --> n2["내용 수정"] --> n3["검증"] --> n4["카탈로그 반영"]
으로 이어져야 한다.
이런 구조가 있어야
메타데이터 품질도 지속적으로 좋아진다.
37. 기술만 도입한다고 성공하지 않는다
좋은 데이터 카탈로그를 설치했다고 해서
메타데이터 관리가 자동으로 성공하는 것은 아니다.
사람들이 실제로
설명을 작성하고
소유자를 지정하고
품질을 관리하고
용어를 정리하고
잘못된 정보를 수정해야
한다.
즉 메타데이터 관리는
기술
+
프로세스
+
조직
+
사람
+
문화
가 함께 필요한 영역이다.
38. 실무 예제로 전체 흐름 이해하기
다음 데이터가 있다고 하자.
commerce.order
메타데이터가 없다면
개발자는
DB를 확인하고
소스코드를 검색하고
다른 개발자에게 물어보고
관련 문서를 찾아야
이 테이블을 이해할 수 있다.
하지만 메타데이터가 잘 관리되어 있다면
다음처럼 볼 수 있다.
데이터 프로덕트
실시간 주문 데이터
도메인
커머스
소유자
주문팀
물리 데이터
commerce.order
주요 컬럼
buyer_id
seller_id
point_amount
amount
갱신
실시간
사용 시스템
정산
랭킹
통계
관련 비즈니스 용어
주문
포인트
판매자
주문 금액
계보도 확인할 수 있다.
flowchart LR
n0["주문 서비스"] --> n1["Kafka"] --> n2["commerce.order"] --> n3["주문 집계"] --> n4["정산 / 랭킹 / Dashboard"]
품질 정보도 볼 수 있다.
최근 갱신
정상
파이프라인
정상
품질 검사
통과
그러면 새로운 개발자나 분석가도
이 데이터가 무엇이고
어디서 만들어지며
누가 책임지고
어디에서 사용하는지
빠르게 이해할 수 있다.
39. 15장 정리
이 장의 개념을 하나로 연결하면 다음과 같다.
flowchart TB
S1["메타데이터<br/>──────────<br/>이 데이터는 무엇인가"]
S2["메타모델<br/>──────────<br/>다른 데이터와 어떤 관계인가"]
S3["개념 · 논리 · 물리 모델<br/>──────────<br/>업무 개념이 실제 시스템에<br/>어떻게 구현되는가"]
S4["데이터 계보<br/>──────────<br/>어디에서 와서 어디로 가는가"]
S5["데이터 품질<br/>──────────<br/>믿고 사용해도 되는가"]
S6["데이터 카탈로그<br/>──────────<br/>어디에서 찾을 수 있는가"]
S7["데이터 민주화<br/>──────────<br/>필요한 사람이<br/>안전하게 스스로 활용한다"]
S1 --> S2 --> S3 --> S4 --> S5 --> S6 --> S7
style S1 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S2 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S3 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S4 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S5 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style S6 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style S7 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
이 흐름을 문장으로 옮기면 이렇다.
데이터가 많아질수록
데이터 자체보다 데이터를 이해하기 위한 정보가 중요해진다.
메타데이터는 이 데이터가 무엇이고, 어디에 있고,
누가 관리하고, 어디에서 만들어졌고, 어디에서 쓰이고,
믿어도 되는지를 알려준다.
메타모델은 그 정보들을 관계로 연결한다.
연결되어야 지도가 된다.
개념·논리·물리 모델은
비즈니스 개념이 실제 시스템에 어떻게 구현되는지를 보여준다.
데이터 계보는 데이터의 이동과 변환을 추적하고,
데이터 품질 정보는 그 데이터를 신뢰할 수 있는지 알려준다.
데이터 카탈로그는 사람들이 필요한 데이터를 스스로 찾게 해준다.
그리고 이 모든 것의 목적이 데이터 민주화다.
여기서 더 나아가 조직의 데이터·서비스·사람·용어를
그래프로 연결하고(지식 그래프),
분산된 데이터를 하나처럼 다루고(데이터 패브릭),
데이터 프로덕트를 상품처럼 찾아 쓰게 하는(데이터 마켓플레이스)
접근법이 있다.
부록 B 「지식 그래프와 시맨틱 웹」에서 다룬다.
무엇보다 중요한 원칙
처음부터 모든 데이터를 완벽하게 관리하려고 하지 않는 것
핵심 도메인과 중요한 데이터부터 시작해
소유자와 정의와 품질과 계보를 명확하게 만들고
점진적으로 범위를 넓힌다.
그리고 메타데이터의 가치는
설명문을 많이 쓰는 데 있지 않다.
데이터의 의미, 구조, 출처, 품질, 소유권과
다른 시스템과의 관계를 연결해
조직이 데이터를 이해하고 신뢰할 수 있게 만드는 것.
궁극적인 목표는 하나다.
조직의 구성원이 필요한 데이터를 스스로 발견하고,
의미를 이해하고, 신뢰성을 판단하며,
적절한 권한 아래 안전하게 활용할 수 있는 환경.
이것이 메타데이터를 통한 데이터 민주화다.
이 장에서 나온 용어는 부록 C 「용어집」의
「메타데이터와 거버넌스」 항목에 정리해 두었다.
그래프 관련 기술은 「메타데이터 심화」에 있다.
16장. 거버넌스
5부 · 신뢰 — 찾고, 믿고, 안전하게 쓰려면
15장 · 16장 · 17장 · 18장
데이터를 책임 있게 관리하고 안전하게 활용하는 법
회사가 작을 때는 데이터 관리가 비교적 단순하다.
어떤 데이터가 필요하면
담당 개발자에게 물어보면 된다.
"회원 가입일은 어디에 있어요?"
"member 테이블의 created_at입니다."
문제가 생겨도 누가 만든 데이터인지
대략 알고 있기 때문에 해결하기 쉽다.
하지만 회사가 성장하면 상황이 달라진다.
회원, 결제, 배송, 정산, 마케팅처럼
여러 도메인이 생기고,
각 도메인마다 데이터베이스, API, 이벤트,
데이터 파이프라인과 분석 시스템이 만들어진다.
그러면 자연스럽게 이런 질문이 생긴다.
이 데이터의 정확한 의미는 무엇이지?
어느 데이터가 기준이지?
누가 이 데이터를 책임지지?
잘못됐으면 누가 고치지?
누가 접근할 수 있지?
개인정보는 어디에 저장되어 있지?
이 데이터를 다른 목적으로 써도 되나?
이런 문제를 조직적으로 해결하기 위한 체계가
데이터 거버넌스(Data Governance) 다.
그리고 데이터의 중요도와 사용 목적에 따라
적절한 보호 조치를 적용하는 것이
데이터 보안(Data Security) 이다.
두 영역은 서로 밀접하게 연결되어 있다.
1. 데이터 거버넌스란 무엇인가
데이터 거버넌스를 어렵게 생각할 필요는 없다.
간단히 말하면,
데이터를 누가 책임지고,
어떤 의미와 규칙에 따라
관리하고 사용할지 정하는 체계다.
예를 들어 회원가입일이라는 데이터가 있다고 하자.
거버넌스가 없다면 팀마다 의미가 달라질 수 있다.
| 팀 | 회원가입일의 의미 |
|---|---|
| 회원팀 | 최초 가입 완료일 |
| 마케팅팀 | 본인인증 완료일 |
| 통계팀 | 최근 재가입일 |
모두 회원가입일이라는 이름을 쓰는데
실제 의미가 다르다.
이 상태에서 보고서를 만들면
팀마다 숫자가 다르게 나온다.
거버넌스를 적용하면 다음과 같이 정리할 수 있다.
데이터명
회원 가입일
정의
최초 회원가입 절차가 완료된 시각
소유자
회원 도메인
저장 위치
member.created_at
개인정보 여부
아님
주요 사용 목적
회원 가입 통계
즉 데이터의 의미와 책임을
공식적으로 정의하는 것이다.
2. 좋은 거버넌스는 데이터를 막지 않는다
거버넌스라고 하면 흔히
승인
통제
제한
규칙
을 떠올린다.
잘못 만든 거버넌스는 실제로
업무를 느리게 만들기도 한다.
예를 들어 데이터 하나를 보기 위해
flowchart LR
n0["신청서 작성"] --> n1["팀장 승인"] --> n2["데이터팀 승인"] --> n3["보안팀 승인"] --> n4["권한 부여"]
를 거쳐야 한다면
사용자는 거버넌스를 피하려 할 것이다.
좋은 거버넌스의 목적은 그 반대다.
믿을 수 있는 데이터를
필요한 사람이 안전하게 사용할 수 있게 만드는 것
이 핵심이다.
따라서 좋은 거버넌스는
통제
+
자율성
+
안전성
+
접근성
사이의 균형을 맞춰야 한다.
3. 회사가 커질수록 거버넌스가 필요한 이유
조직이 커지면 데이터의 양뿐 아니라
데이터를 사용하는 사람과 시스템도 늘어난다.
처음에는 한두 사람이 알고 있던 지식이
더 이상 개인의 기억만으로 관리되지 않는다.
예를 들어 활성 사용자라는 지표도
- 서비스팀 — 최근 7일 로그인 사용자
- 마케팅팀 — 최근 30일 활동 사용자
처럼 달라질 수 있다.
데이터가 잘못됐을 때도
서비스팀 문제인가?
데이터 파이프라인 문제인가?
분석팀 문제인가?
를 알기 어려워진다.
개인정보나 금융정보가 포함되기 시작하면
더 복잡해진다.
조직은 최소한 다음을 알아야 한다.
어떤 데이터를 보유하는가
어디에 저장되어 있는가
왜 사용하는가
누가 책임지는가
누가 접근하는가
얼마나 보관하는가
이런 질문에 답할 수 있게 만드는 것이
데이터 거버넌스의 중요한 역할이다.
4. 데이터 거버넌스와 데이터 보안
두 개념은 관련되어 있지만 동일하지 않다.
데이터 거버넌스는 주로 이런 질문을 한다.
이 데이터는 무엇인가?
누가 책임지는가?
어떤 목적으로 사용하는가?
어떤 품질을 유지해야 하는가?
얼마나 보관해야 하는가?
데이터 보안은 이런 질문을 한다.
누가 접근할 수 있는가?
어떤 작업까지 허용할 것인가?
암호화가 필요한가?
마스킹해야 하는가?
접근 기록을 남겨야 하는가?
쉽게 관계를 표현하면 다음과 같다.
데이터 거버넌스
→ 관리 원칙과 책임을 정의
데이터 보안
→ 정책·프로세스·기술적 통제로
데이터를 보호
데이터 보안은 단순히 기술만을 뜻하지 않는다.
접근 정책, 조직의 책임, 운영 절차, 감사 같은
관리적 활동도 함께 포함한다.
5. 가장 먼저 정해야 할 것은 책임이다
거버넌스를 시작할 때
가장 먼저 솔루션을 구매할 필요는 없다.
먼저 정해야 할 것은
누가 무엇을 책임지는가
이다.
조직마다 명칭과 책임 범위는 다르지만,
대표적으로 다음과 같은 역할을 사용한다.
| 역할 | 무엇을 책임지나 | 대표 질문 |
|---|---|---|
| 최고 데이터 책임자 (CDO) | 회사 전체의 데이터 방향 | 우리는 데이터를 어떤 원칙으로 다루는가 |
| 데이터 오너 | 특정 데이터 영역 | 이 데이터는 무엇을 뜻하는가 |
| 데이터 스튜어드 | 실무 관리 | 정의와 품질이 실제로 지켜지는가 |
| 애플리케이션 오너 | 시스템 | 이 시스템이 정상 동작하는가 |
| 데이터 사용자 · 비즈니스 사용자 | 쓰는 쪽 | 무엇이 필요한가 |
| 데이터 생성자 | 만드는 쪽 (주로 시스템) | 이 데이터는 어디서 생기는가 |
하나씩 보자.
6. 최고 데이터 책임자
CDO(Chief Data Officer)는
조직의 전체적인 데이터 전략을 책임하는 역할이다.
조직에 따라 CDO가 없을 수도 있으며
다른 임원이나 데이터 조직이 역할을 나눠 맡기도 한다.
주요 관심사는 다음과 같다.
데이터 전략
데이터 관리 원칙
데이터 표준
거버넌스 운영 방향
즉 개별 테이블을 관리하기보다
회사 전체의 데이터 방향을 결정하는 역할에 가깝다.
7. 데이터 오너
Data Owner는 특정 데이터 영역에 대한
책임을 갖는 역할이다.
예를 들어 다음처럼 나눌 수 있다.
- 회원 데이터 — 회원 도메인
- 결제 데이터 — 커머스 도메인
- 배송 데이터 — 주문 도메인
Data Owner는 보통 다음과 같은 내용을 결정하거나
그 결정에 대한 책임을 가진다.
데이터 정의
사용 목적
품질 기준
분류 기준
접근 정책
Data Owner가 반드시 개발자일 필요는 없다.
데이터의 비즈니스 의미를 잘 이해하는 사람이
오히려 적절한 경우도 많다.
8. 데이터 스튜어드
Data Steward는 쉽게 말해
데이터 관리 실무 담당자
라고 이해하면 된다.
Data Owner가
"이 데이터는 이런 기준으로 관리합니다."
라고 방향을 정한다면,
Data Steward는 실제로
정의 관리
메타데이터 관리
품질 확인
표준 준수 확인
같은 일을 수행할 수 있다.
다만 Data Steward의 정확한 업무 범위는
조직마다 상당히 다르다.
9. 애플리케이션 오너
Application Owner는
데이터가 아니라 시스템을 책임한다.
예를 들어
결제 API
회원 서비스
정산 시스템
배송 시스템
등이다.
주요 관심사는
시스템 운영
유지보수
배포
장애 대응
접근 제어 구현
등이다.
10. Data Owner와 Application Owner의 차이
두 역할은 비슷해 보이지만
관점이 다르다.
Data Owner는 이런 질문을 한다.
결제 완료란 무엇인가?
결제 금액은 어떤 값을 의미하는가?
환불 데이터는 어떻게 정의하는가?
Application Owner는 이런 질문을 한다.
결제 API가 정상 동작하는가?
DB 연결에 문제가 없는가?
배포가 정상적으로 이루어졌는가?
권한 검사가 제대로 동작하는가?
즉,
- Data Owner — 데이터의 의미와 책임
- Application Owner — 시스템의 기술적 운영
으로 이해하면 쉽다.
11. 데이터 사용자와 비즈니스 사용자
Data User는 실제로 데이터를 사용하는 사람이다.
예를 들면
SQL 조회
대시보드 확인
리포트 작성
데이터 분석
등이다.
Business User는 비즈니스 요구를 제시하는 역할이다.
예를 들어
"월별 결제 전환율을 보고 싶습니다."
"신규 가입자의 30일 유지율이 필요합니다."
와 같은 요구사항을 만든다.
한 사람이 두 역할을 동시에 수행할 수도 있다.
12. 데이터 생성자
Data Creator는 데이터를 만드는
사람이나 시스템이다.
예를 들어
회원가입 API
결제 시스템
관리자 입력
외부 제휴 시스템
등이 있다.
현대 시스템에서는 사람이 직접 만드는 것보다
애플리케이션이 생성하는 데이터가 더 많은 경우가 일반적이다.
13. 중앙 집중과 도메인 자율성
대규모 조직에서는 중앙 데이터팀이
모든 데이터의 비즈니스 의미를 이해하기 어렵다.
그래서 상황에 따라
- 중앙 조직 — 공통 원칙과 표준
- 각 도메인 — 자기 데이터에 대한 책임
구조를 사용할 수 있다.
특히 Data Mesh 같은 접근에서는
도메인 데이터 소유권과
연합형 거버넌스(Federated Governance)
를 중요한 원칙으로 본다.
하지만 모든 회사가 반드시
이 구조를 사용해야 하는 것은 아니다.
조직 규모와 구조에 따라
중앙 집중형 거버넌스가 더 적합할 수도 있다.
중요한 것은 구조보다
책임과 의사결정 권한이 명확해야 한다는 것
이다.
14. 거버넌스 프레임워크
거버넌스 프레임워크는 쉽게 말해
조직이 데이터를 관리하는 전체 운영 방식
이다.
프레임워크에는 역할만 들어가는 것이 아니다.
역할
책임
정책
표준
절차
가이드라인
등이 함께 정의되어야 한다.
예를 들어 이런 질문에 답할 수 있어야 한다.
Data Owner는 무엇을 승인하는가?
품질 문제가 발생하면 누가 처리하는가?
개인정보 접근은 누가 승인하는가?
데이터 정의 변경은 어떤 절차를 따르는가?
15. 데이터 생명주기
데이터 거버넌스는
데이터가 저장된 순간만 관리하지 않는다.
데이터의 전체 수명주기를 살펴본다.
flowchart LR
n0["생성"] --> n1["저장"] --> n2["제공"] --> n3["사용"] --> n4["보관"] --> n5["폐기"]
회원 데이터를 예로 들면
flowchart LR
n0["회원가입"] --> n1["회원 데이터 생성"] --> n2["DB 저장"] --> n3["API 또는 분석 시스템으로 제공"] --> n4["서비스와 분석에 사용"] --> n5["보존기간 만료"] --> n6["삭제 또는 적절한 후속 처리"]
까지 관리 대상이 될 수 있다.
16. RACI로 책임을 명확하게 하기
복잡한 업무에서는 누가 무엇을 해야 하는지
명확하게 표현할 필요가 있다.
이때 자주 사용하는 방법 중 하나가 RACI다.
R - Responsible
실제 수행자
A - Accountable
최종 책임자
C - Consulted
의견을 제공하는 사람
I - Informed
결과를 전달받는 사람
예를 들어 개인정보 접근 정책을 변경한다면
A
Data Owner
R
Data Steward
C
보안팀 / Application Owner
I
Data User
처럼 정의할 수 있다.
핵심은
최종 책임자가 누구인지 모르는 상태를 없애는 것
이다.
17. 거버넌스 조직의 역할
회사에 별도의 Governance Team이 있다면
모든 데이터를 직접 관리하기보다는
전체적인 관리 체계를 운영하는 역할을 맡는다.
예를 들어
정책과 표준 관리
교육
정기 리뷰
감사
성숙도 평가
개선 영역 식별
등이다.
쉽게 말하면
- Data Owner — 자기 데이터 책임
- Governance Team — 회사 전체의 관리 체계 책임
이다.
18. 거버넌스는 기술 프로젝트만이 아니다
회사가 거버넌스를 시작할 때 흔히
데이터 카탈로그를 사자.
품질 관리 솔루션을 도입하자.
권한 관리 도구를 구축하자.
부터 생각한다.
하지만
데이터 책임자가 없고
정의가 합의되지 않았고
조직 간 책임도 불명확하다면
도구만으로 해결하기 어렵다.
일반적으로는
flowchart LR
n0["역할과 책임"] --> n1["정책과 원칙"] --> n2["프로세스"] --> n3["필요한 도구"]
순서로 생각하는 것이 이해하기 쉽다.
19. 데이터 카탈로그
Data Catalog는 쉽게 말하면
회사의 데이터 검색 시스템
이다.
예를 들어 결제 금액을 검색했을 때
데이터명
payment_amount
정의
실제 승인된 결제 금액
Owner
커머스 도메인
위치
payment_order.amount
개인정보 여부
아님
품질 상태
정상
같은 정보를 확인할 수 있다.
현대적인 카탈로그는 테이블 목록만 보여주지 않는다.
비즈니스 용어, 소유자, 출처, 계보, 분류, 품질,
사용 현황까지 함께 관리할 수 있다.
카탈로그를 어떻게 구축하는지는 15장에서 다뤘다.
거버넌스에서 중요한 것은 카탈로그가
누가 무엇을 책임지는지 드러내는 창구라는 점이다.
20. 애플리케이션 리포지터리
Application Repository는
조직에 어떤 애플리케이션이 존재하는지 관리하는 목록
이라고 생각하면 된다.
예를 들어
Commerce API
Owner
커머스 개발팀
중요도
Critical
주요 데이터
결제 / 주문
개인정보
일부 포함
같은 정보를 관리할 수 있다.
데이터와 애플리케이션을 연결하면
이 데이터는 어느 시스템에서 만들어졌는가?
도 추적하기 쉬워진다.
21. 메타데이터와 데이터 계보
메타데이터는 데이터를 설명하는 데이터다.
컬럼 이름, 타입, 설명, 소유자, 개인정보 여부,
생성 시스템 같은 정보가 여기에 해당한다.
데이터 계보는 데이터가 어디에서 생성되고
어떤 변환을 거쳐 어디에서 사용되는지 추적하는 것이다.
flowchart LR
n0["결제 DB"] --> n1["ETL"] --> n2["Data Warehouse"] --> n3["일별 매출 테이블"] --> n4["경영 대시보드"]
이렇게 기록해 두면 결제 DB의 컬럼을 바꿀 때
어떤 파이프라인이 영향을 받지?
어떤 리포트가 깨질 수 있지?
를 분석할 수 있다.
메타데이터와 계보를 어떻게 모으고 관리하는지는
15장 「메타데이터와 데이터 지도」에서 다뤘다.
거버넌스 관점에서 기억할 것은
이 정보가 없으면 책임도 통제도 성립하지 않는다는 점이다.
22. 데이터 계약
Data Contract는
데이터 제공자와 소비자 사이의 명시적인 약속
이라고 이해하면 된다.
API Contract와 비슷한 생각이다.
예를 들어 결제 이벤트를 제공한다면
- payment_id — bigint / 필수
- user_id — bigint / 필수
- amount — 0 이상
- 제공 주기 — 실시간
- 변경 — 호환성에 영향을 주면 사전 협의
같은 내용을 정할 수 있다.
23. 데이터 계약에 들어갈 수 있는 내용
Data Contract의 범위에는
하나의 국제 표준이 정해져 있는 것은 아니다.
조직이나 도구에 따라 달라진다.
기술적인 내용으로는
스키마
데이터 타입
품질 기준
전송 방식
가용성
버전
변경 정책
등이 포함될 수 있다.
필요하다면 비즈니스나 보안 측면의
사용 목적
허용된 소비자
보존 조건
개인정보 처리 조건
까지 포함할 수도 있다.
즉 Data Contract를
단순한 스키마 정의서로만 볼 필요는 없다.
24. 사용 약정
Usage Agreement는
데이터를 어떤 목적으로 사용할 수 있는지
를 정하는 약속이다.
예를 들어
사용 목적
마케팅 분석
사용 조직
마케팅팀
외부 반출
금지
제3자 재배포
금지
처럼 정의할 수 있다.
중요한 것은
데이터를 가지고 있다는 사실과
그 데이터를 어떤 목적으로든 사용할 수 있다는 것은
같은 의미가 아니라는 점이다.
25. 데이터 계약을 자동 검증하기
Data Contract가 문서로만 존재하면
실제 데이터가 계약을 지키는지 확인하기 어렵다.
그래서 계약을 검증 가능한 규칙으로 만들 수 있다.
예를 들어
- user_id — NULL 불가
- amount — 0 이상
- created_at — 미래 시각 불가
라고 정의했다면 데이터 파이프라인에서
flowchart LR
n0["데이터 생성"] --> n1["계약 검증"] --> n2["품질 테스트"] --> n3["통과"] --> n4["배포 또는 제공"]
과 같은 흐름을 만들 수 있다.
이런 방식은 소프트웨어의 테스트와
CI/CD 사고방식과 비슷하다.
26. 데이터 관측 가능성
Data Observability는
데이터와 데이터 파이프라인의 상태를
지속적으로 관찰할 수 있는 능력
을 의미한다.
서비스를 운영할 때
CPU
Memory
Error
Latency
를 관찰하듯,
데이터에서도 대표적으로
최신성(Freshness)
데이터 양(Volume)
스키마 변화
데이터 품질
데이터 흐름(Lineage)
같은 요소를 관찰할 수 있다.
이것들은 이해를 돕기 위한 대표적인 예이며
공식적으로 고정된 하나의 목록은 아니다.
27. 계약과 관측 가능성
둘의 관계는 다음처럼 이해하면 쉽다.
- Data Contract — 정상 상태를 정의
- Data Observability — 실제 상태를 관찰
예를 들어 계약에
5분 이내에 새로운 데이터가 도착해야 한다.
라고 되어 있는데,
마지막 데이터가 30분 전에 들어왔다면
이상 상태를 감지할 수 있다.
28. 데이터 품질은 가능한 한 앞단에서 해결한다
데이터 품질 문제를 분석 시스템에서 계속 고치는 것은
장기적으로 관리 비용을 높인다.
좋지 않은 구조는 다음과 같다.
flowchart LR
n0["서비스에서 잘못된 값 생성"] --> n1["ETL에서 보정"] --> n2["DW에서 또 보정"] --> n3["리포트에서도 예외 처리"]
가능하면
flowchart LR
n0["데이터가 생성되는 곳에서 올바른 값을 만들고"] --> n1["뒤쪽 시스템이 그대로 사용"]
하는 편이 좋다.
이를 흔히
업스트림에서 품질 문제를 해결한다
고 표현한다.
29. 모든 데이터에 동일한 품질 수준이 필요한 것은 아니다
데이터의 목적에 따라 요구되는 품질 수준은 다르다.
예를 들어
- 정산 금액 — 매우 높은 정확성 필요
- 추천 시스템 행동 로그 — 일부 손실을 허용할 수도 있음
처럼 다르게 판단할 수 있다.
중요한 것은
데이터의 비즈니스 중요도에 맞는
현실적인 품질 목표를 세우는 것
이다.
30. 작게 시작해서 넓혀 간다
거버넌스를 시작하면서
모든 데이터 자동 분류
모든 접근 ABAC 적용
모든 Data Contract 자동 검증
완전한 셀프서비스
를 한 번에 만들려고 하면
프로젝트가 지나치게 커진다.
처음에는 회원·결제·정산처럼
중요한 데이터 몇 개부터 시작하는 것이 좋다.
순서는 조직 상황에 따라 달라지지만
대체로 다음 흐름이 이해하기 쉽다.
flowchart TB
P1["1단계 · 정한다<br/>──────────<br/>데이터 책임자를 정하고<br/>핵심 데이터의 의미를 정의한다"]
P2["2단계 · 보이게 한다<br/>──────────<br/>메타데이터를 모아 카탈로그에서 찾게 하고<br/>민감도와 사용 목적을 분류한다"]
P3["3단계 · 지키게 한다<br/>──────────<br/>접근 정책과 데이터 계약을 적용하고<br/>품질과 관측 가능성을 관리한다<br/>반복 업무는 자동화한다"]
P1 --> P2 --> P3
style P1 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style P2 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style P3 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
핵심은
작게 시작하고 반복적으로 개선하는 것
이다.
31. 거버넌스가 사용자에게 가치를 줘야 한다
사용자 입장에서 거버넌스가
승인
통제
문서 작업
규칙
으로만 느껴지면 정착하기 어렵다.
좋은 거버넌스는
필요한 데이터를 쉽게 찾고
정확한 의미를 확인하고
믿을 수 있는지 판단하고
책임자를 쉽게 찾고
적절한 권한을 빠르게 받는 것
을 가능하게 해야 한다.
즉,
거버넌스가 업무를 방해하는 것이 아니라
업무를 더 쉽게 만들어야 한다.
32. 결국 조직 문화가 중요하다
앞에서 도구보다 역할과 책임이 먼저라고 했다.
그런데 역할을 정해 놓아도
그 역할을 실제로 수행하지 않으면 종이에만 남는다.
결국 사람과 조직이
데이터에 책임을 가지고
공통 정의를 따르고
문제를 발견하면 수정하고
도메인 간에 협력
해야 한다.
그래서 데이터 거버넌스는
기술 프로젝트이면서 동시에
조직 변화 프로젝트
다.
33. 리더십의 역할
거버넌스는 한 팀만의 업무가 아니다.
여러 조직의 업무 방식과 책임에 영향을 준다.
따라서 리더는
왜 필요한지
어떤 원칙으로 운영할지
누가 책임지는지
조직이 어떤 가치를 얻는지
를 명확하게 설명해야 한다.
경영진이나 CDO, CTO, CISO 같은 역할의 지원이
필요한 경우도 많다.
34. 16장 정리
네 가지만 기억하면 된다.
거버넌스는 누가 어떤 기준으로 데이터를 관리할지 정하는 체계다.
같은 이름의 데이터가 팀마다 다른 의미를 갖는 상태를 없애는 일이다.
도구보다 역할과 책임이 먼저다.
책임자가 없고 정의가 합의되지 않은 상태에서
카탈로그를 사도 문제는 그대로 남는다.
데이터 계약은 제공자와 소비자의 명시적인 약속이다.
스키마, 품질 기준, 갱신 주기, 변경 정책을 정해 두면
문서로만 두지 않고 자동으로 검증할 수도 있다.
좋은 거버넌스는 데이터를 막지 않는다.
믿을 수 있는 데이터를 필요한 사람이
안전하게 쓸 수 있게 만드는 것이 목적이다.
다음 장에서는 이 정보를 바탕으로
데이터를 실제로 지키는 방법을 본다.
17장. 보안과 접근 제어
5부 · 신뢰 — 찾고, 믿고, 안전하게 쓰려면
15장 · 16장 · 17장 · 18장
분석용으로 복사해 둔 테이블을 열어 봤다.
운영 DB에서 그대로 떠온 탓에
전화번호와 이메일이 마스킹 없이 들어 있었다.
누가 이 테이블을 조회할 수 있는지도
정리된 적이 없다.
16장에서 누가 무엇을 책임지는지 정했다.
그 정보가 있어야 보호도 할 수 있다.
이 장에서는 데이터를 실제로 지키는 방법을 다룬다.
분류와 라벨, 접근 제어 모델, 행과 열 단위 통제,
그리고 API와 이벤트 각각의 보안이다.
1. 데이터 보안
이제 거버넌스를 통해
데이터가 무엇인지
누가 책임지는지
얼마나 중요한지
왜 사용하는지
알게 되었다.
이 정보를 바탕으로
실제 보호 조치를 적용할 수 있다.
보호 대상은 다양하다.
개인정보
금융정보
건강정보
기업 기밀
지적재산
등이 있다.
2. 데이터 중심 보안
기존 보안은 주로
네트워크
서버
애플리케이션
방화벽
같은 시스템 경계를 보호하는 데 집중했다.
하지만 현대 시스템에서 데이터는
DB
S3
Kafka
DW
API
SaaS
등 여러 환경으로 이동한다.
그래서 데이터가 어디에 있든
데이터 자체의 중요도를 기준으로 보호하는
Data-Centric Security
관점이 중요해졌다.
3. 신뢰 경계
Trust Boundary는
같은 신뢰 수준과 보안 규칙이 적용되는 영역의 경계
라고 이해하면 된다.
예를 들어 커머스 도메인 내부에서 사용되던 데이터가
flowchart LR
n0["커머스"] --> n1["마케팅"]
으로 전달되는 순간,
사용 목적과 사용자가 달라질 수 있다.
따라서 경계를 넘을 때는
누가 사용하는가?
어떤 목적인가?
어떤 데이터가 필요한가?
민감한 정보가 포함되어 있는가?
를 다시 확인할 필요가 있다.
4. 데이터 분류
Data Classification은
데이터의 중요도와 민감도를 구분하는 것
이다.
예를 들어 조직에서 다음과 같이 정할 수 있다.
Public
공개 가능
General
일반 내부 데이터
Confidential
기밀
Highly Confidential
매우 민감한 데이터
명칭과 단계는 회사마다 달라질 수 있다.
5. 분류가 필요한 이유
회사 홈페이지의 공개 공지와
고객의 신용카드 정보를
같은 수준으로 보호할 필요는 없다.
- 공개 정보 — 낮은 보호 수준
- 신용카드 정보 — 높은 보호 수준
즉,
flowchart LR
n0["데이터 중요도"] --> n1["적절한 보호 수준"]
을 결정하기 위해 분류가 필요하다.
6. 데이터 라벨
분류 결과를 실제 데이터에 표시하는 것을
라벨링이라고 생각할 수 있다.
예를 들어
credit_card_number
Classification
→ Highly Confidential
이라는 메타데이터를 붙인다.
시스템은 이 라벨을 보고
마스킹
암호화
접근 제한
감사 강화
같은 정책을 적용할 수 있다.
7. 데이터 사용 목적도 분류할 수 있다
데이터 자체의 민감도뿐 아니라
어떤 목적으로 사용되는지도 분류할 수 있다.
예를 들어
- DATA_SCIENCE — 분석과 연구
- AD_HOC_USAGE — 일회성 분석
- HR_ONLY — 인사 업무
- FINANCIAL_REPORTING — 재무 보고
- DQ_INVESTIGATION — 데이터 품질 조사
처럼 정의할 수 있다.
따라서 같은 데이터라도
HR 업무에는 허용
마케팅에는 금지
처럼 다른 정책을 적용할 수 있다.
8. 인증과 권한은 다르다
무엇을 얼마나 지켜야 하는지는 정했다.
다음은 누구에게 열어 줄 것인가다.
그 전에 자주 섞여 쓰이는 두 낱말부터 구분하자.
Authentication은
누구인가?
를 확인한다.
Authorization은
무엇을 할 수 있는가?
를 결정한다.
따라서
로그인 성공
했다고 해서
모든 데이터 접근 가능
이라는 뜻은 아니다.
9. 접근 제어
Access Control은
누가 어떤 데이터에
어떤 행동을 할 수 있는지 결정하는 것
이다.
대표적으로
ACL
RBAC
ABAC
같은 모델이 있다.
10. ACL
ACL은 Access Control List의 약자다.
대상마다
누가 무엇을 할 수 있는가
를 목록으로 관리한다.
예를 들어
문서 A
사용자 A
→ 읽기
사용자 B
→ 읽기 / 쓰기
사용자 C
→ 접근 불가
와 같은 방식이다.
세밀하게 설정할 수 있지만
사용자와 대상이 많아지면 관리가 복잡해질 수 있다.
11. RBAC
RBAC는 Role-Based Access Control이다.
사용자 개인에게 직접 권한을 주기보다
역할(Role)에 권한을 부여한다.
flowchart LR
n0["사용자 A"] --> n1["HR 역할"] --> n2["직원 정보 조회 권한"]
예를 들어
- HR — 직원 정보 조회
- Finance — 재무 데이터 조회
- Developer — 개발 환경 접근
처럼 정의한다.
기업 시스템에서 널리 사용되는 접근 방식이다.
12. RBAC의 한계
조직이 커지면 역할이 지나치게 많아질 수 있다.
HR
HR 관리자
HR 조회 전용
서울 HR
부산 HR
채용 HR
처럼 역할을 계속 만들게 된다.
이를 Role Explosion 문제라고 한다.
또한 RBAC만으로는
접속 시간
접속 위치
사용 기기
데이터 민감도
같은 동적인 조건을 표현하기 불편할 수 있다.
13. ABAC
ABAC는 Attribute-Based Access Control이다.
역할 하나만 보는 것이 아니라
여러 속성을 조합해서 접근 여부를 판단한다.
예를 들어
사용자 부서 = HR
AND
데이터 분류 = Confidential
AND
관리되는 회사 기기 = true
이면 접근을 허용하는 식이다.
NIST가 설명하는 ABAC 역시
Subject, Object, Action, Environment 등의 속성과
정책을 기반으로 접근 결정을 내리는 방식이다.
14. 정책을 누가 정하고, 누가 판단하고, 누가 막는가
ABAC처럼 조건이 여러 개가 되면 규칙 자체가 복잡해진다.
그 규칙을 서비스 코드 안에 직접 박아 두면
같은 규칙이 여러 곳에 흩어지고, 바꿀 때마다 전부 찾아다녀야 한다.
그래서 보통 세 가지 일을 서로 다른 자리에 맡긴다.
- 규칙을 정하는 자리
- 규칙으로 판단하는 자리
- 판단 결과를 집행하는 자리
사용자가 민감한 HR 데이터를 요청했다고 하자.
요청 하나가 이렇게 흘러간다.
flowchart LR
REQ["사용자 요청"]
PEP["PEP<br/>요청을 가로막고<br/>결정을 적용한다"]
PDP["PDP<br/>정책을 평가해<br/>결정한다"]
PIP["PIP<br/>──────────<br/>사용자 부서 · 데이터 분류<br/>접속 위치 · 기기 정보"]
PAP["PAP<br/>정책을 작성하고<br/>관리한다"]
REQ --> PEP
PEP -- "① 이 요청 허용해도 되나?" --> PDP
PDP -- "② 판단에 쓸 속성 조회" --> PIP
PIP -- "③ 속성 값" --> PDP
PAP -. "정책" .-> PDP
PDP -- "④ ALLOW / DENY" --> PEP
style PDP fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style PEP fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
style PIP fill:#fafafa,stroke:#bbb,color:#1a1a1a
style PAP fill:#fafafa,stroke:#bbb,color:#1a1a1a
네 자리에는 각각 이름이 붙어 있다.
| 이름 | 하는 일 | 실제로는 이런 것 |
|---|---|---|
| PEP (Policy Enforcement Point) | 요청을 가로막고 결정을 적용한다 | API Gateway, DB 프록시 |
| PDP (Policy Decision Point) | 정책을 평가해 ALLOW / DENY를 낸다 | 정책 엔진 |
| PIP (Policy Information Point) | 판단에 필요한 속성을 제공한다 | IdP, 데이터 카탈로그 |
| PAP (Policy Administration Point) | 정책을 작성하고 관리한다 | 정책 관리 콘솔 |
판단 재료는 어디에서 오는가
PIP가 가져오는 속성은 사용자 쪽에만 있는 것이 아니다.
앞에서 데이터에 붙여 둔 분류 라벨과
16장에서 본 Data Contract의 사용 목적도
그대로 판단 재료가 된다.
flowchart LR
IDP["IdP<br/>부서 · 직급 · 그룹"]
CAT["데이터 카탈로그<br/>분류 라벨"]
CON["Data Contract<br/>허용된 사용 목적"]
PIP2["PIP"]
PDP2["PDP<br/>판단"]
IDP --> PIP2
CAT --> PIP2
CON --> PIP2
PIP2 --> PDP2
style PDP2 fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style PIP2 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style IDP fill:#fafafa,stroke:#bbb,color:#1a1a1a
style CAT fill:#fafafa,stroke:#bbb,color:#1a1a1a
style CON fill:#fafafa,stroke:#bbb,color:#1a1a1a
그래서 데이터를 분류해 두는 일이 문서 작업으로 끝나지 않는다.
분류가 곧 정책의 입력이 된다.
그럼 게이트웨이에서 다 막으면 되지 않나
자연스럽게 드는 생각이다.
서비스마다 조건문을 쓰지 말고 API Gateway 한곳에서 검사하면 되지 않을까.
절반은 맞다. Gateway는 대표적인 PEP다.
다만 두 가지를 구분해야 한다.
첫째, 막는 자리를 옮기는 것과 규칙을 한곳에 두는 것은 다른 문제다.
조건문을 각 서비스에서 Gateway로 옮기기만 하면
규칙은 여전히 코드 안에 있다.
흩어져 있던 것이 한 덩어리가 됐을 뿐,
정책을 바꿀 때마다 Gateway를 고쳐서 배포해야 한다.
PDP를 따로 두는 이유가 여기에 있다.
규칙을 코드가 아니라 정책 데이터로 관리하면
막는 쪽을 건드리지 않고 규칙만 바꿀 수 있다.
둘째, Gateway가 판단할 수 없는 것이 있다.
GET /orders를 호출해도 되는지는 Gateway가 판단할 수 있다.
하지만 그 결과에서
어느 행을 보여줄 것인가
전화번호 컬럼을 가릴 것인가
는 데이터가 있는 곳에서만 정할 수 있다.
Gateway는 아직 결과를 보지 못했기 때문이다.
그래서 PEP는 보통 한 군데가 아니다.
flowchart LR
U["요청"]
GW["API Gateway<br/>PEP ①<br/>──────────<br/>이 API를 불러도 되나"]
SVC["서비스 · DB<br/>PEP ②<br/>──────────<br/>어느 행을 보여줄까<br/>어느 컬럼을 가릴까"]
PDP3["PDP<br/>정책은 한곳에"]
U --> GW --> SVC
GW -. "판단 요청" .-> PDP3
SVC -. "판단 요청" .-> PDP3
style GW fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
style SVC fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
style PDP3 fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
행과 열 단위로 좁히는 방법은 이 장 뒤쪽에서 따로 다룬다.
이름보다 중요한 것
중요한 것은 약어가 아니라 역할이 나뉘어 있다는 점이다.
막는 쪽(PEP)과 판단하는 쪽(PDP)이 분리되어 있으므로
정책이 바뀌어도 각 서비스의 코드를 고칠 필요가 없다.
한 가지 덧붙이면, 이 네 이름은
ABAC의 필수 구성요소는 아니다.
XACML 계열을 포함한 정책 기반 접근 제어 아키텍처에서
널리 쓰이는 역할 구분이라고 이해하는 편이 정확하다.
15. 이 사용자가 누구인지 어떻게 아는가
RBAC든 ABAC든 판단의 출발점은 같다.
이 사용자가 누구인가
이걸 모르면 역할도 속성도 확인할 수 없다.
이 일을 맡는 시스템을 Identity Provider(IdP) 라고 부른다.
IdP는 보통 다음과 같은 신원 정보를 제공한다.
사용자 ID
부서
직급
그룹
역할
앞 절에서 PDP가 판단에 쓰려고 PIP에 조회하던 사용자 속성이
대개 여기에서 온다.
서비스마다 로그인하게 할 수는 없다
회사에 서비스가 열 개라고 해서
사용자를 열 번 로그인시킬 수는 없다.
한 번 인증한 사용자가 여러 서비스를 그대로 쓰게 해주는 것이
SSO(Single Sign-On) 다.
SSO를 실제로 구현하는 규약은 여러 가지다.
| 규약 | 주로 쓰이는 곳 |
|---|---|
| SAML | 기업 내부 시스템 |
| OpenID Connect | 웹과 모바일 |
OAuth와 OpenID Connect는 다르다
이 둘은 자주 섞여 쓰이는데 하는 일이 다르다.
| 무엇을 하는가 | |
|---|---|
| OAuth 2.0 | 클라이언트가 보호된 리소스에 제한된 접근 권한을 얻기 위한 권한 부여 프레임워크 |
| OpenID Connect | OAuth 2.0 위에 사용자 인증과 신원 정보를 얹은 것 |
즉 OAuth 자체는 “이 사용자가 누구인가“에 답하는 기술이 아니다.
OAuth = 로그인 기술
이라고만 이해하면 부정확하다.
앞에서 본 인증과 권한의 구분이 여기에도 그대로 적용된다.
16. 데이터 제품마다 보안을 새로 만들 것인가
앞에서 PEP가 한 군데가 아니라고 했다.
데이터 프로덕트에서도 같은 문제가 생긴다.
주문·회원·정산 데이터 프로덕트가 각각 있다면
셋 모두 누가 어디까지 볼 수 있는지 판단하고 적용해야 한다.
이걸 데이터 프로덕트마다 직접 구현하면
프로덕트가 열 개일 때 보안 코드도 열 벌이 된다.
비용도 문제지만 더 큰 문제가 있다.
팀마다 마스킹 방식이 달라지고 감사 로그 형식도 달라진다.
어디가 어떻게 막혀 있는지 아무도 전체를 알지 못하게 된다.
그래서 보안을 데이터 프로덕트 본체에서 떼어낸다.
flowchart LR
subgraph BAD["각자 구현하면"]
B1["주문 DP<br/>+ 보안 코드"]
B2["회원 DP<br/>+ 보안 코드"]
B3["정산 DP<br/>+ 보안 코드"]
end
subgraph GOOD["공통으로 제공하면"]
G1["주문 DP"]
G2["회원 DP"]
G3["정산 DP"]
SEC["공통 보안 계층<br/>──────────<br/>마스킹 · 필터링<br/>접근 판단 · 감사"]
G1 --> SEC
G2 --> SEC
G3 --> SEC
end
style BAD fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style GOOD fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
style SEC fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
떼어내는 방법은 여러 가지다.
- 플랫폼이 제공하는 공통 컴포넌트를 거쳐 데이터를 내보낸다
- 데이터 프로덕트 옆에 보안 처리를 맡는 별도 프로세스를 붙인다 (사이드카)
- 저장소 자체의 행·열 단위 통제 기능을 쓴다
사이드카는 그중 한 가지 구현 패턴이지
반드시 써야 하는 표준은 아니다.
14장에서 본 셀프서비스 플랫폼과 같은 생각이다.
플랫폼이 보안을 기본으로 딸려 보내면
각 도메인이 애써 지키지 않아도 지켜진다.
17. 소비자마다 다른 데이터를 보여주기
같은 데이터셋이라고 해서
모든 사용자에게 모든 컬럼을 보여줄 필요는 없다.
예를 들어 고객 데이터가
이름
이메일
전화번호
주소
결제정보
를 가지고 있다고 하자.
마케팅팀에는
이름
이메일
지역
정도만 제공하고,
정산팀에는
회원 ID
결제 관련 정보
만 제공할 수 있다.
18. 데이터를 보호하는 방법
상황에 따라 다양한 기법을 사용할 수 있다.
- Filtering — 필요 없는 데이터 제외
- Masking — 민감한 값을 일부 숨김
- Tokenization — 실제 값을 다른 토큰으로 치환
- De-identification — 개인을 직접 식별하기 어렵게 처리
각 방식의 법적·보안적 효과는 다를 수 있으므로
사용 목적에 맞는 방법을 선택해야 한다.
19. Row-Level Security
RLS는 행 단위 접근 제어다.
예를 들어 영업 담당자가
SELECT *
FROM sales;
를 실행해도,
실제 결과는 해당 담당 지역 데이터만
보이도록 제한할 수 있다.
개념적으로는
- 사용자 A — 부산 지역 데이터만
- 사용자 B — 서울 지역 데이터만
처럼 동작한다.
20. Column-Level Security
CLS는 컬럼 단위 접근 제어다.
예를 들어
user_id
nickname
phone
resident_number
가 있을 때,
일반 직원에게는
user_id
nickname
만 보이고,
민감한 컬럼은 숨길 수 있다.
21. 도메인 내부와 도메인 간 보안
상황에 따라 도메인 내부 보안과
도메인 간 보안을 다르게 설계할 수 있다.
도메인 내부에서는
개발자
운영자
관리자
처럼 세밀한 권한을 관리한다.
반면
flowchart LR
n0["커머스"] --> n1["마케팅"]
처럼 도메인 경계를 넘는 데이터 공유에는
Data Contract
Usage Agreement
공통 보안 정책
같은 좀 더 명시적인 약속을 적용할 수 있다.
22. API에서는 보안 정보를 어떻게 넘기나
앞에서 Gateway가 문 앞의 PEP가 된다고 했다.
API 환경에서 Gateway는 보통 이런 일을 맡는다.
인증
Access Token 검증
Rate Limit
접근 정책 적용
감사 로그
문제는 그다음이다.
Gateway를 통과한 요청이 Provider에 도착했을 때,
Provider는 이 요청이 누구 것이고 어떤 목적인지 모른다.
그런데 Provider도 PEP다.
어느 행을 보여줄지, 어느 컬럼을 가릴지는 여기서 정해야 한다.
판단하려면 재료가 필요하다.
사용자 ID와 역할만으로는 부족하다
주문 API라면 이런 정보까지 있어야 판단할 수 있다.
user_id
role
customer_id
department
delegation
purpose
이렇게 판단에 필요한 정보 묶음을
Security Context라고 부른다.
누가 Context를 만드나
두 가지 방식이 있다.
flowchart LR
GW["API Gateway"]
SRC["IdP · 권한 시스템<br/>고객 시스템"]
PRV["API Provider"]
GW -- "① 조회해서 Context를 만들고" --> SRC
SRC --> GW
GW -- "요청 + Context" --> PRV
PRV -. "② 또는 Provider가 직접 조회" .-> SRC
style GW fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
style PRV fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
style SRC fill:#fafafa,stroke:#bbb,color:#1a1a1a
| 방식 | 좋은 점 | 치르는 값 |
|---|---|---|
| Gateway가 모아서 넘긴다 | 한곳에서 공통화하기 쉽다 | Gateway가 점점 복잡해진다 |
| Provider가 직접 조회한다 | 도메인에 맞는 최신 판단을 한다 | 호출이 늘어난다 |
어느 쪽이든, 문 앞에서 한 번 막았다고 끝이 아니라
안쪽에서도 판단할 재료가 있어야 한다는 점은 같다.
23. 이벤트 기반 아키텍처의 보안
API는 요청이 들어올 때 막으면 된다.
이벤트는 다르다.
flowchart LR
P["Producer"] --> BRK["Event Broker"]
BRK --> C1["Consumer A"]
BRK --> C2["Consumer B"]
BRK --> C3["Consumer C"]
style BRK fill:#fafafa,stroke:#bbb,color:#1a1a1a
한 번 발행하면 여러 소비자에게 전달되고,
발행하는 쪽은 앞으로 누가 이 이벤트를 받을지 모른다.
브로커 권한으로 되는 것과 안 되는 것
Kafka는 리소스 단위의 ACL로 권한을 제어할 수 있다.
“이 컨슈머가 이 토픽을 구독해도 되나“까지는 여기서 정한다.
| 하고 싶은 것 | 브로커 권한으로 |
|---|---|
| 이 토픽을 구독해도 되나 | 정할 수 있다 |
| 이 컨슈머에게만 전화번호를 가리기 | 정할 수 없다 |
| 허용된 사용 목적의 메시지만 보내기 | 정할 수 없다 |
토픽 접근은 전부 아니면 전무다.
구독 권한을 준 순간 그 토픽의 모든 메시지, 모든 필드가 넘어간다.
Kafka 생태계의 상용 제품에서는 RBAC 같은 기능도 제공하므로
“Kafka는 ACL만 된다“고 단정할 필요는 없다.
다만 어느 쪽이든 메시지 내부의 필드 단위 통제는 별개의 문제다.
그럼 어떻게 하나
세 가지 방법이 있다.
하나. 애초에 민감한 값을 담지 않는다.
이벤트에는 식별자만 싣고, 필요한 쪽이 API로 조회하게 한다.
가장 단순하지만 조회가 늘어나고, 실시간성이 떨어질 수 있다.
둘. 소비자별로 이벤트를 따로 만든다.
원본 고객 이벤트가 이렇다고 하자.
user_id
email
purchase_amount
이것을 정책에 따라 변환해서 소비자마다 다른 이벤트를 내보낸다.
flowchart LR
SRC["원본 Event<br/>──────────<br/>user_id · email<br/>purchase_amount"]
POL["정책에 따른 변환"]
M["마케팅용<br/>──────────<br/>email<br/>purchase_amount"]
A["통계용<br/>──────────<br/>익명 user_id<br/>purchase_amount"]
SRC --> POL
POL --> M
POL --> A
style POL fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style SRC fill:#fafafa,stroke:#bbb,color:#1a1a1a
소비자별로 토픽이 나뉘므로
브로커의 구독 권한만으로 통제가 된다는 것이 장점이다.
다만 토픽과 변환 파이프라인이 늘어나 운영 복잡도가 올라간다.
셋. 소비자 쪽에서 걸러 쓰게 한다.
가장 쉽지만 가장 약하다.
소비자가 규칙을 지킨다고 믿어야 하기 때문이다.
신뢰 경계 안쪽에서만 쓸 만한 방법이다.
앞에서 본 공통 보안 계층을 여기에 두면
변환 규칙을 소비자마다 따로 만들지 않아도 된다.
24. 데이터를 결합하면 보안 책임도 따라온다
예를 들어
회원 데이터
Confidential
+
결제 데이터
Highly Confidential
를 합쳐 새로운 데이터 제품을 만들었다고 하자.
새로운 데이터라고 해서
기존 데이터의 민감도가 사라지는 것은 아니다.
따라서 데이터가 변환되거나 결합되더라도
출처
분류
소유권
사용 제한
같은 정보를 추적할 필요가 있다.
이 때문에 메타데이터와 Lineage가 중요하다.
25. 개인정보와 데이터 윤리
데이터가 많아지고
여러 곳으로 복제될수록
개인정보 보호도 어려워진다.
운영 DB
Kafka
S3
Data Warehouse
Feature Store
ML Dataset
사용자가 개인정보 삭제를 요청했는데
운영 DB만 삭제했다고 끝나는 문제가 아닐 수 있다.
어떤 데이터가 어디에 존재하고
어디까지 전달되었는지 알아야 한다.
AI 활용이 증가하면서
질문은 더욱 넓어진다.
어떤 데이터를 수집했는가?
왜 수집했는가?
어떤 데이터와 결합했는가?
AI 모델에서 어떻게 사용했는가?
모델의 결과가 사람에게 어떤 영향을 미치는가?
데이터의 정확성뿐 아니라
데이터 사용 방식의 적절성도 중요해지는 것이다.
현대의 데이터 거버넌스는
품질과 보안을 넘어
개인정보, 윤리, 투명성, 규제 준수까지
함께 고려해야 한다.
26. 17장 정리
이 장의 흐름을 한 장으로 보면 다음과 같다.
flowchart TB
C1["분류한다<br/>──────────<br/>데이터의 민감도와 사용 목적을 나누고<br/>라벨로 표시한다"]
C2["정책을 만든다<br/>──────────<br/>ACL · RBAC · ABAC 중<br/>상황에 맞는 모델을 고른다"]
C3["집행한다<br/>──────────<br/>PEP가 막고 PDP가 판단한다<br/>정책은 한곳에서 관리한다"]
C4["데이터 단위로 좁힌다<br/>──────────<br/>Filtering · Masking · RLS · CLS로<br/>소비자마다 보이는 범위를 다르게 한다"]
C5["경로마다 적용한다<br/>──────────<br/>API는 Gateway에서<br/>이벤트는 소비자별 변환으로"]
C1 --> C2 --> C3 --> C4 --> C5
style C1 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style C2 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style C3 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style C4 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style C5 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
네 가지만 기억하면 된다.
보안은 데이터를 이해한 다음에 온다.
무엇이고 누가 책임지고 얼마나 민감한지 모르면
무엇을 어느 수준으로 지켜야 할지도 정할 수 없다.
16장에서 정한 책임과 정의가 여기서 재료가 된다.
인증과 권한은 다른 문제다.
로그인에 성공했다는 것이 모든 데이터를 봐도 된다는 뜻은 아니다.
막는 방식은 전부 아니면 전무가 아니다.
Filtering, Masking, RLS, CLS로
같은 데이터셋에서 소비자마다 다른 범위를 보여줄 수 있다.
데이터를 결합해도 민감도는 사라지지 않는다.
그래서 출처와 분류를 따라갈 수 있어야 하고,
메타데이터와 계보가 여기서도 필요하다.
좋은 보안의 목적은 데이터를 막는 것이 아니라,
믿을 수 있는 데이터를 필요한 사람이
허용된 목적과 범위 안에서 안전하게 쓰게 만드는 것이다.
다음 장에서는 여러 도메인이 함께 쓰는
회원·상품 같은 기준 데이터를 어떻게 관리할지 본다.
이 장에서 나온 용어는 부록 C 「용어집」의
「보안」 항목에 정리해 두었다.
18장. 마스터 데이터 관리
5부 · 신뢰 — 찾고, 믿고, 안전하게 쓰려면
15장 · 16장 · 17장 · 18장
회사가 작고 시스템이 몇 개 없을 때는
데이터를 일관되게 관리하기 어렵지 않다.
하지만 회사가 성장하면 회원, 결제, CRM, 상품, 정산,
분석 시스템처럼 여러 시스템이 생긴다.
그러면 자연스럽게 같은 고객이나 상품 정보가
여러 시스템에 중복해서 저장된다.
문제는 시간이 지나면서
각 시스템의 데이터가 조금씩 달라진다는 것이다.
회원 시스템
홍길동 / 010-1234-5678
CRM
홍 길동 / 01012345678
결제 시스템
홍길동 / 010-9999-9999
사람이 보면 같은 고객일 가능성이 높다.
하지만 시스템 입장에서는
서로 다른 고객으로 판단할 수도 있다.
이런 문제를 해결하기 위한 체계가
마스터 데이터 관리
MDM, Master Data Management
이다.
이번 장에서는 MDM이 무엇인지부터 시작해서
도메인 중심의 현대적인 데이터 아키텍처에서
MDM을 어떻게 적용해야 하는지 살펴본다.
1. 마스터 데이터란 무엇인가
마스터 데이터는 여러 업무 시스템에서
반복적으로 사용하는 핵심 기준 데이터다.
대표적인 예는 다음과 같다.
고객
상품
직원
조직
협력사
공급업체
계정
지역
예를 들어 상품 데이터에는 이런 정보가 있을 수 있다.
상품 ID
상품명
상품 분류
브랜드
제조사
판매 상태
이 상품 정보는 상품 시스템만 사용하는 것이 아니다.
상품 시스템
주문 시스템
결제 시스템
재고 시스템
정산 시스템
통계 시스템
여러 시스템에서 동일한 상품을 사용한다.
따라서 시스템마다 상품 정보가 다르면
기업 전체의 데이터 신뢰성이 떨어진다.
2. 왜 MDM이 필요한가
최근 시스템은 업무 영역에 따라
도메인 단위로 분리되는 경우가 많다.
예를 들어 다음과 같다.
회원 도메인
결제 도메인
상품 도메인
정산 도메인
배송 도메인
각 도메인이 자신의 데이터를 직접 관리하면
팀의 독립성과 개발 속도를 높일 수 있다.
하지만 데이터 관점에서는
몇 가지 문제가 발생한다.
같은 데이터가 여러 곳에 존재한다
고객 정보가 회원 시스템뿐 아니라
CRM과 결제 시스템에도 저장될 수 있다.
flowchart LR
M["회원 DB<br/>원본"]
C["CRM"]
P["결제 DB"]
M -- "복사" --> C
M -- "복사" --> P
style M fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
복사한 다음이 문제다.
고객이 전화번호를 바꿨는데
회원 시스템만 수정되었다고 해보자.
| 시스템 | 전화번호 | |
|---|---|---|
| 회원 시스템 | 010-2222-3333 | 변경 반영 |
| CRM | 010-1111-1111 | 옛 값 |
| 결제 시스템 | 010-1111-1111 | 옛 값 |
복사한 쪽은 원본이 바뀐 것을 모른다.
이제 어느 값이 최신 값인지 판단하기 어려워진다.
같은 정제 작업을 여러 번 만든다
각 도메인이 데이터를 독립적으로 관리하면
비슷한 데이터 처리 기능도 반복해서 개발할 수 있다.
예를 들어 전화번호를
01012345678
에서
010-1234-5678
형태로 바꾸는 기능을
회원팀
CRM팀
마케팅팀
정산팀
이 각각 구현할 수 있다.
결과적으로 같은 기능을
여러 번 개발하고 유지보수하게 된다.
같은 이름인데 의미가 다를 수 있다
다음 데이터가 있다고 하자.
customer_status
회원 시스템에서는
ACTIVE
BLOCKED
WITHDRAWN
을 의미할 수 있다.
반면 마케팅 시스템에서는
NORMAL
VIP
DORMANT
를 의미할 수도 있다.
둘 다 이름은 고객 상태지만
실제로 표현하는 개념은 다르다.
이런 상황에서 데이터를 단순히 합치면
잘못된 분석 결과가 만들어질 수 있다.
3. MDM이 해결하려는 문제
MDM의 목적을 간단하게 표현하면 다음과 같다.
여러 시스템에 존재하는 핵심 데이터를
동일한 대상으로 식별하고
신뢰할 수 있는 기준을 제공하는 것
예를 들어 동일한 고객이
여러 시스템에서 다음처럼 관리된다고 하자.
회원 고객 ID = U1001
CRM 고객 ID = C8821
결제 고객 ID = P5512
MDM은 이 세 레코드가
동일한 고객
이라는 사실을 관리할 수 있다.
그리고 필요하다면 다음과 같은
통합된 기준 데이터를 만들 수 있다.
Master Customer ID = M000123
이름 = 홍길동
전화번호 = 010-1234-5678
국가 = KR
이렇게 만들어진 신뢰할 수 있는 기준 레코드를
흔히 골든 레코드(Golden Record) 라고 한다.
4. MDM은 단순한 데이터 통합이 아니다
MDM을 처음 접하면
여러 DB의 데이터를
한 DB에 모으는 것
이라고 생각하기 쉽다.
하지만 이것만으로는 부족하다.
데이터를 추출하고 변환해서
다른 장소로 옮기는 것은 ETL에서도 할 수 있다.
Extract
데이터 추출
Transform
데이터 변환
Load
데이터 적재
MDM에서는 그보다 더 많은 판단이 필요하다.
flowchart LR
n0["수집"] --> n1["표준화"] --> n2["중복 탐지"] --> n3["동일 엔터티 매칭"] --> n4["병합"] --> n5["품질 검증"] --> n6["기준값 결정"] --> n7["배포"]
즉 MDM의 핵심은
데이터를 한곳에 모으는 것보다
어떤 데이터가 같은 대상이며
어떤 값을 신뢰해야 하는지를 관리하는 것
이다.
5. MDM에서 흔히 하는 작업
고객 데이터를 예로 들어보자.
다음처럼 표현이 다른 전화번호가 있을 수 있다.
01012345678
010-1234-5678
+82 10 1234 5678
MDM에서는 이런 데이터를
같은 형식으로 표준화할 수 있다.
다음 두 레코드도 살펴보자.
홍길동
01012345678
홍 길동
010-1234-5678
이 둘이 동일한 사람인지
매칭 규칙을 통해 판단할 수 있다.
또 다음과 같은 작업도 MDM 영역과 연결된다.
데이터 품질 검사
중복 제거
엔터티 매칭
표준화
데이터 보강
병합 규칙
승인 프로세스
데이터 수명주기 관리
중요한 점은 MDM이 특정 제품이나 DB를 뜻하는 것이 아니라
이런 문제를 해결하기 위한 관리 체계와 아키텍처라는 것이다.
6. MDM은 특정 데이터베이스 기술과 관계없다
MDM을 구현할 때 관계형 DB를 사용할 수도 있고
NoSQL이나 그래프 DB를 활용할 수도 있다.
하지만
MDM = NoSQL
처럼 이해하면 안 된다.
MDM에서 중요한 것은 저장 기술보다
동일 엔터티 식별
중복 제거
관계 관리
기준값 결정
품질 관리
거버넌스
다.
저장 기술은 이를 구현하기 위한
선택지 중 하나일 뿐이다.
7. 모든 데이터를 MDM으로 관리하면 안 된다
MDM을 도입할 때 가장 흔한 실수 중 하나는
회사의 모든 데이터를
MDM으로 관리하자
는 생각이다.
예를 들어 다음 데이터를 모두 MDM에 넣는다고 생각해 보자.
고객
상품
결제 로그
클릭 로그
서버 로그
세션
내부 설정
시스템은 지나치게 복잡해진다.
MDM은 일반적으로
여러 시스템이나 도메인에서 공통으로 사용하며
잘못되었을 때 비즈니스 영향이 큰 핵심 데이터
에 적용하는 것이 적절하다.
8. MDM의 네 가지 대표적인 구현 스타일
MDM에는 하나의 정답 구조가 있는 것이 아니다.
대표적으로 다음 네 가지 스타일을 많이 사용한다.
| 스타일 | 핵심 |
|---|---|
| 레지스트리 | 동일한 대상을 연결 |
| 통합(Consolidation) | 여러 데이터를 모아 통합 |
| 중앙집중(Centralized) | MDM이 기준 데이터를 직접 관리 |
| 공존(Coexistence) | MDM과 운영 시스템이 함께 관리 |
이 분류는 절대적인 성숙도 순서가 아니다.
조직의 시스템 구조와 목적에 따라
필요한 방식을 선택하거나 섞어서 사용할 수 있다.
9. 레지스트리 스타일
레지스트리는 비교적 가벼운 MDM 방식이다.
실제 데이터를 모두 중앙으로 옮기는 것이 아니라
회원 U1001
CRM C8821
결제 P5512
→ 동일한 고객
이라는 관계를 관리한다.
구조를 단순하게 표현하면 다음과 같다.
flowchart LR
hub["MDM Registry"]
s0["회원 DB"] --> hub
s1["CRM"] --> hub
s2["결제 DB"] --> hub
기존 운영 시스템을 크게 변경하지 않아도 된다는 장점이 있다.
그래서 기존 시스템의 변경 부담이 큰 조직에서는
좋은 출발점이 될 수 있다.
다만
MDM은 반드시 레지스트리부터 시작해야 한다
는 의미는 아니다.
조직 상황에 따라 처음부터
통합 스타일이나 중앙집중 방식을 사용할 수도 있다.
10. 통합 스타일
통합 스타일에서는 여러 시스템의 데이터를
MDM 저장소에 모은다.
flowchart LR
hub["MDM"]
s0["시스템 A"] --> hub
s1["시스템 B"] --> hub
s2["시스템 C"] --> hub
MDM에서는 데이터를
정제
매칭
중복 제거
병합
해서 신뢰할 수 있는 데이터를 만든다.
그리고 이를 분석이나 보고에서 사용할 수 있다.
flowchart LR
n0["운영 시스템"] --> n1["MDM"] --> n2["BI / 분석 / 보고"]
이 방식에서는 MDM에서 개선된 데이터가
반드시 운영 시스템으로 다시 돌아갈 필요는 없다.
11. 중앙집중식 스타일
중앙집중식에서는
MDM이 마스터 데이터의 권위 있는 관리 지점이 된다.
flowchart TD
m["MDM"] --> a["회원"]
m --> b["결제"]
m --> c["CRM"]
고객 주소가 변경되면
flowchart LR
n0["MDM 수정"] --> n1["다른 시스템으로 배포"]
하는 방식이다.
데이터 일관성을 강하게 관리할 수 있지만
기존 시스템이 MDM의 규칙을 따르도록
변경해야 할 수도 있다.
따라서 기존 시스템이 많은 기업에서는
적용 비용이 커질 수 있다.
12. 공존 스타일
공존 스타일에서는
MDM
에도 데이터가 존재하고
회원
CRM
결제
같은 운영 시스템에도 데이터가 존재한다.
그리고 서로 변경 내용을 주고받는다.
CRM
↕
MDM
↕
회원 / 결제
예를 들어 CRM에서 주소가 변경되면
flowchart LR
n0["CRM 변경"] --> n1["MDM 반영"] --> n2["관련 시스템에 배포"]
할 수 있다.
기존 시스템을 유지하면서
MDM을 적용할 수 있다는 장점이 있다.
하지만 양방향 동기화 때문에
운영 복잡도가 높아진다.
동시에 변경되면 어느 쪽이 우선인가?
동기화에 실패하면 어떻게 복구할 것인가?
변경 순서는 어떻게 관리할 것인가?
같은 문제를 해결해야 한다.
13. Single Source of Truth를 오해하지 말자
1장에서 본 것처럼 Single Source of Truth는
데이터가 물리적으로 한 DB에만 있다는 뜻이 아니다.
MDM에서도 마찬가지다.
공존 스타일처럼 여러 시스템에
같은 데이터가 존재할 수도 있다.
중요한 것은
조직이 어떤 값을 권위 있는 기준으로
신뢰해야 하는지 알 수 있다는 것
이다.
따라서 MDM의 기준 데이터는
하나의 물리적 저장소라기보다
하나의 신뢰 가능한 기준이라고 이해하는 편이 정확하다.
14. 배치와 실시간 처리
MDM은 다른 시스템과
지속적으로 데이터를 주고받는다.
이때 크게 배치와 실시간 방식을 사용할 수 있다.
배치는 일정 시간마다
데이터를 한꺼번에 처리한다.
flowchart TD
n0["매일 새벽 2시"]
n1["회원 데이터 수집"]
n2["MDM 정제"]
n3["분석 시스템 배포"]
n0 --> n2
n1 --> n2
n2 --> n3
대량 처리에 적합하다.
반대로 운영 중 즉시 반영해야 하는 데이터는
API나 이벤트를 사용할 수 있다.
flowchart LR
n0["고객 정보 변경"] --> n1["이벤트 발생"] --> n2["MDM 반영"] --> n3["관련 시스템에 전달"]
MDM이라고 해서
무조건 실시간이어야 하는 것은 아니다.
데이터의 중요도와 업무 요구사항에 따라
배치
API
이벤트
스트리밍
을 적절히 선택한다.
15. 일관성과 속도 사이의 균형
모든 시스템의 데이터를 항상 완벽하게 같게 유지하려면
상당한 비용이 필요할 수 있다.
반대로 처리 속도만 생각하면
잠시 동안 시스템 간 데이터가 다를 수 있다.
예를 들어
결제 차단 상태
는 매우 빠르게 반영해야 할 수 있다.
반면
상품 통계 분류
는 몇 분이나 몇 시간 늦어도
문제가 없을 수 있다.
따라서 MDM 설계에서는
데이터마다 어느 수준의 일관성과
어느 정도의 지연을 허용할 것인지
정해야 한다.
16. 운영 시스템이 MDM을 항상 직접 호출할 필요는 없다
다음과 같은 구조를 생각해 보자.
flowchart LR
n0["주문 요청"] --> n1["고객 MDM 조회"] --> n2["상품 MDM 조회"] --> n3["다른 MDM 조회"] --> n4["주문 처리"]
이 구조에서는 MDM 장애가
주문 장애로 바로 이어질 수 있다.
따라서 핵심 트랜잭션 경로에서
무조건 MDM을 실시간 호출하도록 만들 필요는 없다.
필요에 따라
로컬 복제본
캐시
이벤트 동기화
데이터 프로덕트
API
등을 사용할 수 있다.
17. MDM 설계는 데이터의 출처부터 파악한다
MDM을 만들기 전에
데이터가 어디에서 생성되는지 알아야 한다.
예를 들어 고객 데이터라고 해도
모든 속성이 같은 시스템에서 만들어지는 것은 아니다.
- 이름 — 회원 시스템
- 결제 가능 상태 — 결제 시스템
- 마케팅 등급 — CRM
- 본인인증 정보 — 인증 시스템
따라서 MDM에서는
어떤 속성의 기준 시스템은 어디인가?
를 명확하게 정의해야 한다.
이를 흔히 권위 있는 소스
또는 Source of Truth 관점에서 바라본다.
18. 참조 데이터와 마스터 데이터
마스터 데이터와 함께 자주 등장하는 것이
참조 데이터(Reference Data) 다.
마스터 데이터는
기업의 핵심 대상을 표현한다.
고객
상품
직원
협력사
참조 데이터는
다른 데이터를 분류하거나 설명하는 기준값이다.
국가 코드
통화 코드
지역 코드
상품 분류 코드
예를 들어
고객 = 홍길동
국가 = KR
이라면
홍길동은 마스터 데이터이고KR은 참조 데이터다.
둘은 개념적으로는 다르지만
실제 데이터 관리 체계에서는 함께 관리하는 경우가 많다.
19. 참조 데이터도 일관성이 필요하다
대한민국을 나타내는 값이
시스템 A = KR
시스템 B = KOR
시스템 C = 410
처럼 다를 수 있다.
모두 같은 의미지만
그대로는 데이터 결합이 어렵다.
따라서 중앙 기준과
각 시스템의 로컬 값을 매핑할 수 있다.
flowchart LR
hub["대한민국"]
s0["KR"] --> hub
s1["KOR"] --> hub
s2["410"] --> hub
기존 시스템을 한꺼번에 변경하기 어렵다면
이런 매핑 방식이 현실적인 해결책이 된다.
20. 마스터 식별자
여러 시스템에서 동일한 고객이
각기 다른 ID를 가지고 있다고 하자.
회원 ID = U1001
CRM ID = C881
결제 ID = P553
MDM에서는 이를
Master Customer ID = M000123
으로 연결할 수 있다.
이 마스터 식별자는
여러 시스템에 흩어진 동일한 대상을
하나의 엔터티로 연결하는 역할
을 한다.
21. 애플리케이션 키와 대리 키
기존 업무 시스템의 ID를
마스터 식별자로 사용할 수도 있다.
이를 애플리케이션 키 관점에서 볼 수 있다.
하지만 서로 다른 시스템에서
같은 숫자가 사용될 수도 있다.
회원 ID = 100
CRM ID = 100
둘은 전혀 다른 대상을 의미할 수도 있다.
그래서 MDM에서 별도의
대리 키(Surrogate Key) 를 만들기도 한다.
flowchart LR
hub["Master ID M000123"]
s0["회원 ID U1001"] --> hub
s1["CRM ID C881"] --> hub
s2["결제 ID P553"] --> hub
대리 키 자체에는 특별한 비즈니스 의미를 넣지 않고
대상을 안정적으로 식별하는 역할을 맡기는 것이 일반적이다.
22. 결정적 식별자도 주의해서 사용한다
같은 데이터를 다시 적재할 때마다
새로운 랜덤 GUID를 만든다고 생각해 보자.
첫 번째 적재에서는
홍길동
→ GUID A
두 번째 적재에서는
홍길동
→ GUID B
가 만들어질 수 있다.
이 문제를 해결하기 위해
같은 입력값이면 항상 같은 식별자가 만들어지는
결정적 식별자를 사용할 수도 있다.
하지만 주의할 점이 있다.
예를 들어
이름 + 전화번호
로 식별자를 만들었는데
고객이 전화번호를 변경한다면
같은 고객
→ 다른 ID
가 되어버릴 수 있다.
따라서 이름, 주소, 전화번호처럼
변경 가능한 업무 속성을 영구 마스터 ID의 기반으로 사용할 때는
매우 신중해야 한다.
23. 마스터 ID를 모든 시스템에 강제할 필요는 없다
마스터 ID가 존재한다고 해서
모든 시스템
→ 무조건 Master ID 사용
하도록 할 필요는 없다.
각 시스템은 기존 로컬 ID를 유지하고
Local ID ↔ Master ID
관계만 관리할 수도 있다.
MDM과 직접 관련 없는 시스템이라면
자체 식별자만 사용하는 것도 가능하다.
24. 어디까지 MDM으로 관리할 것인가
앞에서 모든 데이터를 MDM으로 관리하면 안 된다고 했다.
그럼 어디까지가 MDM의 몫인가.
기준은 하나다. 얼마나 넓게 쓰이는 데이터인가.
flowchart LR
E["엔터프라이즈<br/>회사 전체"] --> D["도메인<br/>몇 개 팀"] --> L["로컬<br/>한 시스템"]
style E fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style D fill:#fafafa,stroke:#bbb,color:#1a1a1a
style L fill:#fafafa,stroke:#bbb,color:#1a1a1a
| 범위 | 어떤 데이터인가 | 예 | 어떻게 관리하나 |
|---|---|---|---|
| 엔터프라이즈 | 회사 전체가 같은 의미로 이해해야 한다 | 고객, 상품, 국가 코드 | 전사 기준을 만든다. MDM의 몫 |
| 도메인 | 몇 개 도메인이 함께 쓴다 | 정산 등급, 배송 권역 | 관련 팀끼리 합의한다 |
| 로컬 | 한 시스템 안에서만 쓴다 | 화면 정렬 순서, 내부 캐시 키 | 그 팀이 알아서 한다 |
위로 갈수록 맞춰야 할 사람이 늘어난다.
합의 비용이 커진다는 뜻이다.
그래서 위 칸에 올릴 데이터는 적을수록 좋다.
어떤 데이터를 MDM으로 가져올지 고민된다면
이 질문 하나면 대체로 정리된다.
이 값이 틀리면
몇 개 팀이 곤란해지는가?
한 팀만 곤란하면 그 팀이 알아서 하면 된다.
회사 전체가 곤란하면 전사 기준이 필요하다.
덧붙이면 이 3단 구분은 유용한 설계 관점이지
MDM의 공식 표준으로 외울 것은 아니다.
25. 모든 MDM을 중앙에서 관리할 필요도 없다
회사 전체가 사용하는 데이터는
중앙 MDM에서 관리할 수 있다.
예를 들어
고객
상품
조직
같은 데이터다.
하지만 몇 개 도메인만 사용하는 데이터라면
배송 관련 분류
정산 관련 분류
판매자 등급
해당 도메인 수준에서
관리하는 것이 더 효율적일 수 있다.
즉 현대적인 MDM의 핵심은
모든 것의 중앙화
가 아니라
필요한 범위의 일관성 확보
다.
26. MDM이 만든 기준을 어떻게 내보낼 것인가
기준 데이터를 만들었다면 다른 도메인이 가져다 써야 한다.
가장 쉬운 방법은 MDM DB에 바로 붙게 하는 것이다.
SELECT *
FROM mdm.customer_master
WHERE master_id = 'M000123';
그런데 이러면 7장 「무엇을 공개하고 무엇을 감출 것인가」에서 본
문제가 그대로 돌아온다.
MDM 내부 테이블에 여러 팀이 의존하게 되고,
매칭 규칙을 바꾸려고 컬럼 하나 손대면
누가 깨지는지 알 수 없게 된다.
MDM도 다른 도메인과 똑같이 공개 계약을 내놓는다.
flowchart LR
M1["회원"] --> MDM
M2["CRM"] --> MDM
M3["결제"] --> MDM
MDM["MDM<br/>🔒 내부 구현<br/>──────────<br/>매칭 규칙 · 병합 규칙"]
MDM --> CT["공개 계약<br/>──────────<br/>고객 마스터 API<br/>CustomerMerged Event<br/>고객 마스터 Data Product"]
CT --> C1["마케팅"]
CT --> C2["분석"]
CT --> C3["정산"]
style MDM fill:#f5f5f5,stroke:#999,stroke-dasharray: 5 5,color:#1a1a1a
style CT fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
소비자는 MDM이 몇 개 시스템에서 데이터를 모으는지,
어떤 매칭 규칙을 쓰는지 알 필요가 없다.
정해진 인터페이스만 쓰면 된다.
MDM은 특별한 시스템처럼 보이지만
경계와 계약이라는 점에서는 다른 도메인과 다르지 않다.
27. MDM과 헷갈리기 쉬운 것들
MDM은 하는 일이 겹치는 개념이 많다.
말로 구분하면 계속 헷갈리므로
상황 하나를 놓고 각자 무엇을 하는지 보자.
같은 고객인데
회원 DB의 주소는 부산,
CRM의 주소는 서울이다.
| 이 상황에서 하는 일 | |
|---|---|
| 통합 뷰 | 부산과 서울을 둘 다 보여준다. 어느 쪽이 맞는지는 보는 사람이 판단한다 |
| MDM | 어느 쪽이 기준인지 정한다. 그렇게 정한 값이 골든 레코드다 |
| 데이터 큐레이션 | 이 질문에는 관심이 없다. 주소를 재료로 「수도권 고객 비율」 같은 새 데이터를 만든다 |
| 데이터 웨어하우스 | 정해진 값을 받아 분석용으로 쌓아 둔다 |
| 데이터 프로덕트 | 정해진 기준값을 다른 팀이 쓰기 좋게 포장해서 내보낸다 |
다섯 중 “어느 값이 맞는가“에 답하는 것은 MDM뿐이다.
나머지는 그 답을 가져다 쓰거나, 아예 다른 질문을 한다.
하나씩 조금 더 보자.
통합 뷰 — 보여주기까지가 역할이다
여러 시스템의 데이터를 하나의 쿼리로 묶어
마치 한 테이블처럼 보여줄 수 있다.
flowchart LR
M["회원 DB<br/>주소 = 부산"] --> V["customer_integrated_view"]
C["CRM<br/>주소 = 서울"] --> V
P["결제 DB"] --> V
style V fill:#fafafa,stroke:#bbb,color:#1a1a1a
여기까지는 MDM과 비슷해 보인다.
차이는 값이 어긋났을 때 드러난다.
통합 뷰는 부산과 서울을 나란히 보여주고 끝난다.
그것만으로도 “이 고객 정보가 어디에 어떻게 있는지“를 아는 데 쓸모가 있다.
MDM은 거기서 멈추지 않는다.
어느 시스템의 값을 더 믿을지, 언제 갱신된 값인지를 따져
하나의 기준값을 정해야 한다. 그리고 그 결정에 책임을 진다.
큐레이션 — 묻는 질문 자체가 다르다
데이터 큐레이션은 여러 데이터를 골라 정리하고 결합해
특정 목적에 더 가치 있는 데이터로 만드는 일이다.
flowchart LR
A["회원 데이터"] --> R["고객 활동 분석 데이터"]
B["결제 데이터"] --> R
C2["배송 데이터"] --> R
style R fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
앞의 주소 상황으로 돌아가 보자.
큐레이션은 “부산과 서울 중 뭐가 맞나“를 묻지 않는다.
주소를 재료 삼아 “수도권 고객 비율” 같은
없던 데이터를 만드는 쪽에 관심이 있다.
다만 둘의 경계가 깔끔하게 갈리지는 않는다.
수집·정제·통합·표준화·품질 관리·메타데이터를 똑같이 쓰고,
MDM도 표준화와 병합과 외부 데이터 보강과 파생 속성 생성을 한다.
그래서 이렇게 나누면 틀린다.
MDM은 기존 데이터만 정리한다.
큐레이션만 새로운 데이터를 만든다.
정확한 차이는 무엇이 중심이냐다.
- MDM — 핵심 엔터티의 기준과 식별성
- 큐레이션 — 특정 소비 목적에 맞는 구성과 가공
데이터 웨어하우스 — 기준값을 받아 쓰는 쪽
둘은 경쟁 관계가 아니라 순서 관계다.
flowchart LR
MD["MDM<br/>기준 주소를 정한다"] --> DW["Data Warehouse<br/>분석용으로 쌓는다"] --> BI["지역별 매출 리포트"]
style MD fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
“지역별 매출“을 뽑으려면 먼저 고객의 지역이 하나로 정해져야 한다.
그 결정은 MDM이 하고, 웨어하우스는 그 값을 받아 집계한다.
웨어하우스의 Gold 계층과 MDM 결과를 같은 것으로 보면 안 된다.
Gold는 특정 분석 목적에 맞춰 이미 가공된 결과물이다.
「월별 지역별 매출」 같은 것이다.
MDM이 관리하는 것은 그 집계에 들어가는 재료,
즉 여러 업무 시스템이 공통으로 재사용할 핵심 엔터티다.
데이터 프로덕트 — 층위가 다르다
이 둘은 비교 대상이 아니다.
- MDM — 핵심 데이터를 식별하고 기준을 정하는 체계
- 데이터 프로덕트 — 데이터를 쓰기 좋게 제공하는 방식
그래서 이렇게 말하면 틀린다.
고객 마스터는 MDM인가, 데이터 프로덕트인가?
둘 다다.
기준값을 정하는 과정은 MDM이고,
그 결과를 계약과 함께 내놓는 형태가 데이터 프로덕트다.
앞 절에서 본 구조가 그것이다.
반대로 데이터 프로덕트라고 해서
모두 MDM을 거치는 것도 아니다.
주문 이력이나 행동 로그처럼
한 도메인이 만들어 그대로 내보내는 데이터 프로덕트가 훨씬 많다.
28. MDM 기능 자체도 공통 서비스가 될 수 있다
각 도메인이 다음 기능을
따로 개발할 필요는 없다.
데이터 프로파일링
중복 탐지
매칭
표준화
검증
중앙에서
데이터 품질 서비스
로 만들어서
회원 도메인
상품 도메인
정산 도메인
이 공통으로 사용할 수도 있다.
이렇게 하면 중복 구현을 줄이고
품질 기준도 통일하기 쉽다.
29. 데이터뿐 아니라 처리 로직도 재사용할 수 있다
각 팀이 같은 데이터 변환 로직을
반복해서 만드는 것도 비효율적이다.
예를 들어
전화번호 표준화
주소 정규화
중복 고객 판단
같은 기능이다.
따라서 결과 데이터뿐 아니라
SQL
변환 코드
스크립트
매핑 규칙
도 공유할 수 있다.
그리고 이런 로직을
Git 같은 저장소에서 버전 관리할 수 있다.
다만 공통 로직의 변경은
여러 팀에 동시에 영향을 미칠 수 있다.
그래서
버전 관리
테스트
호환성 관리
변경 승인
이 함께 필요하다.
30. 통합 허브를 통한 데이터 재게시
여러 데이터를 중앙의 통합 허브에서 처리한 뒤
다시 배포할 수도 있다.
flowchart LR
M["회원"]
C["CRM"]
P["결제"]
HUB["통합 허브<br/>──────────<br/>수집 → 정제<br/>통합 → 보강"]
OUT["통합 고객 데이터"]
DOM["여러 도메인"]
M --> HUB
C --> HUB
P --> HUB
HUB --> OUT --> DOM
style HUB fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
이런 구조는 공통 규칙을
한곳에서 적용하기 쉽다는 장점이 있다.
31. 통합 허브의 위험
중앙 허브가 모든 데이터의
필수 경로가 되면 문제가 생길 수 있다.
flowchart LR
n0["허브 장애"] --> n1["여러 시스템 영향"]
중앙 병목이 될 수도 있다.
또 허브에서 데이터를 변경한다면
어떤 데이터가 원본인가?
어떤 규칙이 적용되었는가?
누가 언제 변경했는가?
를 추적해야 한다.
이때 중요한 것이
데이터 계보(Data Lineage) 다.
32. 원본 문제를 허브에서만 고치면 안 된다
회원 시스템의 주소가 잘못됐다고 생각해 보자.
flowchart LR
SRC["회원 DB<br/>❌ 잘못된 주소"] --> FIX["MDM에서 정제"] --> OK["소비 시스템에는<br/>정상 주소"]
style SRC fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style OK fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
겉으로는 해결된 것처럼 보인다.
하지만 원본 시스템은
여전히 잘못된 값을 가지고 있다.
따라서 다음 질문을 결정해야 한다.
MDM에서만 수정할 것인가?
원본 시스템에도 수정 내용을 돌려보낼 것인가?
어느 쪽이 수정 책임을 가지는가?
이 문제는 기술보다
거버넌스와 오너십 문제에 가깝다.
33. 애그리게이트 데이터 프로덕트
여러 도메인이 계속 같은 데이터들을
반복해서 결합한다고 해보자.
회원 + 결제 + 배송
세 개 팀에서 같은 조합을
각각 만들 필요는 없다.
별도의 통합 데이터 프로덕트를 만들 수 있다.
flowchart LR
hub["고객 활동 데이터 프로덕트"]
s0["회원"] --> hub
s1["결제"] --> hub
s2["배송"] --> hub
다른 팀들은 이 결과를 재사용한다.
이렇게 하면
중복된 통합 작업을 줄일 수 있다.
34. 도메인 간 협업 방식
도메인끼리 데이터를 공유하는 방식도
상황에 따라 달라질 수 있다.
대표적으로 다음과 같이 이해할 수 있다.
| 방식 | 특징 |
|---|---|
| 분리 | 서로 맞추지 않고 각자 처리 |
| 파트너십 | 여러 팀이 함께 규칙을 설계 |
| 고객/공급자 | 한 팀이 제공하고 다른 팀이 소비 |
| 순응주의자 | 소비자가 공급자의 모델을 그대로 사용 |
어느 방식이 항상 좋은 것은 아니다.
공유 데이터의 중요도와
팀 간 관계에 따라 선택한다.
35. 데이터 거버넌스가 필요한 이유
MDM은 기술만으로 해결할 수 없다.
다음 질문에 답할 수 있어야 한다.
누가 이 데이터를 책임지는가?
어떤 시스템의 값을 믿는가?
누가 수정할 수 있는가?
중복 레코드는 누가 병합하는가?
품질 기준은 무엇인가?
스키마 변경은 누가 승인하는가?
이런 규칙을 결정하고 운영하는 것이
데이터 거버넌스의 중요한 역할이다.
36. 데이터 계약도 활용할 수 있다
도메인끼리 데이터를 주고받을 때
규칙을 명확하게 정의하는 것도 도움이 된다.
예를 들면 다음과 같다.
customer_id는 필수
국가 코드는 정해진 표준 사용
전화번호 형식 정의
스키마 변경 시 사전 통보
특정 품질 기준 보장
이런 약속을
데이터 계약(Data Contract) 형태로 관리할 수 있다.
37. 메타데이터와 데이터 계보
MDM에서도 메타데이터와 계보가 필요하다.
customer_status
라는 컬럼이 회원 이용 상태인지,
결제 가능 상태인지, 마케팅 상태인지
값만 봐서는 알 수 없기 때문이다.
또 고객 마스터가
flowchart LR
n0["회원 DB"] --> n1["CRM 결합"] --> n2["중복 제거"] --> n3["주소 표준화"] --> n4["고객 마스터"] --> n5["분석 시스템"]
같은 과정을 거쳤다면
문제가 생겼을 때 어느 단계에서 틀어졌는지
추적할 수 있어야 한다.
메타데이터, 데이터 카탈로그, 데이터 계보는
15장 「메타데이터와 데이터 지도」에서 다뤘다.
38. 머신러닝도 활용할 수 있다
MDM에서는 동일한 엔터티를
정확히 찾는 것이 중요하다.
예를 들어
홍길동
01012345678
부산
홍 길동
010-1234-5678
부산
같은 데이터가 동일한 고객인지
판단해야 한다.
규칙 기반 매칭뿐 아니라
통계적 방법이나 머신러닝 기반
엔터티 매칭을 활용할 수도 있다.
하지만
ML을 사용하면 MDM이 완성된다
는 의미는 아니다.
ML은 MDM을 고도화하기 위한
선택 가능한 기술 중 하나다.
먼저 데이터 모델, 품질 규칙,
오너십과 거버넌스가 마련되어야 한다.
39. MDM은 작게 시작하는 것이 좋다
처음부터
회사 전체의 모든 데이터를
하나의 MDM에서 통합
하려고 하면 프로젝트가
지나치게 커질 수 있다.
현실적으로는 다음처럼 접근할 수 있다.
flowchart LR
n0["현재 데이터 상태 파악"] --> n1["중요한 마스터 데이터 선정"] --> n2["식별 관계와 중복 파악"] --> n3["품질·매칭 규칙 적용"] --> n4["마스터 데이터 제공"] --> n5["필요한 경우 운영 시스템과 동기화"]
기존 시스템을 크게 변경하기 어렵다면
레지스트리 스타일이 좋은 출발점이 될 수도 있다.
하지만 조직 상황에 따라
다른 방식부터 시작할 수도 있다.
40. 가장 복잡한 단계는 양방향 동기화다
MDM의 수정 사항을 운영 시스템에 다시 전달하고
운영 시스템의 변경도 MDM으로 가져오는 구조는
강력하지만 복잡하다.
운영 시스템
↕
MDM
↕
다른 운영 시스템
이런 공존 구조에서는
변경 우선순위
충돌 처리
실패 복구
변경 이력
배포 순서
같은 규칙이 반드시 필요하다.
따라서 모든 조직이
공존 스타일을 목표로 할 필요는 없다.
비즈니스에 필요한 수준까지만 구현하면 된다.
41. MDM에서 가장 중요한 균형
현대적인 데이터 아키텍처에는
두 가지 서로 다른 요구가 존재한다.
한쪽은
도메인의 자율성
빠른 개발
독립적인 변경
이다.
다른 한쪽은
전사 데이터 일관성
데이터 품질
재사용성
이다.
모든 것을 도메인에 맡기면
데이터가 파편화될 수 있다.
반대로 모든 데이터를 중앙에서 관리하면
중앙 조직이 병목이 될 수 있다.
이 균형을 잡는 기준이 앞에서 본 데이터의 범위다.
전사 기준이 필요한 데이터에만 전사 기준을 두고,
나머지는 도메인과 팀에 맡긴다.
둘 중 하나를 고르는 문제가 아니라
데이터마다 다르게 판단하는 문제다.
42. 18장 정리
이 장의 흐름을 한 장으로 보면 다음과 같다.
flowchart TB
S1["문제<br/>──────────<br/>회사가 커지면 같은 고객·상품이<br/>여러 시스템에 따로 저장되고<br/>시간이 지나면서 값이 달라진다"]
S2["식별<br/>──────────<br/>흩어진 레코드가 같은 대상인지<br/>매칭 규칙으로 판단한다"]
S3["기준 결정<br/>──────────<br/>표준화하고 병합해서<br/>어떤 값을 믿을지 정한다<br/>(골든 레코드)"]
S4["제공<br/>──────────<br/>API · 이벤트 · 데이터 프로덕트로<br/>필요한 도메인이 재사용한다"]
S5["떠받치는 것<br/>──────────<br/>오너십 · 품질 규칙 · 메타데이터<br/>데이터 계보 · 변경 관리 · 거버넌스"]
S1 --> S2 --> S3 --> S4
S4 -.-> S5
style S1 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style S2 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S3 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style S4 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
style S5 fill:#fafafa,stroke:#bbb,stroke-dasharray: 5 5,color:#1a1a1a
MDM을
중앙 DB 하나 만드는 기술
이라고 이해하면 안 된다.
MDM은
여러 시스템에 흩어진 핵심 데이터를
동일한 대상으로 식별하고,
신뢰할 수 있는 기준을 정하며,
필요한 곳에서 일관되게 사용할 수 있도록 하는
데이터 관리 체계
다.
목적은 거대한 중앙 데이터베이스를 만드는 것이 아니다.
사용자가 데이터를 쓸 때마다
이 고객이 같은 고객인가?
어느 값이 최신 값인가?
어떤 값을 믿어야 하는가?
를 고민하지 않아도 되게 만드는 것이다.
그리고 이 장에서 가장 중요한 원칙은 이것이다.
모든 데이터를 중앙화하지 않는다.
정말 중요한 데이터에 집중한다.
도메인의 자율성을 최대한 유지한다.
공통으로 사용되는 핵심 데이터에는
신뢰할 수 있는 기준을 만든다.
한 문장으로 정리하면,
도메인에는 자율성을 주되,
여러 시스템이 반드시 같은 의미로 이해해야 하는 핵심 데이터에는
공통 기준을 마련하는 것이 현대적인 MDM의 핵심이다.
여기까지가 5부다.
찾고(15장), 규칙을 정하고(16장), 지키고(17장),
기준을 세우는(18장) 네 가지를 봤다.
다음 부에서는 이렇게 믿을 수 있게 만든 데이터를
실제 성과로 바꾸는 이야기를 한다.
19장. 데이터를 소비하는 환경
6부 · 가치 — 어떻게 성과로 바꾸는가
19장 · 20장
제공된 데이터를 누가 어떻게 쓰는가
데이터를 많이 가지고 있다고 해서
그 데이터가 자동으로 가치가 되는 것은 아니다.
회원 데이터, 결제 데이터, 배송 데이터, 주문 데이터가
수년 동안 쌓여 있더라도 실제 업무에서 찾기 어렵고,
의미를 알 수 없으며, 분석하기 힘들다면 활용 가치는 낮다.
데이터가 실제 가치가 되려면 다음 흐름이 필요하다.
flowchart TB
S1["만들고 지킨다<br/>──────────<br/>데이터를 생성하고<br/>신뢰할 수 있게 관리한다"]
S2["내놓는다<br/>──────────<br/>쓸 수 있는 형태로 제공한다"]
S3["가져다 쓴다<br/>──────────<br/>필요한 데이터를 찾아<br/>결합하고 정제하고 변환한다"]
S4["가치로 바꾼다<br/>──────────<br/>BI · 분석 · 머신러닝을 거쳐<br/>의사결정과 서비스 자동화로"]
S1 --> S2 --> S3 --> S4
style S1 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S2 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S3 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style S4 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
앞의 두 칸은 지금까지 다뤘다.
이 장은 세 번째 칸, 제공된 데이터를 누가 어떻게 쓰는가다.
앞 장들에서는 데이터를 어떻게 관리하고,
어떻게 신뢰할 수 있게 제공할 것인지 살펴봤다.
이번 장에서는 그 다음 질문을 다룬다.
제공된 데이터를 누가, 어떻게 사용하고
실제 비즈니스 가치로 연결할 것인가?
이번 장의 핵심은 단순히
“분석 도구를 사용하자”가 아니다.
개인이 일회성으로 하던 데이터 작업을
조직이 반복해서 사용할 수 있는 체계로 만드는 것이 핵심이다.
1. 데이터 제공과 데이터 소비
먼저 데이터 제공과 데이터 소비를 구분할 필요가 있다.
두 활동은 서로 연결되어 있지만
목적과 책임이 다르다.
데이터 제공
데이터 제공자는 자신이 책임지는 데이터를
다른 사람이 신뢰하고 사용할 수 있도록 만든다.
예를 들어 커머스 도메인이 다음 데이터를 관리한다고 하자.
커머스 도메인
결제
주문
환불
상품
커머스 도메인은 단순히 테이블을 보유하는 데서 끝나지 않는다.
다른 시스템이나 분석 조직이 사용할 수 있도록
데이터의 의미와 접근 방법을 명확하게 제공해야 한다.
이때 중요한 것은 다음과 같다.
- 데이터의 의미와 정의
- 데이터 품질
- 접근 방법
- 보안과 권한
- 스키마와 변경 관리
- 소유자와 책임 범위
이런 관점에서 관리되는 데이터를
일반적으로 데이터 프로덕트(Data Product) 라고 부를 수 있다.
다만 데이터 프로덕트에 대한
전 세계적으로 하나뿐인 절대적인 정의가 있는 것은 아니다.
조직마다 구현 방식은 다르지만,
다른 소비자가 신뢰하고 재사용할 수 있도록
책임과 품질을 갖추어 관리하는 데이터 자산
정도로 이해하면 충분하다.
데이터 소비
데이터 소비자는 제공된 데이터를 이용해
업무 문제를 해결한다.
예를 들어 분석팀이 다음 데이터를 사용한다고 하자.
회원 데이터
+
결제 데이터
+
배송 데이터
+
주문 데이터
이 데이터들을 이용해 다음 질문에 답할 수 있다.
판매자별 상품 수 대비 주문 금액은?
신규 회원의 30일 결제 전환율은?
지난달 주문 금액이 감소한 판매자는?
결제 경험이 있는 사용자의 재방문율은?
여기서는 단순 조회만으로 끝나지 않는다.
데이터를
결합
정제
변환
집계
분석
해야 한다.
이것이 데이터 소비 영역이다.
2. 소비자마다 필요한 데이터가 다르다
같은 데이터라도
누가 사용하느냐에 따라 필요한 형태가 달라진다.
예를 들어 결제 데이터가 다음처럼 저장되어 있다고 하자.
payment_id
user_id
amount
payment_method
status
created_at
경영진은 다음을 보고 싶을 수 있다.
일별 매출
월별 매출
전월 대비 성장률
마케팅팀은 다음이 필요할 수 있다.
회원별 누적 결제금액
첫 결제일
최근 결제일
결제 빈도
추천 시스템은 또 다른 형태가 필요하다.
최근 7일 결제 횟수
최근 30일 결제금액
최근 활동 패턴
같은 원본 데이터라도
소비 목적에 따라 필요한 데이터 모델이 달라진다.
따라서 데이터 제공자가
모든 소비자의 요구사항까지 직접 구현하려 하면 문제가 생긴다.
커머스 팀이
마케팅용 데이터도 만들어 주세요.
재무용 데이터도 만들어 주세요.
추천용 데이터도 만들어 주세요.
경영 보고서용 데이터도 만들어 주세요.
라는 요청을 계속 받는다면
본래 도메인 업무보다 데이터 요청 대응에 더 많은 시간을 쓰게 된다.
그래서 기본적으로 다음과 같이 책임을 나누는 편이 좋다.
flowchart LR
p["Provider<br/>재사용 가능한 데이터를<br/>안정적으로 제공"] --> c["Consumer<br/>자신의 목적에 맞게<br/>데이터를 변환하고 활용"]
3. 소비자 특화 변환
소비자가 자신의 목적에 맞게 데이터를 가공하는 것을
소비자 특화 변환(Consumer-Specific Transformation) 이라고 볼 수 있다.
예를 들어 각각의 도메인이 다음 데이터 프로덕트를 제공한다고 하자.
회원 Data Product
결제 Data Product
배송 Data Product
주문 Data Product
분석 영역에서는 이들을 결합해
다음 데이터를 만들 수 있다.
flowchart TD
n0["회원"]
n2["결제"]
n4["배송"]
n6["주문"]
n7["소비 목적에 맞게 변환"]
n8["판매자 성과 분석 데이터"]
n0 --> n7
n2 --> n7
n4 --> n7
n6 --> n7
n7 --> n8
이 구조에서 중요한 원칙은 간단하다.
제공자는 자신의 데이터를 책임지고,
소비자는 자신의 비즈니스 목적에 맞는 변환을 책임진다.
4. 소비자가 모두 제각각 만들면 생기는 문제
소비자에게 모든 것을 자유롭게 맡기는 것도 좋은 해결책은 아니다.
각 팀이 자체적으로 환경을 구축한다고 생각해보자.
마케팅팀
회원 DB → 자체 ETL → 마케팅 DB
분석팀
회원 DB → 자체 ETL → 분석 DB
AI팀
회원 DB → 자체 ETL → ML 저장소
처음에는 빠르게 움직일 수 있다.
하지만 시간이 지나면 조직 안에 다음과 같은 것들이 쌓인다.
서로 다른 ETL
서로 다른 스케줄러
서로 다른 저장소
서로 다른 모니터링
서로 다른 데이터 정의
결국 비슷한 문제를 여러 팀이 반복해서 해결하게 된다.
따라서
소비자는 자유롭게 데이터를 활용하되,
공통적인 데이터 소비 기반을 사용하는 것
이 중요해진다.
5. 공통 소비 환경
그래서 팀마다 따로 만들지 않고 함께 쓰는 자리를 둔다.
이 책에서는 이것을 소비 환경이라고 부르겠다.
특정 업무 목적을 위해
여러 데이터 프로덕트를 가져다 쓰고,
결합·변환·저장·분석하는 논리적인 영역
이름보다 하는 일이 중요하다.
참고로 이 중에서 저장소 부분만 떼어 보면
업계에서 흔히 말하는 데이터 마트(Data Mart) 에 가깝다.
특정 업무 영역을 위해 분석용으로 따로 마련한 저장소라는 뜻이다.
다만 여기서 말하는 소비 환경은 저장소보다 넓다.
다음 절에서 무엇까지 포함하는지 본다.
예를 들면 다음과 같다.
flowchart TD
n0["회원 Data Product"]
n1["결제 Data Product"]
n2["배송 Data Product"]
n3["주문 Data Product"]
n4["분석용 소비 환경"]
n5["정제 · 결합 · 집계"]
n6["보고서 · BI · ML"]
n0 --> n4
n1 --> n4
n2 --> n4
n3 --> n4
n4 --> n5
n5 --> n6
6. 소비 환경은 데이터베이스 하나가 아니다
저장소라는 말 때문에
소비 환경 = 특정 DB 하나
라고 생각하기 쉽다.
하지만 데이터를 가져다 쓰려면 저장소만으로는 안 된다.
상황에 따라 다음이 함께 들어간다.
Database
Data Warehouse
Data Lake
ETL / ELT
데이터 파이프라인
스케줄러
BI
머신러닝
모니터링
CI/CD
따라서 소비 환경은
특정 업무 목적을 위한 작은 데이터 플랫폼
정도로 이해하면 쉽다.
7. 소비 환경에서 만들어지는 데이터
소비 환경 안에서는 여러 종류의 데이터가 생성될 수 있다.
복사된 데이터
원본과 의미는 거의 같지만
다른 저장소로 복사한 데이터다.
Commerce DB
payment
↓ 복제
분석용 소비 환경
payment_copy
운영 시스템의 부하를 분리하거나
분석에 더 적합한 기술을 사용하기 위해 복사할 수 있다.
다만 운영 DB를 직접 조회하는 것이
항상 잘못된 것은 아니다.
데이터가 작거나 부하가 낮거나,
Read Replica 등을 활용해 충분히 감당할 수 있다면
직접 조회도 가능하다.
핵심은
분석 부하가 운영 서비스에 영향을 주지 않도록 설계하는 것
이다.
통합된 데이터
여러 데이터를 결합해
새로운 비즈니스 문맥을 만든 데이터다.
flowchart TD
n0["회원"]
n2["결제"]
n4["배송"]
n6["주문"]
n7["판매자별 월간 성과 데이터"]
n0 --> n7
n2 --> n7
n4 --> n7
n6 --> n7
이 데이터는 각각의 원본에는 존재하지 않았지만
결합을 통해 새로운 의미가 생긴다.
새롭게 생성된 데이터 프로덕트
소비 환경에서 만든 결과가 여러 곳에서 반복 사용된다면
새로운 데이터 프로덕트로 발전할 수 있다.
flowchart LR
n0["회원 + 결제 + 배송"] --> n1["고객 가치 점수"] --> n2["Customer Value Data Product"]
이 데이터는 다시
마케팅
CRM
추천
운영
등에서 사용할 수 있다.
8. 모든 가공 데이터가 데이터 프로덕트는 아니다
분석 과정에서 데이터를 한 번 결합했다고 해서
모두 데이터 프로덕트가 되는 것은 아니다.
예를 들어
flowchart LR
n0["회원 + 결제"] --> n1["일회성 분석"] --> n2["결과 폐기"]
라면 굳이 별도의 데이터 프로덕트를 만들 이유가 없다.
반대로 다음과 같은 상황이라면
정식 데이터 프로덕트로 관리할 가치가 있다.
반복적으로 사용됨
여러 소비자가 사용함
명확한 책임자가 필요함
품질 관리가 필요함
안정적인 인터페이스가 필요함
즉,
일회성 분석 결과
≠
데이터 프로덕트
이다.
9. Consumer가 다시 Provider가 될 수 있다
데이터 세계에서는 역할이 고정되어 있지 않다.
처음에는 어떤 조직이
다른 데이터 프로덕트를 사용하는 Consumer일 수 있다.
flowchart TD
n0["회원 Data Product"]
n2["결제 Data Product"]
n3["분석팀"]
n0 --> n3
n2 --> n3
하지만 분석팀이
고객 LTV
고객 등급
판매자 수익성 지표
같은 데이터를 만들고
다른 조직에 제공하기 시작하면
분석팀은 새로운 Provider가 된다.
flowchart LR
p["Provider"] --> c["Consumer"] --> n["새로운 데이터 생성"] --> p2["다시 Provider"] --> c2["다른 Consumer"]
따라서 데이터의 출처와 변환 과정을 추적하는
Data Lineage가 중요해진다.
10. 공식 데이터의 출처를 명확히 한다
데이터가 여러 번 복제되고 가공되면
같은 이름을 가진 데이터가 여러 곳에 존재할 수 있다.
예를 들어
| 저장소 | 매출 값 |
|---|---|
| Commerce DB | 10,000원 |
| Analytics DB | 9,500원 |
| Marketing DB | 11,000원 |
처럼 모두 다른 매출 숫자를 보여준다면 문제가 된다.
그래서 다음을 명확히 해야 한다.
이 데이터의 공식 정의는 무엇인가?
누가 책임지는가?
어디가 신뢰할 수 있는 출처인가?
이런 공식적인 출처를
Golden Source 또는 Authoritative Source 등의 표현으로 부르기도 한다.
중요한 것은 명칭보다
어떤 데이터를 공식 기준으로 사용할 것인지
조직이 합의하고 관리하는 것
이다.
11. 소비 환경의 경계를 정하는 방법
소비 환경을 무조건 많이 만드는 것이 좋은 것은 아니다.
너무 잘게 쪼개면
소비 환경 A
소비 환경 B
소비 환경 C
소비 환경 D
...
사이에 데이터 이동과 통합이 계속 발생한다.
반대로 모든 것을 하나에 몰아넣으면
거대한 중앙 데이터 플랫폼이 되어버린다.
따라서 적절한 경계를 찾아야 한다.
가장 중요한 기준은 다음 두 가지다.
비즈니스 목적
+
기술 요구사항
비즈니스 목적
먼저 다음을 질문한다.
무슨 문제를 해결하려는가?
누가 이 데이터를 사용하는가?
결과를 어디에 사용할 것인가?
예를 들어
판매자별 상품 수 대비 판매 효율을 분석한다.
가 하나의 목적일 수 있다.
기술 요구사항
같은 데이터를 사용하더라도
기술 조건이 다르면 구조를 분리할 수도 있다.
예를 들어
월간 경영 보고서
는 하루 단위 배치로도 충분할 수 있다.
하지만
실시간 이상 결제 탐지
는 수초 이하의 지연시간이 필요할 수 있다.
같은 결제 데이터를 사용한다고 해서
반드시 같은 시스템에 넣을 필요는 없다.
12. 기술보다 비즈니스 문제가 먼저다
데이터 프로젝트를 시작하면
기술부터 생각하기 쉽다.
Kafka를 쓸까?
Spark를 쓸까?
MongoDB를 쓸까?
BigQuery를 쓸까?
하지만 좋은 설계는 반대 순서로 시작한다.
flowchart LR
n0["무엇을 해결하려는가?"] --> n1["어떤 데이터가 필요한가?"] --> n2["얼마나 빨리 필요한가?"] --> n3["누가 사용할 것인가?"] --> n4["어떤 수준의 품질과 안정성이 필요한가?"] --> n5["적합한 기술은 무엇인가?"]
즉,
기술이 문제를 결정하는 것이 아니라
문제가 기술을 결정해야 한다.
13. 비기능 요구사항
기능 요구사항이
매출을 계산한다.
라면,
비기능 요구사항은
얼마나 빨라야 하는가?
얼마나 많은 데이터를 처리해야 하는가?
얼마나 안전해야 하는가?
얼마나 오래 보관해야 하는가?
를 결정한다.
데이터 시스템에서는 특히 다음을 살펴본다.
성능
확장성
지연시간
가용성
보안
비용
데이터 크기
증가 속도
쿼리 패턴
데이터 보존기간
일관성 요구사항
14. 저장소를 어떻게 고르는가
데이터 저장소는 기술의 인기가 아니라
실제 데이터 특성을 기준으로 고른다.
봐야 할 축은 두 개다. 무엇을 저장하는가와 어떻게 읽는가다.
무엇을 저장하는가
| 데이터가 이렇다면 | 검토할 것 |
|---|---|
| 정형이고 관계와 트랜잭션이 중요하다 | RDBMS |
| JSON 중심이고 구조가 자주 바뀐다 | Document DB |
| 대규모 파일이고 분석용이다 | Object Storage, Data Lake, 분석용 저장소 |
다만 이렇게 외우면 안 된다.
RDB = 강한 일관성
NoSQL = 최종 일관성
RDB = 스키마 고정
NoSQL = 스키마 없음
현대 데이터베이스는 제품과 구성에 따라 여러 일관성 모델을 제공한다.
NoSQL에서도 스키마 관리가 필요할 수 있고,
RDBMS도 JSON 타입이나 온라인 스키마 변경 같은 유연성을 제공한다.
실제 제품이 무엇을 제공하는지 확인해야 한다.
어떻게 읽는가
저장할 데이터만 보고 고르면 절반만 본 것이다.
소비자가 어떻게 읽을지에 따라 맞는 저장 형태가 달라진다.
| 읽는 방식 | 예 | 맞는 저장 형태 |
|---|---|---|
| PK로 한 건씩 찾는다 | 주문 상세 조회, 회원 정보 | 행 지향 — RDBMS, 키-값 저장소 |
| 수십억 건을 훑어 집계한다 | 월별 매출, 판매자별 통계 | 열 지향 — 분석용 웨어하우스, Parquet |
왜 갈리는지는 저장 방식을 보면 알 수 있다.
flowchart LR
ROW["행 지향<br/>──────────<br/>한 행의 모든 컬럼을<br/>붙여서 저장한다"]
COL["열 지향<br/>──────────<br/>같은 컬럼의 값끼리<br/>모아서 저장한다"]
style ROW fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style COL fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
SELECT * FROM orders WHERE order_id = 1 처럼 한 건을 통째로 꺼낼 때는
행 지향이 유리하다. 그 행만 읽으면 끝나기 때문이다.
반대로 SELECT SUM(amount) FROM orders 처럼 한 컬럼만 대량으로 훑을 때는
열 지향이 유리하다. amount만 읽으면 되고,
비슷한 값이 모여 있어 압축도 잘 된다.
행 지향에서 대량 집계를 돌리면
읽지 않아도 될 컬럼까지 전부 읽게 된다.
둘 다 필요하면
둘 다 두면 된다.
주문 처리는 운영 DB에서 하고,
주문 통계는 분석용 저장소에 따로 쌓는 식이다.
변경 모델과 조회 모델을 나누는 생각은
9장 「서비스 경계와 조회 모델」에서 다뤘다.
다만 같은 데이터를 두 곳에 두면 동기화 비용이 생긴다.
그 대가는 14장 「데이터 프로덕트를 신뢰할 수 있게 만들기」에서 다뤘다.
15. 데이터 기술을 너무 많이 늘리지 않는다
문제마다 가장 적합한 데이터베이스를 선택하는 접근을
Polyglot Persistence라고 부르기도 한다.
개념 자체는 유용하다.
하지만 지나치게 적용하면 조직 안에
MySQL
PostgreSQL
MongoDB
Cassandra
Redis
Elasticsearch
ClickHouse
BigQuery
...
가 계속 늘어난다.
그러면 각각에 대해
운영
백업
모니터링
보안
장애 대응
업그레이드
전문 인력
이 필요하다.
따라서 조직 차원에서는
몇 가지 표준 저장소를 정해 두고,
명확한 이유가 있을 때만
새로운 기술을 추가하는 것이 현실적이다.
16. 데이터 파이프라인
저장소를 정했다면
데이터가 어떻게 이동하고 가공되는지 설계해야 한다.
이를 Data Pipeline이라고 한다.
flowchart LR
n0["운영 DB"] --> n1["CDC"] --> n2["Kafka"] --> n3["Data Lake"] --> n4["ETL / ELT"] --> n5["Data Warehouse"] --> n6["BI"]
파이프라인은 단순 이동만 뜻하지 않는다.
수집·정제·변환·검증·통합·저장·배포까지 포함한다.
돌리는 방식은 크게 둘이다.
| 언제 쓰나 | 예 | |
|---|---|---|
| 배치 | 일정 주기로 모아서 처리 | 월간 보고서, 정산 |
| 스트리밍 | 들어오는 대로 계속 처리 | 이상거래 탐지, 실시간 추천 |
둘의 선택 기준은 12장 「무엇으로 연결할 것인가」에서 다뤘다.
여기서 기억할 것은 하나다.
같은 데이터를 쓴다고 해서
같은 방식으로 처리해야 하는 것은 아니다.
17. ETL과 ELT
전통적인 방식은 ETL이다.
flowchart LR
n0["Extract"] --> n1["Transform"] --> n2["Load"]
먼저 데이터를 가져오고
가공한 후 대상 시스템에 저장한다.
ELT는 순서가 다르다.
flowchart LR
n0["Extract"] --> n1["Load"] --> n2["Transform"]
먼저 데이터를 저장한 뒤
저장된 데이터를 필요에 따라 변환한다.
현대적인 클라우드 데이터 플랫폼에서는
ELT 방식이 널리 사용된다.
하지만 ETL이 구식이라는 뜻은 아니다.
보안, 데이터 품질, 대상 시스템 특성에 따라
ETL이 더 적합한 경우도 있다.
18. 파이프라인도 운영해야 한다
데이터 파이프라인 역시 프로그램이다.
그런데 애플리케이션 코드는 Git에 넣고 테스트하고 CI/CD로 배포하면서,
파이프라인은 서버에 스크립트 하나 올려 두고 끝내는 경우가 많다.
같은 것이 필요하다.
Git
Versioning
Test
CI/CD
Monitoring
특히 파이프라인의 입력 · 변환 · 출력을 명확히 나누면
입력 저장소가 바뀌어도 변환 로직을 다시 쓰지 않아도 된다.
그리고 데이터가 정상적으로 이동했다고 해서
데이터 자체가 정상이라는 보장은 없다.
필수 컬럼 존재 여부, NULL 비율의 급증, 중복 ID,
음수 금액, 참조 무결성, 건수의 비정상적 감소 같은 것을
파이프라인 안에서 자동으로 검사한다.
변환을 코드처럼 관리하는 방법과 품질 검사의 종류는
14장 「데이터 프로덕트를 신뢰할 수 있게 만들기」에서 다뤘다.
여기서는 그 장치들이 소비 환경의 파이프라인에도 똑같이 필요하다는 점만 기억하면 된다.
19. 가져올 수 있는가와 가져와도 되는가
운영 시스템에서 분석 환경으로 데이터를 복사할 때는
가져올 수 있는가?
뿐 아니라
가져와도 되는가?
를 생각해야 한다.
예를 들어 분석에 필요하지 않은
이름
전화번호
이메일
CI
IP
까지 무조건 복사할 필요는 없다.
필요하다면
제거
마스킹
토큰화
가명처리
등을 적용한다.
20. 메타데이터와 데이터 계보
파이프라인이 복잡해질수록 다음 질문이 어려워진다.
이 테이블은 어디에서 왔는가?
이 컬럼은 어떻게 계산했는가?
누가 이 데이터를 관리하는가?
어떤 데이터가 바뀌면 이 보고서가 영향을 받는가?
그래서
Owner
Schema
Source
Transformation
Version
Lineage
같은 메타데이터를 관리해야 한다.
특히 데이터가
flowchart LR
n0["원본"] --> n1["정제"] --> n2["통합"] --> n3["집계"] --> n4["보고서"]
처럼 여러 단계를 지나간다면
Data Lineage가 중요하다.
메타데이터와 계보를 어떻게 관리하는지는 15장에서 다뤘다.
21. 계층화된 데이터 모델
분석 환경에서는 데이터를 단계별로 나누기도 한다.
대표적인 예가 Bronze / Silver / Gold 구조다.
원본에 가까운 데이터, 정제·검증된 데이터,
비즈니스 목적에 맞게 가공된 데이터로 나눈다.
각 단계를 어떻게 나누는지는
14장 「데이터 프로덕트를 신뢰할 수 있게 만들기」에서 다뤘다.
여기서 기억할 것은 하나다.
이것은 유용한 설계 패턴이지
모든 시스템이 반드시 따라야 하는 규칙은 아니다.
단순한 환경이라면
flowchart LR
n0["원본"] --> n1["분석 테이블"]
만으로 충분할 수도 있다.
22. 같은 구성을 매번 다시 고르지 않는다
새 팀이 분석 환경을 만든다고 하자.
저장소는 뭘 쓸지, 적재는 어떻게 돌릴지,
권한은 어떻게 줄지, 모니터링은 무엇을 걸지를
팀마다 처음부터 정한다.
세 번째 팀쯤 되면 같은 회의를 세 번 한 셈이 되고,
조금씩 다른 환경이 세 벌 남는다.
그래서 자주 쓰는 구성을 미리 한 벌로 묶어 둔다.
이렇게 미리 만들어 둔 표준 구성을 Blueprint라고 부른다.
원래 건축 도면이라는 뜻인데, 여기서는
“이대로 만들면 되는 기본 설계” 정도로 이해하면 된다.
예를 들어 「분석용」 한 벌은 이런 식이다.
| 항목 | 기본값 |
|---|---|
| 저장소 | 분석용 웨어하우스 |
| 적재 | 매일 새벽 배치 |
| 오케스트레이션 | 공통 스케줄러 |
| 권한 | 도메인 단위 읽기, 개인정보 컬럼 마스킹 |
| 모니터링 | 적재 실패 알림, 건수 급감 알림 |
| 메타데이터 | 카탈로그 자동 등록 |
| 배포 | 공통 CI/CD 파이프라인 |
목적별로 몇 벌을 준비해 둘 수 있다.
분석용
실시간 처리용
ML용
리포트용
팀은 맞는 것을 골라 시작하고, 필요한 부분만 바꾼다.
중요한 것은 이것이 강제가 아니라는 점이다.
기본값을 제공해 반복 설계를 줄이는 것
이 목적이다.
특수한 요구사항이 있다면 그 부분을 바꿀 수 있어야 한다.
바꿀 수 없으면 기본값이 아니라 규제가 된다.
14장에서 본 셀프서비스 플랫폼이 이런 기본값을 제공하는 쪽이다.
클라우드 환경에서 같은 생각을 어떻게 적용하는지는
부록 A 「클라우드 랜딩 존과 Blueprint」에서 다룬다.
23. 숫자를 사람이 읽을 수 있게 만든다
소비 환경에 데이터를 잘 쌓아 뒀다고 하자.
그런데 기획자가 테이블을 열어 보면 이렇게 되어 있다.
settle_amt payment_status_cd member_seq
결국 데이터팀에 물어보게 된다.
데이터를 만드는 일과
그 데이터를 사람이 쓸 수 있게 만드는 일은 다르다.
뒤쪽을 맡는 것이 BI(Business Intelligence) 다.
BI는 이런 질문에 답한다.
어제 매출은 얼마였는가?
이번 달 주문 금액은 증가했는가?
어떤 판매자의 성과가 좋아졌는가?
이를 위해 대시보드, 보고서, KPI, 차트,
그리고 직접 파 볼 수 있는 임시 분석 화면을 제공한다.
그래서 BI는 그래프를 그리는 도구가 아니라
데이터를 의사결정으로 잇는 마지막 구간이다.
flowchart LR
D["데이터"] --> I["사람이 읽을 수 있는 정보"] --> A["의사결정"]
style A fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
다만 화면을 보기 좋게 만드는 것만으로는 부족하다.
그 화면에 찍히는 숫자가 무엇인지 먼저 합의되어야 한다.
24. 시맨틱 계층
Semantic Layer는 앞의 두 문제를 한꺼번에 푼다.
첫째, 이름을 이어 준다
| 데이터베이스에는 | 현업은 이렇게 부른다 |
|---|---|
payment_status_cd | 결제상태 |
settle_amt | 매출 |
member_seq | 회원 |
seller_idx | 판매자 |
현업 사용자가 settle_amt를 몰라도매출을 골라 쓸 수 있게 해준다.
둘째, 계산식을 정한다
이쪽이 더 중요하다.
매출이라는 말 하나에도 계산식이 여럿이다.
매출 = 결제완료 금액
매출 = 결제완료 금액 - 환불
매출 = 결제완료 금액 - 환불 - 취소
시맨틱 계층은 이 중 하나를 공식 계산식으로 못 박는다.
없으면 이렇게 된다.
flowchart LR
P["기획팀 쿼리"] --> N1["매출 102억"]
F["재무팀 쿼리"] --> N2["매출 98억"]
M["마케팅팀 쿼리"] --> N3["매출 110억"]
style N1 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style N2 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style N3 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
셋 다 틀리지 않았는데 회의에서 숫자가 맞지 않는다.
그리고 회의 시간의 절반을 “그 숫자 어떻게 뽑으셨어요“에 쓴다.
그래서 시맨틱 계층은
조직의 비즈니스 용어와 지표를 통일하는 공통 언어
역할을 한다.
13장의 유비쿼터스 언어, 15장의 비즈니스 용어집과 같은 문제를
BI 화면 쪽에서 푸는 장치라고 보면 된다.
25. Self-Service Analytics
전통적인 분석 조직에서는
현업이 데이터를 보고 싶을 때 데이터팀에 요청한다.
flowchart LR
U["현업"] -- "요청" --> T["데이터팀"]
T -- "SQL · 분석" --> R["결과 전달"]
R --> U
style T fill:#fff4f4,stroke:#d9534f,stroke-width:2px,color:#1a1a1a
간단한 질문에도 며칠이 걸리고
데이터팀은 단순 조회 요청에 묻힌다.
그래서 현업이 직접 하게 하자는 것이
Self-Service Analytics다.
개발자가 아닌데 어떻게 직접 하나
여기서 바로 의문이 생긴다.
SQL을 모르는 기획자가 어떻게 데이터를 가져다 쓰는가.
답은 앞에서 만들어 둔 것들에 있다.
| 필요한 것 | 어디서 왔나 | 현업이 할 수 있게 되는 일 |
|---|---|---|
| 데이터 카탈로그 | 15장 | 「주문」으로 검색해 쓸 만한 데이터를 찾는다 |
| 시맨틱 계층 | 앞 절 | settle_amt가 아니라 「매출」을 골라 쓴다 |
| 미리 만든 데이터셋 | 소비 환경 | 이미 결합·집계된 것을 그대로 쓴다 |
| BI 도구 | 앞 절 | 끌어다 놓기와 필터로 화면을 만든다 |
즉 현업이 SQL을 배우는 것이 아니라,
SQL이 필요 없는 지점까지 미리 깔아 두는 것이다.
그중에서도 시맨틱 계층이 결정적이다.
매출이라는 항목 하나에 계산식이 이미 박혀 있으므로
현업은 그것을 고르고 기간과 조건만 바꾸면 된다.
시맨틱 계층이 없으면 셀프서비스는 성립하지 않는다.
결국 컬럼 이름을 물어보러 데이터팀에 가게 된다.
어디까지가 셀프서비스인가
물론 전부를 맡길 수는 없다.
| 현업이 스스로 하는 것 | 데이터팀이 하는 것 |
|---|---|
| 기존 지표를 기간·조건별로 본다 | 새 데이터 소스를 연결한다 |
| 만들어 둔 데이터셋을 필터하고 집계한다 | 지표 계산식을 새로 정의한다 |
| 화면을 만들고 공유한다 | 파이프라인을 만들고 운영한다 |
그래서 셀프서비스의 목적은
모든 직원을 데이터 엔지니어로 만드는 것이 아니다.
현업이 간단한 질문과 탐색과 일회성 분석과 가설 검증을
스스로 할 수 있게 하는 것이다.
그러면 데이터팀은 단순 조회 요청 대신
데이터 플랫폼
데이터 품질
데이터 프로덕트
거버넌스
같은 일에 집중할 수 있다.
경계를 넘는 요청이 반복해서 들어온다면
그건 현업이 욕심을 내는 것이 아니라
플랫폼에 빠진 것이 있다는 신호로 보는 편이 낫다.
26. Data Discovery
셀프서비스에서는
Data Discovery도 중요하다.
정형 분석은 일반적으로 질문이 먼저 있다.
flowchart LR
n0["지난달 매출은 얼마인가?"] --> n1["데이터 조회"] --> n2["답"]
반면 데이터 탐색은
데이터를 보면서 질문을 발견하기도 한다.
flowchart LR
n0["데이터 탐색"] --> n1["이상한 패턴 발견"] --> n2["왜 이런 현상이 발생했지?"] --> n3["새로운 가설"] --> n4["추가 분석"]
즉,
질문에 답하는 분석뿐 아니라
새로운 질문을 발견하는 분석도 중요하다.
27. 공식 관리 데이터와 셀프서비스 데이터를 구분한다
셀프서비스를 허용하면
각 사용자가 새로운 데이터를 만들 수 있다.
예를 들어
VIP 후보군
실험용 고객 점수
특정 캠페인 사용자 그룹
이런 데이터를 공식 데이터와 똑같이 취급하면 문제가 발생한다.
그래서 크게 두 종류로 나눌 수 있다.
관리형 데이터
공식 매출
공식 회원수
공식 주문 금액
처럼 조직에서 공식적으로 사용하는 데이터다.
다음이 명확해야 한다.
정의
품질
소유자
권한
거버넌스
셀프서비스 데이터
사용자가 분석이나 실험 과정에서
임시로 만든 데이터다.
빠르게 바뀔 수 있고
공식 지표로 사용하기에는 검증이 부족할 수 있다.
따라서 조직에서는
Certified
Managed
Experimental
Personal
같은 방식으로 데이터의 상태를 구분할 수도 있다.
28. 셀프서비스 결과를 운영화한다
셀프서비스에서 좋은 분석이 발견됐다고 하자.
처음에는 분석가 한 명이 수동으로 계산했지만
계속 사용할 가치가 확인되었다.
그렇다면 다음 단계로 넘어가야 한다.
flowchart LR
n0["실험"] --> n1["가치 검증"] --> n2["정의 정리"] --> n3["품질 검증"] --> n4["자동화"] --> n5["관리형 데이터"]
이를 운영화(Operationalization) 라고 생각할 수 있다.
즉,
개인의 분석을
조직이 반복해서 사용할 수 있는 시스템으로 바꾸는 과정
이다.
29. 19장 정리
네 가지만 기억하면 된다.
제공자와 소비자의 책임을 나눈다.
제공자는 재사용 가능한 데이터를 안정적으로 제공하고,
소비자는 자기 목적에 맞는 변환을 책임진다.
제공자가 모든 소비자의 요구를 직접 구현하면
본래 업무보다 데이터 요청 대응에 시간을 더 쓰게 된다.
소비자가 제각각 만들면 같은 문제를 여러 번 푼다.
그래서 공통 소비 기반이 필요하다.
시맨틱 계층은 지표 정의를 통일하는 공통 언어다.매출이 팀마다 다르게 계산되면
회의에서 숫자가 맞지 않는다.
셀프서비스의 목적은 모두를 엔지니어로 만드는 것이 아니다.
현업이 간단한 질문과 탐색을 스스로 할 수 있게 하고,
데이터팀은 플랫폼과 품질에 집중하게 하는 것이다.
다음 장에서는 여기서 한 걸음 더 나간
머신러닝과 그 운영을 본다.
20장. 머신러닝과 MLOps
6부 · 가치 — 어떻게 성과로 바꾸는가
19장 · 20장
추천 모델을 만들어 배포했다.
석 달이 지났다.
그동안 사용자 구성은 꽤 달라졌는데
모델 성능을 확인한 사람은 아무도 없다.
19장에서 데이터를 소비하는 환경을 만들었다.
여기서 한 걸음 더 나가면 머신러닝이 있다.
이 장에서는 모델을 만드는 이야기보다
모델을 계속 운영하는 이야기를 주로 다룬다.
좋은 모델 하나를 만드는 것보다
모델을 반복해서 만들 수 있는 체계가 어렵기 때문이다.
데이터 활용이 아직 그 단계가 아니라면
이 장은 건너뛰어도 된다.
1. 고급 분석과 머신러닝
데이터 활용이 발전하면
머신러닝을 사용할 수 있다.
예를 들어
구매 가능성이 높은 사용자는 누구인가?
이탈 위험 사용자는 누구인가?
이 결제는 이상거래인가?
어떤 상품을 추천해야 하는가?
같은 문제를 해결할 수 있다.
BI와는 무엇이 다른가
앞 장에서 본 BI와 헷갈리기 쉽다.
흔히 이렇게 나눈다.
BI = 과거 분석
ML = 미래 예측
외우기는 쉽지만 정확하지 않다.
BI에서도 예측이나 What-if 분석을 할 수 있고,
머신러닝도 예측 말고 분류·군집화·이상탐지·추천에 쓰인다.
차이는 시점이 아니라 하는 일에 있다.
| 무엇을 하는가 | |
|---|---|
| BI | 사람이 데이터를 이해하고 판단하도록 돕는다 |
| ML | 데이터에서 패턴을 학습해 예측·분류·추천·자동화로 확장한다 |
BI는 사람이 결정하고, ML은 결정의 일부를 기계에 넘긴다.
넘기는 순간 새로운 문제가 생긴다.
하지만 여기에서 중요한 점이 있다.
모델을 만드는 것보다
모델을 지속적으로 운영하는 것이 더 어렵다.
그래서 등장하는 것이 MLOps다.
2. MLOps란 무엇인가
MLOps는
머신러닝 모델을 안정적으로 개발하고,
검증하고, 배포하고, 운영하기 위한 엔지니어링 체계
라고 이해하면 된다.
흔히
ML + DevOps
라고 설명하지만, 실제로는 DevOps보다 관리 대상이 많다.
일반 애플리케이션은 주로
Code
를 관리한다.
ML 시스템에서는 다음을 함께 관리해야 한다.
Code
Data
Feature
Model
Configuration
Environment
3. 머신러닝 전체 생애주기
MLOps에서는 모델 하나만 보지 않고
프로젝트 전체 흐름을 관리한다.
flowchart LR
n0["비즈니스 문제 정의"] --> n1["데이터 탐색"] --> n2["데이터 준비"] --> n3["피처 엔지니어링"] --> n4["모델 학습"] --> n5["모델 평가"] --> n6["배포"] --> n7["운영 모니터링"] --> n8["필요 시 재학습"]
이 과정은 한 번으로 끝나는 것이 아니라
계속 반복된다.
4. 프로젝트 시작부터 표준화한다
새로운 ML 프로젝트를 시작할 때마다
Git 저장소
폴더 구조
환경
CI/CD
실험 기록 방식
을 새로 정의하면 비효율적이다.
따라서 조직에서는
프로젝트 템플릿
표준 코드 구조
공통 라이브러리
공통 실행 환경
을 제공할 수 있다.
다만 모든 프로젝트를 똑같이 만들 필요는 없다.
반복되는 부분을 표준화하고
특수한 부분만 개별적으로 설계하는 것이 목적이다.
5. Experiment Tracking
머신러닝 실험에서는 작은 차이만으로도
모델 결과가 달라질 수 있다.
예를 들어
데이터셋
Feature
Algorithm
Hyperparameter
Code Version
이 달라지면 결과도 달라진다.
그래서 실험할 때마다 다음을 기록한다.
어떤 데이터를 사용했는가?
어떤 피처를 사용했는가?
어떤 파라미터인가?
성능은 얼마인가?
어떤 코드 버전인가?
이것을 Experiment Tracking이라고 한다.
MLflow 같은 도구가 대표적인 예다.
6. 재현 가능성
머신러닝에서는
지난달 만들어진 모델을
오늘 동일한 조건에서 다시 만들 수 있는가?
가 중요하다.
이를 위해
Code Version
Data Version
Feature Version
Parameter
Environment
를 함께 관리해야 한다.
이를 Reproducibility, 즉 재현 가능성이라고 한다.
7. Feature Engineering
원본 데이터를 그대로 모델에 사용하는 것보다
새로운 의미를 가진 입력값을 만들어 사용하는 경우가 많다.
예를 들어 원본에는
주문 이벤트
조회 이벤트
결제 이벤트
가 있을 수 있다.
이를 이용해 다음과 같은 피처를 만든다.
최근 7일 주문 횟수
최근 30일 체류시간
마지막 결제 후 경과일
최근 30일 결제금액
이처럼 모델이 사용할 입력 변수를 만드는 과정을
Feature Engineering이라고 한다.
8. Feature Store
여러 모델이 같은 피처를 반복 사용한다면
각 팀이 따로 구현하는 것은 비효율적일 수 있다.
이때 Feature Store를 사용할 수 있다.
예를 들어
Feature Store
user_7d_order_count
user_30d_watch_minutes
days_since_last_payment
처럼 공통 피처를 관리할 수 있다.
주요 장점은 다음과 같다.
피처 재사용
정의 일관성
학습과 서비스 간 계산 차이 감소
유지보수 개선
하지만 Feature Store는
모든 ML 시스템에 반드시 필요한 것은 아니다.
모델이 적고 피처 공유가 거의 없다면
기존 Data Warehouse나 DB만으로도 충분할 수 있다.
즉,
반복적으로 사용하고 운영할 가치가 있는 피처를
중앙 관리할 필요가 있을 때 도입한다.
9. 모델 제공 방식
학습한 모델을 실제 서비스에서 사용하는 방식은 여러 가지다.
대표적으로 다음 세 가지를 생각할 수 있다.
| 방식 | 특징 | 예 |
|---|---|---|
| API | 요청 시 즉시 추론 | 실시간 추천 |
| Batch | 일정 주기로 대량 추론 | 일일 이탈예측 |
| Stream | 들어오는 이벤트를 지속적으로 추론 | 실시간 이상거래 탐지 |
여기서 Stream 모델이라는 별도의 모델 종류가 있는 것은 아니다.
정확히는
스트림으로 들어오는 이벤트를 모델이 계속 추론하는 구조
라고 이해하면 된다.
10. Model Registry
모델이 계속 만들어지면
파일 이름만으로 관리하기 어렵다.
model_v1
model_v2
model_final
model_final2
really_final
같은 상황이 발생한다.
그래서 Model Registry를 사용할 수 있다.
Order Prediction
v1 → Archived
v2 → Staging
v3 → Production
같이 버전과 상태를 관리한다.
모델과 함께 다음 정보도 기록할 수 있다.
학습 데이터
피처
성능
작성자
배포 시점
모델 버전
11. 모델 배포 후 모니터링
모델을 배포했다고 프로젝트가 끝나는 것은 아니다.
운영 환경에서는 계속 상태를 확인해야 한다.
모델 성능
응답시간
오류율
입력 데이터 품질
입력 데이터 분포
예측 결과 분포
특히 시간이 지나면서
운영 환경의 데이터가 달라질 수 있다.
12. Drift를 구분해서 이해한다
Drift라는 말을 하나의 현상처럼 사용하기 쉽지만
조금 더 구분하는 것이 좋다.
Data Drift
입력 데이터의 분포가 달라지는 현상이다.
예를 들어 예전에는
20대 사용자 70%
였는데 어느 순간
40대 사용자 60%
가 되었다면 입력 분포가 크게 바뀐 것이다.
Prediction Drift
모델이 출력하는 예측값의 분포가 달라지는 현상이다.
예를 들어 기존에는
고위험 사용자 5%
였는데 갑자기
고위험 사용자 40%
가 된다면 점검이 필요하다.
Concept Drift
입력과 실제 결과 사이의 관계 자체가 바뀌는 현상이다.
예전에 구매 가능성을 높이던 행동이
시장이나 사용자 행동 변화로 더 이상 같은 의미를 가지지 않을 수 있다.
중요한 점은
Drift가 발생했다고 해서 반드시 모델 성능이 떨어졌다는 뜻은 아니며,
모델 성능 저하 역시 Drift 하나만으로 설명되는 것은 아니다.
따라서 여러 신호를 함께 봐야 한다.
13. 모델 재학습
모델은 필요할 때 다시 학습할 수 있다.
재학습 기준은 여러 방식으로 정할 수 있다.
매주 재학습
신규 데이터 일정량 누적
성능 기준 이하로 하락
Data Drift 발생
중요한 비즈니스 이벤트 발생
다만 모든 모델을 자주 재학습할 필요는 없다.
데이터 분포가 안정적이고
모델 성능도 유지되고 있다면
재학습 빈도가 매우 낮아도 된다.
즉,
재학습 주기는 모델의 특성과 데이터 변화 속도를 기준으로 결정한다.
14. 자동 재학습과 자동 배포는 구분한다
재학습을 자동화한다고 해서
flowchart LR
n0["재학습"] --> n1["즉시 운영 배포"]
까지 자동으로 해야 하는 것은 아니다.
위험도가 높은 시스템에서는
flowchart LR
n0["재학습"] --> n1["자동 평가"] --> n2["사람 또는 정책 기반 승인"] --> n3["운영 배포"]
를 사용할 수 있다.
자동화 수준 역시
업무 위험도에 따라 결정해야 한다.
15. 안전한 모델 배포
새 모델을 만들었다고
기존 모델을 한 번에 교체할 필요는 없다.
A/B 테스트
기존 모델 → 일부 사용자
신규 모델 → 일부 사용자
로 나누어 실제 서비스 지표를 비교한다.
반드시 50:50일 필요는 없다.
99:1
95:5
90:10
처럼 작은 비율로 시작할 수도 있다.
Shadow Deployment
실제 요청을 두 모델이 모두 처리하지만
사용자에게는 기존 모델 결과만 보여준다.
flowchart LR
req["실제 요청"] --> a["기존 모델"] --> s["실제 서비스에 사용"]
req --> b["신규 모델"] --> l["결과만 기록"]
신규 모델을 실제 트래픽에서
안전하게 검증하는 방법이다.
A/B 테스트와 Shadow 방식은 유용한 선택지이지만
모든 모델에 반드시 필요한 절차는 아니다.
16. 모델 지표와 비즈니스 지표
모델의 기술적인 정확도가 높아졌다고 해서
반드시 비즈니스가 좋아지는 것은 아니다.
예를 들어 추천 모델의 정확도가 올라갔어도
체류시간
재방문율
주문율
매출
이 개선되지 않았다면
비즈니스 관점에서는 성공이라고 보기 어려울 수 있다.
따라서
Model Metric
+
Business Metric
을 함께 본다.
예를 들어
flowchart LR
M["추천 정확도 ↑<br/>모델 지표"] --> S["체류시간 ↑"] --> C["주문 전환율 ↑<br/>비즈니스 지표"]
style M fill:#fafafa,stroke:#bbb,color:#1a1a1a
style C fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
까지 연결되어야 한다.
모델 지표만 보고 있으면
정확도는 올랐는데 아무것도 나아지지 않은 상태를 알아차리지 못한다.
17. 학습한 환경과 서비스하는 환경이 다르다면
모델을 만드는 곳과 쓰는 곳은 환경이 다른 경우가 많다.
모델은 파이썬으로 PyTorch를 써서 만들었는데,
그 모델을 쓸 서비스는 Java로 돌아갈 수 있다.
학습에 쓴 프레임워크를 서비스 서버에 그대로 올리자니
무겁고, 언어도 맞지 않는다.
그래서 모델을 프레임워크에서 떼어내는 형식이 필요하다.
ONNX
ONNX(Open Neural Network Exchange) 가 그런 형식 중 하나다.
이미지에 PNG라는 공통 형식이 있는 것과 비슷하다.
어떤 그림 도구로 그렸든 PNG로 저장하면 어디서나 열린다.
모델도 마찬가지로, 학습에 쓴 도구와 상관없이
공통 형식으로 저장해 두면 다른 환경에서 실행할 수 있다.
flowchart LR
PT["PyTorch"] --> ONNX
TF["TensorFlow"] --> ONNX
SK["scikit-learn"] --> ONNX
ONNX["ONNX 파일<br/>──────────<br/>프레임워크에 묶이지 않은<br/>공통 형식"]
ONNX --> RT["ONNX Runtime"]
RT --> J["Java 서비스"]
RT --> C["C++ 서비스"]
RT --> M["모바일 · 엣지"]
style ONNX fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
학습은 익숙한 프레임워크로 하고,
서비스는 ONNX Runtime이 있는 환경이면 어디서든 돌린다.
추론에 최적화된 런타임을 쓸 수 있어
속도나 자원 면에서 이득을 보기도 한다.
만능은 아니다
다만 이렇게 생각하면 안 된다.
ONNX로 변환하면
어디에서든 100% 동일하게 실행된다.
변환 과정에서 지원되지 않는 연산자가 있을 수 있고,
직접 만든 계층은 그대로 옮겨지지 않을 수 있다.
런타임 구현에 따라 결과가 미세하게 달라지기도 한다.
그래서 변환한 뒤에는
원래 모델과 같은 결과가 나오는지 반드시 확인한다.
ONNX는 모델의 상호운용성을 높이는 수단이지
모든 환경을 똑같이 만들어 주는 장치가 아니다.
18. MLOps의 본질
결국 MLOps의 목적은
좋은 모델 하나 만들기
가 아니다.
좋은 모델을
반복해서 만들고
검증하고
배포하고
감시하고
개선할 수 있는 체계
를 만드는 것이다.
즉,
모델이 아니라 모델을 만드는 공장을 만드는 것
이라고 생각하면 이해하기 쉽다.
이 장에서 나온 장치들을 다시 보면 모두 같은 일을 한다.
| 장치 | 무엇을 반복 가능하게 만드나 |
|---|---|
| 프로젝트 템플릿 | 시작하는 방식 |
| Experiment Tracking | 무엇을 시도했는지 |
| 재현 가능성 | 같은 결과를 다시 만드는 일 |
| Feature Store | 피처를 다시 쓰는 일 |
| Model Registry | 어느 모델이 운영 중인지 |
| 모니터링과 재학습 | 성능을 유지하는 일 |
관통하는 낱말은 셋이다.
표준화
자동화
재사용
사람이 매번 손으로 처리하면 느리고 실수가 생긴다.
템플릿, CI/CD, 자동 테스트, 자동 모니터링으로 옮길 수 있는 것은 옮긴다.
환경별로 코드를 따로 두지 않는 것도 같은 생각이다.
DB 주소나 모델 버전 같은 값은 코드에 박지 않고
공통 코드 하나에 환경별 설정을 붙인다.
정책도 문서로만 두면 지켜지지 않는다.
개인정보 암호화나 저장 지역 제한 같은 규칙은
시스템이 자동으로 검사하게 만들 수 있다.
이 이야기는 ML에만 해당하지 않는다.
조직 전체에 어떻게 적용하는지는
22장 「플랫폼과 조직」에서 다룬다.
19. 19~20장을 하나로 연결하면
6부에 등장한 용어가 많아서
처음에는 각각 별개의 주제처럼 느껴질 수 있다.
하지만 하나로 이으면 단순하다.
flowchart LR
sys["업무 시스템<br/>회원 · 결제 · 배송 · 주문"]
dp["Data Product"]
dds["소비 환경"]
sys --> dp --> dds
dds --> bi["BI"]
dds --> ml["ML"]
bi --> sem["Semantic Layer"] --> ss["Self-Service"] --> dec["사람의 의사결정"]
ml --> fe["Feature"] --> mt["Model"] --> ops["MLOps"] --> auto["예측 · 추천 · 자동화"]
style dds fill:#f8fbff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style dec fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
style auto fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
갈라지는 지점은 하나뿐이다.
사람이 결정하느냐, 기계가 결정하느냐다.
그리고 이 모든 것을 밑에서 받치는 기반이 있다.
Platform
Governance
Security
Metadata
Lineage
Automation
셋은 같은 것을 한다
소비 환경, BI, MLOps를 나란히 놓으면
사실 같은 방향을 향하고 있다.
- 소비 환경 — 데이터 소비를 표준화하고 재사용한다
- BI — 분석과 지표를 표준화하고 재사용한다
- MLOps — ML 개발과 운영을 표준화하고 재사용한다
조직의 데이터 활용은 대체로 이 길을 지난다.
flowchart LR
n0["개인의 수작업"] --> n1["공통 패턴 발견"] --> n2["표준화"] --> n3["자동화"] --> n4["재사용"] --> n5["운영 가능한 시스템"]
style n0 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
style n5 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
6부의 제목이 「가치」인 이유가 여기에 있다.
데이터가 가치가 되는 것은 많이 저장해서가 아니라
이 사슬이 끝까지 이어질 때다.
20. 20장 정리
네 가지만 기억하면 된다.
모델을 만드는 것보다 운영하는 것이 어렵다.
그래서 MLOps는 모델이 아니라 모델을 만드는 공장을 다룬다.
ML은 관리할 것이 코드만이 아니다.
데이터, 피처, 모델, 설정, 환경까지 함께 버전을 맞춰야
지난달 모델을 오늘 다시 만들 수 있다.
자동 재학습과 자동 배포는 다른 문제다.
재학습을 자동화했다고 바로 운영에 올릴 이유는 없다.
위험도에 따라 평가와 승인을 사이에 둔다.
모델 지표가 올라도 비즈니스 지표는 그대로일 수 있다.
정확도와 체류시간과 전환율이 이어지는지 함께 봐야 한다.
여기까지가 6부다.
데이터의 가치는 많이 저장하는 데서 생기지 않는다.
신뢰할 수 있는 데이터를 사람들이 쉽게 찾고 소비하며,
반복 가능한 분석과 의사결정과 자동화로 연결할 때 만들어진다.
좋은 데이터 아키텍처의 최종 목표는
거대한 데이터베이스를 만드는 것이 아니다.
조직의 사람들이 데이터를 믿을 수 있고,
필요한 데이터를 쉽게 찾을 수 있고,
필요한 형태로 안전하게 쓸 수 있으며,
좋은 분석과 모델이 발견되면
그 결과를 조직 전체가 다시 쓸 수 있는 시스템으로 키우는 것.
그것이 데이터를 비즈니스 가치로 바꾸는 아키텍처의 핵심이다.
이 장에서 나온 용어는 부록 C 「용어집」에 정리해 두었다.
다음 부에서는 지금까지의 이야기를
실제 조직에서 어떻게 시작할지 다룬다.
21장. 도메인 토폴로지
7부 · 실행 — 어디서부터 시작하는가
21장 · 22장 · 23장
앞 장까지는 데이터 도메인이 무엇인지,
그리고 비즈니스를 어떤 기준으로 나눠야 하는지를 살펴봤다.
이제 다음 단계로 넘어가야 한다.
회원
결제
배송
주문
정산
이렇게 도메인을 나눴다고 해서
아키텍처 설계가 끝난 것은 아니다.
실제 시스템을 만들려면 다음과 같은 질문에
답해야 한다.
각 도메인의 데이터는 누가 관리할까?
다른 도메인의 데이터는 어떻게 사용할까?
도메인끼리 직접 연결할까?
중앙 데이터 플랫폼을 둘까?
어떤 기능을 공통으로 제공할까?
클라우드에서는 각 도메인을 어디에 배치할까?
이 장이 답하는 것은 앞쪽 질문들이다.
도메인들을 어떻게 연결하고 운영할 것인가
마지막 질문, 즉 이 구조를 실제 클라우드에 어떻게 배치하는지는
부록 A 「클라우드 랜딩 존과 Blueprint」에서 따로 다룬다.
1. 도메인 토폴로지란 무엇인가
토폴로지(Topology)는 어렵게 생각할 필요가 없다.
쉽게 말하면
구성 요소들이 어디에 있고,
서로 어떻게 연결되어 있는지를 나타내는 구조
다.
예를 들어 회사에 다음과 같은 도메인이 있다고 하자.
회원
결제
배송
주문
정산
도메인을 나눈 뒤에는
이들의 관계를 정해야 한다.
예를 들어 주문 도메인은
회원 정보가 필요할 수 있다.
정산 도메인은
주문 결과를 필요로 할 수 있다.
flowchart LR
n0["회원"] --> n1["주문"] --> n2["정산"]
그렇다면 다음을 결정해야 한다.
주문이 회원 DB를 직접 조회할까?
회원 도메인이 API를 제공할까?
이벤트를 받을까?
중앙 데이터 플랫폼에서 가져올까?
이러한 관계를 설계하는 것이
도메인 토폴로지다.
2. 먼저 알아야 할 것: 정답은 하나가 아니다
도메인 아키텍처에는
모든 회사에 적용되는 하나의 정답이 없다.
어떤 조직은 빠른 개발과
팀의 자율성을 중요하게 생각한다.
각 팀이 기술을 선택
각 팀이 직접 운영
각 팀이 빠르게 변경
반대로 어떤 조직은
보안
데이터 품질
규제 준수
감사
표준화
를 더 중요하게 생각할 수 있다.
따라서 아키텍처를 설계한다는 것은
결국 여러 요소 사이에서 균형점을 찾는 일이다.
| 한쪽을 택하면 | 다른 쪽을 잃는다 |
|---|---|
| 자율성 | 통제 |
| 개발 속도 | 표준화 |
| 독립성 | 운영 효율 |
| 분산 | 중앙집중 |
3. 데이터 제품이란 무엇인가
도메인 구조를 이해하려면
먼저 데이터 제품(Data Product) 개념이 필요하다.
6장에서 본 것처럼 데이터 제품은
DB 테이블이나 파일 하나를 뜻하지 않는다.
다른 사람이 신뢰하고 사용할 수 있도록
의미·품질·소유자·접근 방법까지 함께 관리한 데이터다.
무엇을 갖춰야 데이터 제품이라고 부를 수 있는지는
13장에서 다뤘다.
이 장에서는 데이터 제품을
도메인이 외부에 내놓는 단위 정도로 생각하면 충분하다.
4. 데이터 메시와 도메인 소유권
데이터 메시(Data Mesh)를 이야기할 때
가장 중요한 개념 중 하나가
도메인 중심 데이터 소유권이다.
기존에는 이런 구조가 많았다.
flowchart LR
hub["중앙 데이터팀"]
s0["회원 데이터"] --> hub
s1["결제 데이터"] --> hub
s2["주문 데이터"] --> hub
s3["배송 데이터"] --> hub
s4["정산 데이터"] --> hub
모든 데이터를 중앙 데이터팀이 관리한다.
문제는 중앙 데이터팀이
모든 비즈니스 의미를 정확히 알기 어렵다는 것이다.
예를 들어 주문 데이터는
주문 서비스를 만드는 팀이 가장 잘 이해한다.
그래서 데이터 메시에서는
회원 데이터 → 회원 도메인
결제 데이터 → 결제 도메인
주문 데이터 → 주문 도메인
처럼 데이터의 비즈니스 책임을
해당 도메인에 가깝게 둔다.
5. 데이터 메시의 핵심 원칙
데이터 메시의 핵심은
특정 네트워크 구조나 특정 제품이 아니다.
3장에서 본 네 가지 원칙,
즉 도메인 소유권·데이터 제품·셀프서비스 플랫폼·연합형 거버넌스가
함께 있어야 한다.
따라서
데이터 메시
= 모든 것을 완전히 분산
이라고 이해하면 안 된다.
공통 플랫폼이나 중앙 인프라도 충분히 사용할 수 있다.
6. 도메인 토폴로지 패턴
이제 여러 가지 도메인 구조를 살펴보자.
여기서 중요한 주의사항이 있다.
앞으로 나오는
완전 연합형
거버넌스 기반
부분 연합형
가치 사슬 정렬형
큰 단위 도메인
중앙집중형
같은 이름은
데이터 아키텍처 업계에서 반드시 따라야 하는
공식 표준 분류
라고 생각하면 안 된다.
조직의 중앙화와 분산 정도를 이해하기 위한
대표적인 설계 패턴으로 보는 것이 좋다.
7. 완전 연합형 도메인 토폴로지
가장 분산된 구조부터 살펴보자.
완전 연합형에서는
각 도메인이 자신의 데이터를 직접 책임진다.
flowchart LR
m["회원 도메인"] --> mp["회원 데이터 제품"]
p["결제 도메인"] --> pp["결제 데이터 제품"]
o["주문 도메인"] --> op["주문 데이터 제품"]
s["정산 도메인"] --> sp["정산 데이터 제품"]
각 도메인은 상당한 자율성을 가진다.
예를 들어
데이터 구조
품질 기준
데이터 제품
배포 방식
기술 선택
을 자체적으로 결정할 수 있다.
8. 완전 연합형의 장점
가장 큰 장점은
도메인의 자율성이다.
주문 데이터를 가장 잘 이해하는 사람이
주문 도메인 개발자라면,
주문 데이터에 대한 중요한 판단도
그 팀이 하는 것이 자연스럽다.
중앙팀에게 매번 요청하지 않아도 되므로
변경 속도 ↑
도메인 전문성 ↑
자율성 ↑
을 기대할 수 있다.
9. 자율성이 ’마음대로’를 의미하지는 않는다
도메인이 자율적으로 운영된다고 해서
각 팀 마음대로 하면 된다
는 뜻은 아니다.
조직 전체에서 반드시 지켜야 하는
공통 규칙은 존재한다.
예를 들면
개인정보 정책
접근 권한 규칙
보안 정책
메타데이터 규칙
데이터 표준
등이다.
따라서 이상적인 형태는
- 도메인 내부의 세부 구현 — 도메인이 결정
- 회사 공통 원칙 — 모두 준수
다.
이를 연합형 거버넌스 관점으로
이해하면 된다.
10. Peer-to-Peer는 하나의 방식일 뿐이다
완전 분산된 구조에서는
도메인들이 직접 데이터를 주고받을 수도 있다.
회원 ↔ 결제
회원 ↔ 주문
주문 ↔ 배송
주문 ↔ 정산
이런 방식을 Peer-to-Peer라고 생각할 수 있다.
하지만 중요한 점이 있다.
데이터 메시가 Peer-to-Peer 구조를
반드시 요구하는 것은 아니다.
도메인들은 공통 플랫폼이나
이벤트 플랫폼 등을 통해 연결될 수도 있다.
Peer-to-Peer는
가능한 연결 방식 중 하나일 뿐이다.
11. 완전 연합형이 어려운 이유
완전 연합형은 매력적이지만
실제로 운영하려면 조직의 성숙도가 높아야 한다.
도메인이 늘면 연결이 기하급수로 는다
도메인이 서넛이라면 직접 연결도 문제가 아니다.
하지만 수십 개가 되면 관리할 것이 함께 늘어난다.
네트워크
인증
권한
API 버전
이벤트 스키마
장애 대응
데이터 계약
도메인 자율성은 올라가지만 전체 복잡도도 같이 올라간다.
표준이 없으면 통합이 안 된다
같은 회원 ID를 도메인마다 다르게 부를 수 있다.
user_id
member_id
member_no
customer_seq
시간 표현도 제각각이 된다.
2026-09-15
20260915
2026-09-15T10:30:00+09:00
이런 차이가 쌓이면 나중에 데이터를 합칠 수 없다.
도메인마다 데이터 역량이 필요하다
각 도메인이 데이터 제품까지 직접 운영하려면
서비스 개발 능력만으로는 부족하다.
데이터 모델링
파이프라인 구축과 운영
품질 관리
메타데이터 관리
보안과 접근 제어
모든 팀이 이것을 갖추기는 어렵다.
그래서 다음에 볼 구조들이 나온다.
중앙이 무엇을 대신해 줄 것인가의 문제다.
12. 거버넌스 기반 도메인 토폴로지
완전 연합형의 복잡도를 줄이기 위해
중앙 기능을 일부 도입할 수 있다.
핵심 개념은 다음과 같다.
데이터의 비즈니스 책임은 도메인에 두면서,
공통 배포와 거버넌스 기능만 중앙에서 제공한다.
flowchart LR
subgraph OWN["도메인이 데이터 제품까지 책임진다"]
M["회원<br/>+ 회원 데이터 제품"]
P["결제<br/>+ 결제 데이터 제품"]
O["주문<br/>+ 주문 데이터 제품"]
end
HUB["중앙 배포 계층<br/>──────────<br/>배포 경로 · 카탈로그<br/>표준 · 접근 제어"]
M --> HUB
P --> HUB
O --> HUB
HUB --> C["소비자"]
style OWN fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
style HUB fill:#f8fbff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
여기서 중앙은 데이터를 만들지 않는다.
데이터 제품은 각 도메인이 만들고,
중앙은 그것이 지나가는 통로와 규칙을 제공한다.
13. 중앙 배포 계층
예를 들어 주문 데이터가
정산
추천
BI
통계
에서 필요하다고 하자.
직접 연결한다면
주문 → 정산
주문 → 추천
주문 → BI
주문 → 통계
가 된다.
중앙 배포 계층을 사용하면
flowchart LR
o["주문"] --> c["중앙"]
c --> a["정산"]
c --> b["추천"]
c --> d["BI"]
c --> e["통계"]
처럼 만들 수 있다.
14. 중앙 계층에서 제공할 수 있는 기능
공통 계층에서는 다음과 같은 일을 할 수 있다.
스키마 검사
권한 검사
데이터 마스킹
데이터 라우팅
메타데이터 등록
품질 검사
감사 로그
이렇게 하면
모든 도메인이 동일한 기능을 다시 만들 필요가 없다.
15. 중앙화의 가장 큰 위험
중앙 기능이 많아지면
다시 중앙팀이 병목이 될 수 있다.
예를 들어
flowchart LR
n0["도메인팀<br/>‘데이터 하나 추가해주세요’"] --> n2["중앙팀 검토"] --> n3["승인"] --> n4["배포"]
style n2 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
과정이 오래 걸리면
도메인의 자율성과 속도가 사라진다.
따라서 중앙 플랫폼의 이상적인 모습은
중앙팀이 직접 작업
X
중앙팀이 Self-Service 플랫폼 제공
O
에 가깝다.
16. 부분 연합형 도메인 토폴로지
현실에서는 모든 팀의 기술 수준이 같지 않다.
예를 들어
- 신규 서비스팀 — 클라우드 / 자동화에 익숙
- 레거시 서비스팀 — 기존 시스템 유지가 우선
일 수 있다.
이럴 때는 서로 다른 운영 방식을
함께 사용할 수 있다.
- 성숙한 도메인 — 높은 자율성
- 지원이 필요한 도메인 — 중앙 플랫폼 지원
이런 방식을 부분 연합형이라고 이해할 수 있다.
17. 부분 연합형의 위험
운영 방식이 섞이면
책임이 애매해질 수 있다.
예를 들어
- 원본 데이터 — 도메인 팀
- 데이터 제품 — 중앙 데이터팀
이라고 하자.
데이터가 잘못됐을 때
도메인팀
"우리가 준 데이터는 정상입니다."
중앙팀
"원본부터 이상했습니다."
라는 문제가 생길 수 있다.
따라서
누가 무엇을 책임하는지
명확하게 정의해야 한다.
18. 가치 사슬 정렬 도메인 토폴로지
도메인을 개별 기능으로만 보지 않고
하나의 비즈니스 가치 흐름으로 묶는 방식이다.
가치 사슬(Value Chain)은
고객에게 하나의 가치를 제공하기 위해
여러 업무가 이어지는 흐름
이다.
쇼핑몰이라면 이런 흐름이 하나의 가치 사슬이다.
flowchart LR
P["상품"] --> O["주문"] --> PAY["결제"] --> D["배송"] --> S["정산"]
왜 묶는가
같은 사슬 안의 도메인들은 함께 변하기 때문이다.
주문 흐름에 「부분 취소」를 넣는다고 하자.
상품 재고를 되돌려야 하고, 결제를 부분 환불해야 하고,
배송을 멈춰야 하고, 정산 금액을 다시 계산해야 한다.
네 도메인이 같이 움직인다.
이럴 때마다 도메인끼리 계약을 새로 협상하면
기능 하나 넣는 데 몇 달이 걸린다.
무엇을 같이 하는가
묶는다는 것은 경계의 무게를 두 단계로 두는 것이다.
| 같은 가치 사슬 안 | 가치 사슬 밖 | |
|---|---|---|
| 스키마 변경 | 관련 팀이 함께 조율하고 같이 배포한다 | 사전 통보와 호환성 유지 |
| 데이터 공유 | 같은 이벤트 스트림을 공유하기도 한다 | 공개된 계약으로만 |
| 배치 | 같은 계정이나 네트워크 구역에 둔다 | 분리한다 |
| 정책 | 보존 기간·품질 기준을 사슬 단위로 통일한다 | 각자 정한다 |
| 책임 | 사슬 전체를 보는 오너를 둘 수 있다 | 도메인별 |
여기서 오해하기 쉬운 점이 있다.
사슬 안이라고 해서 남의 테이블을 직접 조회해도 된다는 뜻은 아니다.
7장과 12장에서 본 원칙은 그대로다.
달라지는 것은 계약을 바꾸는 절차의 무게다.
밖에서는 사전 통보와 버전 관리가 필요하지만,
안에서는 관련 팀이 모여 합의하고 함께 배포할 수 있다.
19. 여러 사슬이 함께 쓰는 도메인은
모든 도메인이 하나의 사슬에만 속하지는 않는다.
대표적인 예가 회원이다.
flowchart LR
M["회원"]
M --> C["커머스 사슬"]
M --> S["구독 사슬"]
M --> A["광고 사슬"]
style M fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
이런 도메인을 어느 한 사슬에 넣으면 문제가 생긴다.
커머스 사슬에 회원을 넣었다고 하자.
커머스 팀이 회원 스키마를 자기 편한 대로 바꾸기 시작하고,
구독과 광고는 매번 끌려다니게 된다.
그래서 이런 도메인은 어느 사슬에도 넣지 않는다.
- 독립된 공통 도메인으로 둔다
- 모든 사슬에 똑같이 엄격한 계약을 적용한다
- 특정 사슬에만 느슨하게 열어 주지 않는다
마지막 항목이 중요하다.
한 사슬에만 편의를 봐주는 순간 그 사슬에 종속된다.
회원이나 상품처럼 전사가 같은 의미로 써야 하는 데이터는
18장 「마스터 데이터 관리」에서 본 전사 기준 관리 대상이기도 하다.
20. 큰 단위로 나눈 도메인
오래된 대기업에서는
비즈니스 기준보다 기존 시스템이나 조직 기준으로
큰 덩어리가 만들어져 있는 경우가 많다.
예를 들어
한국 플랫폼
일본 플랫폼
광고 플랫폼
커머스 플랫폼
처럼 나뉘어 있을 수 있다.
각 플랫폼 안에는
수십~수백 개 시스템이 들어 있을 수 있다.
21. 큰 단위 도메인의 문제
가장 큰 문제는
비즈니스 경계와 시스템 경계가 일치하지 않는다는 것이다.
예를 들어
- 플랫폼 A — 회원 존재
- 플랫폼 B — 회원 존재
- 플랫폼 C — 회원 존재
라면 이런 문제가 생긴다.
누가 회원의 실제 소유자인가?
어느 회원 데이터가 기준인가?
회원 데이터 품질은 누가 책임지는가?
따라서
현재 시스템 구조가
반드시 올바른 도메인 구조인 것은 아니다.
22. 도메인은 비즈니스 기준으로 나눈다
다음과 같은 기준으로 도메인을 나누는 것은
조심해야 한다.
서버
DB
기존 애플리케이션
개발팀 이름
도메인의 가장 중요한 기준은
비즈니스 책임
비즈니스 능력
데이터 소유권
이다.
물론 현실에서는 조직과 시스템 구조도 고려하지만,
출발점은 비즈니스가 되어야 한다.
23. 공통으로 쓰는 핵심 데이터는 기준이 필요하다
도메인을 나누면 회원이나 상품처럼
여러 도메인이 함께 쓰는 데이터가 남는다.
이런 핵심 데이터를 일관된 기준으로 관리하는 체계를
MDM(Master Data Management) 이라고 한다.
시스템마다 같은 회원을 member_id, user_no, customer_seq로
다르게 부른다면 데이터를 맞추기 어렵다.
교환할 때 쓸 공통 표현을 정해 두기도 하는데
이를 Canonical Model이라고 부른다.
둘 다 18장 「마스터 데이터 관리」에서 자세히 다룬다.
여기서는 토폴로지를 정할 때
도메인에 맡길 데이터와 전사 기준이 필요한 데이터를
구분해야 한다는 점만 기억하면 된다.
24. 중앙집중형 도메인 토폴로지
이번에는 중앙화 정도가 가장 높은 구조다.
flowchart LR
subgraph SRC["도메인은 원본만 넘긴다"]
M["회원"]
P["결제"]
O["주문"]
end
HUB["중앙 데이터 플랫폼<br/>──────────<br/>저장 · 변환 · 품질<br/>메타데이터 · 카탈로그<br/>공통 분석까지"]
M --> HUB
P --> HUB
O --> HUB
HUB --> C["소비자"]
style SRC fill:#fafafa,stroke:#bbb,color:#1a1a1a
style HUB fill:#fff4f4,stroke:#d9534f,stroke-width:3px,color:#1a1a1a
거버넌스 기반과 무엇이 다른가
그림이 비슷해 보이지만 결정적인 차이가 있다.
누가 데이터 제품을 만드는가다.
| 데이터 제품을 만드는 쪽 | 중앙이 하는 일 | 도메인이 하는 일 | |
|---|---|---|---|
| 거버넌스 기반 | 도메인 | 배포 경로와 표준 제공 | 데이터의 의미와 품질 책임 |
| 중앙집중형 | 중앙 | 저장·변환·품질·분석 전부 | 원본을 넘기는 것까지 |
거버넌스 기반에서 중앙은 통로였다.
중앙집중형에서 중앙은 생산자다.
도메인은 원본을 넘기는 데서 역할이 끝난다.
25. 중앙집중형의 장점
각 팀이 같은 기능을
반복해서 만들지 않아도 된다.
예를 들어
Spark
Kafka
Airflow
데이터 카탈로그
데이터 품질 도구
를 각 팀이 하나씩 운영하기보다
공통 플랫폼으로 제공할 수 있다.
장점은
운영 비용 절감
기술 표준화
데이터 재사용
보안 관리 단순화
다.
26. 중앙집중형의 단점
중앙팀으로 일이 집중될 수 있다.
flowchart LR
n0["데이터 변경 요청"] --> n1["중앙팀 대기"] --> n2["개발 지연"]
또한 조직 문화가
데이터 문제
= 중앙 데이터팀 문제
가 되어버릴 수도 있다.
그래서 다음과 같이 책임을 구분하는 것이 좋다.
- 공통 기술 플랫폼 — 플랫폼팀
- 데이터의 비즈니스 의미와 품질 — 도메인팀
27. 중앙화와 분산은 스펙트럼이다
중앙화와 분산을
중앙집중
VS
분산
으로만 보면 안 된다.
실제로는 그 사이에 많은 형태가 있다.
flowchart LR
n0["완전 중앙집중"] --> n1["부분 중앙집중"] --> n2["거버넌스 기반"] --> n3["부분 연합"] --> n4["높은 연합"]
그리고 하나의 회사에서도
여러 형태를 동시에 사용할 수 있다.
예를 들면
- 규제 데이터 — 중앙 관리
- 추천 데이터 — 자율성 높음
- 레거시 — 중앙 지원
- 신규 플랫폼 — Self-Service
같은 형태다.
28. 도메인 크기를 어떻게 정하나
패턴을 골랐다면 남는 질문이 하나 있다.
도메인 하나를 얼마나 크게 잡을 것인가.
판단 기준은 4장 「좋은 경계의 원리」에서 본 것과 같다.
같이 변하는 것은 붙이고(높은 응집도),
남의 내부에 기대지 않는다(낮은 결합도).
여기서는 그 기준을 크기 문제에 적용해 보자.
너무 크면 사일로가 된다
모든 것을 하나에 넣으면
flowchart LR
P["커머스 플랫폼"]
P --> M["회원"]
P --> O["주문"]
P --> PAY["결제"]
P --> D["배송"]
P --> S["정산"]
P --> A["광고"]
style P fill:#fff4f4,stroke:#d9534f,stroke-width:2px,color:#1a1a1a
나눈 의미가 사라지고 다시 거대한 덩어리가 된다.
너무 작으면 통신이 비용이 된다
반대로 이렇게 쪼개면
회원 닉네임
회원 프로필
회원 설정
회원 등급
회원 인증
의존성과 통신이 지나치게 많아진다.
데이터 제품도 마찬가지다.
작게 나누면 독립성과 재사용성은 좋아지지만,
분석 하나를 하려고 회원·배송·주문·결제·정산 제품을
전부 찾아다녀야 한다면 소비자가 힘들어진다.
찾고, 권한 받고, 스키마 이해하고, 조인하고, 품질 확인하는
일이 제품 수만큼 늘어나기 때문이다.
기준은 크기가 아니다
도메인은 몇 개로 나눌지가 아니라
비즈니스 책임과 변경 단위로 정한다.
함께 바뀌는 것이 함께 있으면 크기는 따라온다.
29. 21장 정리
네 가지만 기억하면 된다.
중앙화와 분산은 양자택일이 아니라 스펙트럼이다.
완전 중앙집중과 완전 연합 사이에
여러 형태가 있다.
완전 연합형은 매력적이지만 높은 성숙도를 요구한다.
표준화, 자동화, 셀프서비스 플랫폼,
그리고 각 도메인의 데이터 역량이 함께 있어야 한다.
한 회사 안에서도 데이터마다 다른 방식을 쓸 수 있다.
규제 데이터는 중앙에서,
실험 성격의 데이터는 자율성 높게 운영하는 식이다.
도메인은 비즈니스 책임으로 나눈다.
서버, DB, 기존 애플리케이션, 팀 이름은
출발점이 되기 어렵다.
다음 장에서는 이 구조를 실제로 지탱하는
플랫폼과 조직을 본다.
22장. 플랫폼과 조직
7부 · 실행 — 어디서부터 시작하는가
21장 · 22장 · 23장
아키텍처 가이드 문서를 잘 만들어 공유했다.
API 규칙, 이벤트 규칙, 도메인 경계,
데이터 품질 기준까지 꼼꼼히 정리했다.
여섯 달이 지났다.
문서대로 하는 팀은 거의 없다.
좋은 아키텍처 문서를 만들었다고
조직이 그대로 움직이지는 않는다.
이 장에서는 기술 바깥의 문제를 다룬다.
도메인 팀과 플랫폼 팀의 역할,
팀 사이의 상호작용 방식,
그리고 좋은 방법을 조직에 정착시키는 법이다.
플랫폼의 목표는 대신 해주는 것이 아니라
다른 팀이 스스로 할 수 있게 만드는 것이다.
1. 좋은 기술만으로 조직은 바뀌지 않는다
여기까지는 주로 기술을 이야기했다.
하지만 데이터 아키텍처를 바꾸는 것은
기술만의 문제가 아니다.
다음 요소가 함께 바뀌어야 한다.
기술
+
프로세스
+
조직
+
사람
+
문화
Kafka를 설치하고
API Gateway를 도입했다고 해서
회사 전체 아키텍처가 자동으로 좋아지는 것은 아니다.
2. 도메인 팀
도메인 팀은 특정 비즈니스 영역을 책임진다.
예를 들면:
회원 팀
결제 팀
주문 팀
배송 팀
정산 팀
도메인 팀은 단순히 프로그램만 개발하는 것이 아니라
자신의 비즈니스 영역과 데이터에 대한 책임을 가진다.
예를 들어 주문 팀이라면
주문 비즈니스 규칙
주문 애플리케이션
주문 데이터 모델
주문 데이터 품질
주문 API / Event
주문 Data Product
등을 책임질 수 있다.
핵심은
도메인 데이터의 주인은
해당 비즈니스를 가장 잘 이해하는 도메인 팀이다.
라는 생각이다.
3. 중앙 데이터 플랫폼 팀
도메인 팀이 자기 데이터를 책임진다고 해서
모든 기술을 직접 만들어야 하는 것은 아니다.
예를 들어 주문팀마다
Kafka
데이터 파이프라인
CI/CD
모니터링
데이터 카탈로그
저장소
를 처음부터 직접 구축한다면
중복 작업이 너무 많아진다.
그래서 중앙 데이터 플랫폼 팀이
공통 기반을 제공할 수 있다.
4. 플랫폼 팀의 목표는 대신 해주는 것이 아니다
데이터 제품이 몇 개 없을 때는
중앙팀이 직접 많은 작업을 처리할 수 있다.
하지만 팀이 늘어나면 이렇게 된다.
flowchart LR
M["회원팀"] --> HUB
P["결제팀"] --> HUB
D["배송팀"] --> HUB
S["정산팀"] --> HUB
R["추천팀"] --> HUB
A["광고팀"] --> HUB
HUB["중앙 데이터팀"]
style HUB fill:#fff4f4,stroke:#d9534f,stroke-width:3px,color:#1a1a1a
들어오는 요청도 비슷하다.
"Kafka Topic 만들어 주세요."
"DB 만들어 주세요."
"권한 주세요."
"Dashboard 만들어 주세요."
결국 플랫폼 팀이 새로운 병목이 된다.
그래서 역할을 바꾼다
플랫폼 팀은 모든 일을 대신 처리하는 팀이 아니라
다른 팀이 안전하게 스스로 처리할 수 있도록
기반을 만드는 팀이다.
flowchart LR
DT["도메인 팀"] --> SP["Self-Service Platform"]
SP --> T["Topic 생성"]
SP --> A2["권한 생성"]
SP --> M2["모니터링 연결"]
SP --> ST["저장소 생성"]
SP --> DP["배포"]
style SP fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
도메인 팀이 매번 티켓을 만들지 않고
일반적인 데이터 작업을 직접 할 수 있게 하는 것이다.
플랫폼이 제공할 수 있는 것은 이런 것들이다.
데이터 저장소 생성
파이프라인 생성
접근 권한 요청
모니터링 연결
카탈로그 등록
품질 검사 설정
자유롭게 하라는 뜻은 아니다
셀프서비스라고 해서 아무렇게나 해도 된다는 말이 아니다.
오히려 반대다.
올바른 방법을 가장 쉽게 쓸 수 있게 만드는 것
이것이 핵심이다.
5. 인프라·클라우드 역량
조직에는 보다 기초적인 기술 기반도 필요하다.
예를 들어:
Cloud
Compute
Network
Storage
Kubernetes
IAM
Monitoring
비용 관리
등이다.
조직에 따라
인프라 팀
데이터 플랫폼 팀
을 따로 둘 수도 있고,
작은 조직에서는 하나의 플랫폼 조직이
함께 담당할 수도 있다.
중요한 것은
팀 이름보다 책임과 인터페이스가 명확한가
이다.
또한
flowchart LR
n0["Domain Team"] --> n1["Platform Team"] --> n2["Infra Team"]
을 반드시 수직적인 조직 계층으로 이해할 필요도 없다.
서로 서비스를 제공하고 협업하는 관계라고 보는 편이 낫다.
6. Team Topologies
팀을 어떻게 나눌지 이야기할 때 자주 인용되는 모델이 있다.
Team Topologies는 팀의 종류와 팀 사이의 관계를 다룬
책이자 그 모델의 이름이다.
출발점은 오래된 관찰 하나다.
시스템 구조는 결국
그것을 만든 조직의 소통 구조를 닮는다.
하나의 서비스를 세 팀이 나눠 만들면
그 서비스는 세 조각으로 갈라지기 쉽다.
거꾸로 말하면, 아키텍처를 바꾸고 싶으면
팀 구조도 함께 봐야 한다는 뜻이다.
이 모델은 팀을 네 종류로 나눈다.
| 팀 유형 | 한 줄로 |
|---|---|
| Stream-Aligned | 하나의 비즈니스 흐름을 처음부터 끝까지 책임진다 |
| Platform | 다른 팀이 쓸 공통 기반을 제공한다 |
| Enabling | 다른 팀의 역량을 키워 주고 빠진다 |
| Complicated Subsystem | 전문성이 아주 높은 부분을 맡는다 |
대부분의 팀은 첫 번째다.
나머지 셋은 첫 번째 팀이 빨리 움직이도록 돕기 위해 존재한다.
하나씩 보자.
7. Stream-Aligned Team
특정 비즈니스 가치 흐름을
지속적으로 책임지는 팀이다.
예를 들면:
회원 팀
결제 팀
주문 팀
배송 팀
등을 생각할 수 있다.
단순히 API 하나만 만드는 것이 아니라
해당 영역의 비즈니스 가치를 end-to-end로 책임한다.
도메인 팀과 상당히 비슷하게 생각할 수 있다.
8. Enabling Team
Enabling Team은 다른 팀이
새로운 기술이나 업무 방식을 익히도록 돕는다.
예를 들어:
DDD 전문가
Kafka 전문가
데이터 모델링 전문가
보안 전문가
등이 다른 팀을 지원할 수 있다.
중요한 것은 일을 계속 대신해주는 것이 아니다.
목표는
교육
코칭
가이드
컨설팅
을 통해 다른 팀이
결국 스스로 할 수 있게 만드는 것이다.
9. Complicated Subsystem Team
일반적인 개발 역량만으로 다루기 어려운
전문적인 시스템을 담당하는 팀이다.
예를 들어:
영상 인코딩 엔진
검색 엔진
특수 추천 알고리즘
고성능 처리 엔진
복잡한 ML 시스템
같은 영역이다.
해당 기술에 높은 전문성이 필요한 경우
별도의 전문 팀을 두는 것이 더 효과적일 수 있다.
10. Platform Team
Platform Team은 여러 Stream-Aligned Team이
공통으로 사용할 기술 기반을 제공한다.
예를 들면:
CI/CD
배포 플랫폼
데이터 플랫폼
관측성
클라우드 환경
개발자 플랫폼
등이다.
Platform Team의 중요한 목표는
다른 팀이 인프라와 기술의 복잡성을 덜 신경 쓰고
비즈니스 개발에 집중하도록 만드는 것
이다.
11. 중요한 것은 팀 사이의 관계다
팀을 네 종류로 나누는 것이 전부가 아니다.
더 중요한 것은 팀끼리 어떻게 주고받느냐다.
같은 두 팀이라도 관계를 맺는 방식에 따라
일하는 속도가 크게 달라진다.
이 모델은 그 방식을 세 가지로 나눈다.
Collaboration — 한동안 같이 일한다
두 팀이 바짝 붙어 함께 만든다.
매일 이야기하고 같이 설계한다.
새 영역을 개척할 때, 아직 무엇을 만들지 모를 때 쓴다.
대신 비용이 크다.
두 팀의 시간이 모두 들어가고 책임 경계도 흐려진다.
그래서 Collaboration은 한시적으로 쓴다.
X-as-a-Service — 만들어 둔 것을 가져다 쓴다
한 팀이 만든 것을 다른 팀이 문서 보고 알아서 쓴다.
서로 이야기할 일이 거의 없다.
플랫폼 팀이 도메인 팀을 대하는 기본 방식이다.
앞에서 본 셀프서비스가 바로 이 모드다.
Facilitation — 도와주고 빠진다
한 팀이 다른 팀을 일정 기간 도와 역량을 키워 준다.
그리고 손을 뗀다.
Enabling 팀의 방식이다.
관계는 고정이 아니다
이 셋이 상황에 따라 바뀐다는 점이 핵심이다.
flowchart LR
C["Collaboration<br/>──────────<br/>플랫폼 팀과 도메인 팀이<br/>한동안 함께 만든다"]
X["X-as-a-Service<br/>──────────<br/>자리를 잡으면<br/>셀프서비스로 넘긴다"]
C -- "형태가 잡히면" --> X
style C fill:#fafafa,stroke:#bbb,color:#1a1a1a
style X fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
새 기능을 만들 때는 플랫폼 팀과 도메인 팀이
한동안 Collaboration으로 함께 만든다.
형태가 잡히면 셀프서비스로 넘기고 손을 뗀다.
Collaboration이 끝나지 않고 계속된다면
그건 아직 플랫폼으로 만들지 못했다는 신호다.
즉 목표는 조직 상자를 예쁘게 그리는 것이 아니라
팀 간 의존성을 줄이고
비즈니스 변화가 빠르게 흐르도록 만드는 것
이다.
12. 조직에 좋은 패턴을 어떻게 정착시킬까?
좋은 아키텍처 문서를 만들었다고 하자.
API 규칙
Event 규칙
도메인 경계
데이터 품질 기준
을 모두 정리했다.
하지만 문서를 만든 것만으로
개발팀이 자동으로 따라오는 것은 아니다.
따라서 새로운 방식을 실제 조직에
정착시키는 과정이 필요하다.
13. Playbook
Playbook은 원래 스포츠에서 쓰는 말이다.
상황별 작전을 모아 둔 책이다.
여기서는
자주 마주치는 상황마다
“이럴 땐 이렇게 하더라“를 모아 둔 문서
를 뜻한다.
앞 절에서 문서를 만들어도 따라오지 않는다고 했는데
이것도 문서 아닌가 싶을 수 있다.
성격이 다르다.
| 무엇을 적나 | |
|---|---|
| 규칙 문서 | 반드시 이렇게 해라 |
| Playbook | 이런 상황에는 이런 선택지가 있고, 우리는 이렇게 해왔다 |
강제가 아니라 먼저 해본 사람의 기록이다.
예를 들어 API Playbook에는 다음과 같은 내용이 들어갈 수 있다.
언제 사용하는가?
Timeout은 어떻게 하는가?
Retry는 언제 하는가?
Idempotency는 어떻게 보장하는가?
Circuit Breaker는 필요한가?
이벤트 Playbook에는
이벤트 이름은 어떻게 정하는가?
Schema는 어떻게 관리하는가?
중복 처리는 어떻게 하는가?
재처리는 어떻게 하는가?
실패한 이벤트는 어떻게 처리하는가?
등을 담을 수 있다.
새 팀이 API를 만들 때
Timeout과 Retry를 처음부터 고민하지 않아도 된다.
이미 겪은 사람이 정리해 뒀기 때문이다.
다만 Playbook도 결국 문서다.
읽지 않으면 소용이 없고,
읽어도 따를지 말지는 각 팀이 정한다.
그래서 남는 질문이 있다.
조직의 표준을 어디까지 강제할 것인가.
14. 기술 표준은 필요하지만 너무 강하면 안 된다
조직이 커지면 다음과 같은 상황이 생길 수 있다.
A팀 → Kafka
B팀 → RabbitMQ
C팀 → NATS
D팀 → Redis Streams
각 팀의 결정에는 이유가 있을 수 있다.
하지만 기술 종류가 지나치게 많아지면
운영
모니터링
장애 대응
교육
채용
보안
비용이 증가한다.
그래서 조직에서는
기본적으로 지원할 기술을 정할 수 있다.
하지만 표준화가 지나치면
특수한 요구사항을 해결할 수 없게 된다.
따라서 목표는
표준화
+
자율성
사이의 균형이다.
15. Golden Path
실무에서는 개발자가
가장 안전하고 쉽게 사용할 수 있도록 만들어 놓은
기본 경로를 Golden Path라고 부르기도 한다.
예를 들어:
- 새 API 생성 — 표준 프로젝트 템플릿 사용
- 새 서비스 배포 — 표준 CI/CD 사용
- 이벤트 생성 — 표준 Schema Registry 사용
- 모니터링 — 기본 Dashboard 자동 생성
처럼 만들 수 있다.
중요한 것은
올바른 방법을 문서로 강요하는 것보다
올바른 방법이 가장 쉬운 방법이 되게 만드는 것
이다.
Golden Path라는 용어 자체보다
이 사고방식을 이해하는 것이 중요하다.
Playbook, Blueprint와 어떻게 다른가
이 책에 비슷해 보이는 말이 셋 나온다.
| 무슨 말을 하는가 | 형태 | |
|---|---|---|
| Playbook | 이런 상황에는 이렇게 하더라 | 문서 |
| Blueprint | 이렇게 구성하면 된다 | 미리 맞춰 둔 한 벌의 구성 |
| Golden Path | 이 길로 가면 된다 | 그 구성에 이르는 절차와 도구 |
집 짓기에 비유하면 이렇다.
- Playbook — 집 지을 때 주의할 점을 적어 둔 노트
- Blueprint — 표준 설계도
- Golden Path — 그 설계도로 집을 짓는 표준 공정
셋은 서로 겹친다.
실제로 Golden Path의 첫 걸음이 Blueprint를 고르는 일이다.
위 그림의 「템플릿 선택」이 그것이다.
Blueprint는 19장과 부록 A 「클라우드 랜딩 존과 Blueprint」에서 다뤘다.
셋 중 하나만 고른다면 Golden Path 쪽이 강하다.
문서는 읽지 않을 수 있고 설계도는 안 쓸 수 있지만,
길은 그냥 따라가게 되기 때문이다.
예를 들어 새로운 데이터 제품을 만든다면
이런 표준 흐름을 제공할 수 있다.
flowchart LR
n0["템플릿 선택"] --> n1["Repository 생성"] --> n2["파이프라인 생성"] --> n3["권한 정책 적용"] --> n4["모니터링 연결"] --> n5["카탈로그 등록"] --> n6["배포"]
그러면 개발자는 플랫폼 내부의 복잡성을 다 알지 못해도 된다.
참고로 Golden Path는 Data Mesh의 공식 원칙이 아니다.
셀프서비스 플랫폼을 구현하는 실무적인 방법 중 하나다.
16. 자동화할 수 있는 거버넌스는 자동화한다
사람이 모든 아키텍처 규칙을
매번 수동으로 검토하면 비용이 커진다.
예를 들어 다음과 같은 규칙이 있다고 하자.
API Schema 검사
Event Schema 검사
도메인 의존성 검사
보안 정책 검사
일부는 CI/CD에서 자동화할 수 있다.
flowchart LR
n0["Commit"]
n1["CI"]
n2["Architecture Test"]
n3["Schema Validation"]
n4["Security Check"]
n5["Lint"]
n0 --> n1
n1 --> n2
n1 --> n3
n1 --> n4
n1 --> n5
실무에서는 이러한 접근을Governance as Code와 비슷한 개념으로 설명하기도 한다.
핵심은 이름이 아니라
사람이 반복해서 확인하는 규칙 중
자동화할 수 있는 것은 자동화하자.
는 것이다.
거버넌스는 중앙 통제가 아니다
거버넌스라는 말을 들으면
승인·규정·통제·감사를 먼저 떠올리기 쉽다.
하지만 목적은 규칙을 늘리는 것이 아니라
여러 팀이 안전하고 일관된 방법으로
데이터를 쓸 수 있게 만드는 것
이다.
전사에서 정하는 것은 최소한으로 둔다.
개인정보 취급 기준
데이터 등급
접근 권한 원칙
품질 표현 방법
공통 메타데이터
보존 정책
그 안에서 각 도메인은 자율적으로 움직인다.
이 방식을 Federated Governance라고 부른다.
결정 권한을 어떻게 나누는지는 14장에서,
거버넌스 체계 전반은 16장 「거버넌스」에서 다뤘다.
반복 가능한 규칙일수록 자동으로 적용하기 좋다.
민감정보가 포함되면 자동 태깅
특정 등급 데이터는 외부 접근 차단
품질 기준 미달 시 배포 차단
모든 데이터 제품에 Owner 등록 요구
다만 전부 자동화할 수는 없다.
조직 간 우선순위나 새 정책처럼
사람의 판단이 필요한 영역은 남는다.
17. 처음부터 모든 팀을 바꾸려고 하지 않는다
회사에 새로운 아키텍처 방향을 적용한다고 해서
모든 시스템을 같은 날 바꿀 수는 없다.
팀마다 상황이 다르다.
- 신규 시스템 — 새로운 방식 적용이 쉬움
- 오래된 레거시 — 점진적인 변경 필요
- 장애가 많은 시스템 — 먼저 안정화가 필요할 수 있음
따라서
전체적인 방향은 일관되게 유지하되
실제 전환 속도는 상황에 맞게 조정할 수 있다.
18. 성공 사례와 실패 사례를 모두 공유한다
한 팀이 좋은 방법을 찾았다고 해보자.
flowchart LR
n0["문제 해결"]
n1["경험 정리"]
n2["Playbook 반영"]
n3["다른 팀 사용"]
n0 --> n1
n1 --> n2
n2 --> n3
이렇게 조직 전체의 지식으로 만들 수 있다.
실패 사례도 중요하다.
예를 들어
이 기능을 이벤트 기반으로 바꿨는데
순서 보장 때문에 오히려 훨씬 복잡해졌다.
라는 경험은 매우 가치 있다.
좋은 아키텍처 조직은
성공만 공유하는 조직
보다
성공과 실패에서
둘 다 학습하는 조직
에 가깝다.
19. Consumer의 요구를 이해하면서 Producer를 안정화한다
데이터 제품을 만들 때
사용자, 즉 Consumer의 요구는 매우 중요하다.
사용자가 무엇을 필요로 하는지 모르면
좋은 데이터 제품을 만들 수 없다.
하지만 Consumer가 빠르게 증가하기 전에
Producer 측도 안정적으로 만들어야 한다.
예를 들어 하나의 매출 데이터 제품을
경영 리포트
정산
추천
머신러닝
광고 분석
실시간 대시보드
에서 동시에 사용한다고 하자.
데이터 제품의 품질이 불안정하면
모든 Consumer가 영향을 받는다.
따라서 올바른 접근은
Consumer의 요구를 지속적으로 반영하면서
사용 범위를 크게 확장하기 전에
데이터 제품의 품질과 안정성을 확보하는 것이다.
20. 데이터 품질을 운영에 포함한다
데이터 품질은
좋은 데이터를 만들자.
라는 구호로 끝나서는 안 된다.
실제로 측정할 수 있어야 한다.
예를 들어
NULL 비율
중복률
갱신 지연
스키마 변경
허용 범위
참조 무결성
비즈니스 규칙
등을 확인할 수 있다.
그리고 품질 기준을 위반하면
경고를 보내거나,
파이프라인을 중단하거나,
사용자를 알리거나,
배포를 차단할 수도 있다.
즉,
데이터 품질은 개발 이후 확인하는 작업이 아니라
데이터 제품 운영의 일부다.
21. 품질의 책임은 도메인과 플랫폼이 나눠 가진다
데이터 품질을 중앙팀이 전부 정의하기는 어렵다.
결제 금액이 음수가 될 수 있는가?
이 질문은 플랫폼팀보다 결제 도메인팀이 훨씬 잘 안다.
반대로 이런 질문은 팀마다 다르면 곤란하다.
품질을 어떤 지표로 표현할 것인가?
기준에 미달하면 배포를 막을 것인가, 경고만 할 것인가?
그래서 이렇게 나눈다.
| 중앙 · 거버넌스가 정한다 | 도메인이 정한다 |
|---|---|
| 품질을 재는 방식 | 구체적인 품질 규칙 |
| 공통 기준과 표현 방법 | 그 데이터의 비즈니스 의미 |
| 모니터링 도구 | 목표로 삼을 수준 |
| 위반했을 때의 절차 | 문제가 생겼을 때의 해결 |
한 줄로 줄이면 이렇다.
중앙은 「어떻게 재고 무엇을 할지」를 정하고,
도메인은 「무엇이 옳은 값인지」를 정한다.
앞에서 본 Federated Governance가
품질에 적용된 모습이다.
22. 데이터 거버넌스 조직
조직이 커지면
도메인 사이의 충돌도 늘어난다.
예를 들어
flowchart LR
PAY["결제팀<br/>‘이 컬럼은 더 이상<br/>사용하지 않겠습니다’"]
SET["정산팀<br/>‘그 컬럼을 정산에서<br/>사용하고 있습니다’"]
CONFLICT["⚡ 충돌<br/>조정할 주체가 없다"]
PAY --> CONFLICT
SET --> CONFLICT
style CONFLICT fill:#fff4f4,stroke:#d9534f,stroke-width:2px,color:#1a1a1a
같은 일이 발생한다.
이런 일이 생기는 이유는 둘이다.
하나, 결제팀은 누가 그 컬럼을 쓰는지 몰랐다.
계보와 데이터 계약이 있으면 지우기 전에 알 수 있다.
16장 「거버넌스」에서 다룬 장치들이다.
둘, 알고도 합의가 안 될 수 있다.
결제팀은 더 유지할 수 없고 정산팀은 당장 못 옮긴다면
둘 중 누구도 결정을 내릴 수 없다.
앞쪽은 도구로 풀지만 뒤쪽은 사람이 풀어야 한다.
결정할 자리를 미리 만들어 둔다
거버넌스 조직은 누가 결정하는가를 미리 정해 두는 것이다.
보통 두 층으로 둔다.
| 무엇을 다루나 | 예 | |
|---|---|---|
| 도메인 수준 | 관련 팀끼리 풀 수 있는 문제 | 컬럼 삭제 일정, 스키마 변경, 품질 기준 |
| 전사 수준 | 도메인끼리 못 정하거나 회사 전체에 영향이 있는 문제 | 공통 정책, 데이터 전략, 투자 우선순위 |
대부분은 도메인 수준에서 끝난다.
전사로 올라가는 일은 예외여야 한다.
앞의 충돌은 이렇게 풀린다
flowchart LR
C1["데이터 계약의 통보 기간<br/>──────────<br/>결제팀이 먼저 알린다"]
C2["도메인 회의체<br/>──────────<br/>일정을 조정한다"]
C3["전사 수준<br/>──────────<br/>여기서 결정한다"]
C1 -- "기간 안에 못 옮기면" --> C2
C2 -- "합의가 안 되면" --> C3
style C1 fill:#f2fbf4,stroke:#4caf50,color:#1a1a1a
style C3 fill:#fff4f4,stroke:#d9534f,color:#1a1a1a
계약에 변경 통보 기간이 정해져 있으면
결제팀은 정해진 기간 전에 알린다.
정산팀이 그 안에 옮기면 거기서 끝난다.
못 옮기면 도메인 회의체에서 일정을 조정하고,
거기서도 안 되면 전사 수준으로 올린다.
중요한 것은 마지막 단계까지 가는 일이 드물다는 점이 아니라
막혔을 때 갈 곳이 있다는 점이다.
조직도를 예쁘게 그리는 것보다
막혔을 때 어디로 가는지 모두가 아는 것이 중요하다.
23. 데이터 리터러시가 필요하다
좋은 데이터 플랫폼을 만들었다고 해서
자동으로 데이터 주도 조직이 되는 것은 아니다.
사람들이 데이터를 이해하지 못하면
좋은 플랫폼도 제대로 활용되지 않는다.
데이터 리터러시(Data Literacy) 란
데이터를 읽고, 이해하고, 질문하고,
적절하게 해석하고 사용할 수 있는 능력
이라고 이해하면 된다.
예를 들어
매출이라는 지표가 정확히 무엇인지
DAU의 정의가 무엇인지
평균값이 왜곡될 수 있는 상황은 무엇인지
데이터가 어느 기간을 나타내는지
등을 이해할 수 있어야 한다.
교육만으로 풀려고 하지 않는다
여기서 흔한 실수가 있다.
리터러시를 교육 문제로만 보고
전사 교육을 몇 번 하고 끝내는 것이다.
하지만 「매출」의 정의를 수백 명이 외우고 있게 만드는 것보다
외우지 않아도 되게 만드는 편이 쉽다.
앞에서 본 장치들이 그 일을 한다.
| 무엇이 | 무엇을 대신해 주나 |
|---|---|
| 시맨틱 계층 | 「매출」을 고르면 계산식이 딸려 온다. 외울 필요가 없다 |
| 데이터 카탈로그 | 데이터 옆에 정의와 소유자가 붙어 있다. 물어볼 필요가 없다 |
| 비즈니스 용어집 | 같은 말을 같은 뜻으로 쓰게 한다 |
Golden Path와 같은 생각이다.
올바르게 이해하는 것이 가장 쉬운 길이 되게 만든다.
그래도 사람이 배워야 하는 것
전부를 도구로 옮길 수는 없다.
평균이 왜곡되는 상황, 표본의 한계,
상관관계와 인과관계의 차이 같은 것은
도구가 대신 판단해 주지 못한다.
이 부분이 앞에서 본 Enabling 팀의 몫이다.
일정 기간 도와 역량을 키워 주고 빠진다.
정리하면 이렇다.
| 리터러시를 높이는 방법 | 무엇으로 |
|---|---|
| 알아야 할 것을 줄인다 | 시맨틱 계층 · 카탈로그 · 용어집 |
| 남은 것을 가르친다 | Enabling 팀 · 교육 |
결국 데이터 주도 문화는
좋은 데이터와 좋은 플랫폼과 좋은 거버넌스에
데이터를 이해하는 사람이 더해져야 만들어진다.
그리고 그 마지막 조각은
가르치는 것만으로는 채워지지 않는다.
24. 아키텍처는 한 번 만들고 끝나는 것이 아니다
아키텍처를 완성된 설계도라고 생각하기 쉽다.
하지만 실제 비즈니스는 계속 변한다.
새로운 상품
새로운 국가
새로운 규제
새로운 비즈니스 모델
기술도 변한다.
새로운 DB
새로운 클라우드 서비스
AI
새로운 데이터 처리 기술
따라서 아키텍처도 계속 진화해야 한다.
flowchart LR
n0["패턴 정의"]
n1["실제 적용"]
n2["경험 축적"]
n3["문제 발견"]
n4["패턴 개선"]
n5["플랫폼 개선"]
n0 --> n1 --> n2 --> n3 --> n4 --> n5
n5 -- "다시 적용" --> n1
25. 22장 정리
이 장의 내용을 조직 관점에서 정리하면 이렇다.
| 역할 | 책임 |
|---|---|
| 도메인 · Stream-Aligned 팀 | 비즈니스와 데이터를 책임진다 |
| Platform 팀 | 공통 복잡성을 줄여 주는 기반을 제공한다 |
| Enabling 팀 | 지식과 역량을 전파한다 |
| Complicated Subsystem 팀 | 고도의 전문 영역을 맡는다 |
그리고 플랫폼의 목표는
"우리에게 요청하세요."
가 아니라
"여러분이 직접 할 수 있도록
쉬운 환경을 제공하겠습니다."
에 가깝다.
네 가지만 기억하면 된다.
좋은 문서를 만들었다고 조직이 따라오지 않는다.
기술·프로세스·조직·사람·문화가 함께 움직여야 한다.
플랫폼 팀이 대신 해주기 시작하면 새로운 병목이 된다.
목표는 다른 팀이 스스로 할 수 있게 만드는 것이다.
올바른 방법을 문서로 강요하는 것보다
올바른 방법이 가장 쉬운 방법이 되게 만드는 편이 낫다.
Golden Path와 자동화된 가드레일이 그 수단이다.
처음부터 모든 팀을 바꾸려 하지 않는다.
한 팀에서 성공 사례를 만들고 그것을 퍼뜨린다.
마지막으로, 여기까지 온 과정을 한 장으로 보면 이렇다.
flowchart TB
S1["경계<br/>──────────<br/>비즈니스 영역을 도메인으로 나눈다"]
S2["연결<br/>──────────<br/>요구사항에 따라 API · Event · Batch를 고른다"]
S3["제품<br/>──────────<br/>반복해서 쓰는 데이터는 Data Product로 제공한다"]
S4["신뢰<br/>──────────<br/>Metadata · 품질 · 보안 · Owner를 관리한다"]
S5["플랫폼<br/>──────────<br/>공통 기술은 Platform이 제공하고<br/>도메인 팀이 Self-Service로 쓴다"]
S6["조직<br/>──────────<br/>팀 구조와 협업 방식도 아키텍처에 맞게 바뀐다"]
S1 --> S2 --> S3 --> S4 --> S5 --> S6
style S1 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S2 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S3 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S4 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S5 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style S6 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
다음 장에서는 이 모든 것을
어디서부터 시작할지 본다.
23장. 실행 로드맵
7부 · 실행 — 어디서부터 시작하는가
21장 · 22장 · 23장
작은 데이터 제품에서 시작해 플랫폼·거버넌스·DataOps로 확장하기
앞 장까지 우리는 데이터 전략, 데이터 제품, 도메인,
메타데이터, 데이터 품질, MDM, 거버넌스 등
데이터 아키텍처를 구성하는 여러 개념을 살펴봤다.
하지만 개념을 이해하는 것과
실제 회사에서 구현하는 것은 다른 문제다.
실무에서는 이런 질문을 만나게 된다.
데이터 플랫폼부터 만들어야 할까?
어떤 데이터를 먼저 다뤄야 할까?
중앙 데이터팀이 모든 것을 관리해야 할까?
각 서비스팀이 자신의 데이터를 직접 관리해야 할까?
데이터 제품이 많아지면 누가 품질을 책임져야 할까?
거버넌스를 강화하면 개발 속도가 느려지는 것은 아닐까?
이번 장에서는 지금까지 배운 이론을
실제 조직과 시스템에 적용하는 방법을 살펴본다.
이 장 전체를 관통하는 핵심 원칙은 다음과 같다.
전체적인 방향은 알고 있되,
가치 있는 작은 문제부터 실행하고
그 경험을 플랫폼·표준·거버넌스로 발전시킨다.
1. 기술이 아니라 비즈니스에서 시작한다
여기까지 보면 특정 기술 하나가
모든 문제를 해결할 수 없다는 것을 알 수 있다.
그래서 필요한 것이 데이터 전략이다.
전략의 시작이 이런 말이 되어서는 안 된다.
Data Mesh를 도입하자.
Data Lake를 만들자.
Kafka를 사용하자.
출발점은 회사가 풀려는 문제다.
사용자 이탈률을 줄이고 싶다.
상품별 매출을 빠르게 파악하고 싶다.
이상 결제를 빠르게 탐지하고 싶다.
정산 오류를 줄이고 싶다.
순서는 이렇게 간다.
flowchart LR
n0["비즈니스 목표"] --> n1["데이터가 해야 할 역할"] --> n2["현재 데이터 환경 파악"] --> n3["목표 데이터 환경 정의"] --> n4["조직과 책임 설계"] --> n5["거버넌스 설계"] --> n6["아키텍처 설계"] --> n7["기술 선택"]
예를 들어 「사용자 이탈 감소」가 목표라면
먼저 필요한 데이터를 생각한다.
접속 데이터
조회 데이터
결제 데이터
주문 데이터
그다음 이 데이터로 어떤 분석과 서비스를 만들지 정하고,
마지막에 필요한 플랫폼과 기술을 고른다.
Kafka도 데이터 레이크도 AI도
문제를 풀기 위한 수단일 뿐이다.
2. 큰 방향은 정하되 작게 실행한다
반대 방향의 실수도 있다.
완벽한 전략을 만들겠다고 몇 달 동안 문서만 쓰는 것이다.
작은 활용 사례부터 시작해 실제 효과를 확인하는 편이 낫다.
flowchart LR
n0["작은 영역 선정"] --> n1["실제 데이터 적용"] --> n2["효과 측정"] --> n3["문제 발견"] --> n4["전략 보완"] --> n5["다음 영역으로 확대"]
그렇다고 방향 없이 가면 안 된다
「작게 시작하라」를 잘못 읽으면
큰 그림 없이 작은 프로젝트만 계속 만들면 된다고 생각하기 쉽다.
그렇게 하면 이런 것들이 쌓인다.
팀 A의 데이터 플랫폼
팀 B의 별도 ETL
팀 C의 별도 데이터 모델
또 다른 사일로가 만들어진다.
그래서 장기적으로 어디로 갈지에 대한
목표 상태(Target State) 는 필요하다.
도메인별 데이터 제품 운영
Self-Service Data Platform
데이터 카탈로그
자동 품질 관리
공통 거버넌스
DataOps
다만 이 모두를 첫 프로젝트에서 만들려고 해서는 안 된다.
flowchart LR
cur["현재 상태"] --> p["작은 프로젝트"] --> v["검증"] --> imp["개선"] --> ext["확장"]
cur -. "방향" .-> goal["목표 아키텍처"]
style goal fill:#f8fbff,stroke:#4a90e2,stroke-dasharray: 5 5,color:#1a1a1a
큰 방향을 보고 작은 단위로 실행한다.
이 장의 나머지는 이 문장을 푸는 것이다.
3. 첫 번째 유스케이스를 선택한다
모든 데이터 문제를 동시에 해결할 수는 없다.
그래서 먼저
가치 있는 유스케이스 하나를 선택해야 한다.
예를 들어 커머스 서비스라면
판매자 매출 분석
사용자 이탈 예측
실시간 인기 상품 랭킹
이상 결제 탐지
추천 시스템
정산 자동화
등이 후보가 될 수 있다.
첫 번째 프로젝트는
너무 어렵지도 않고 너무 사소하지도 않아야 한다.
비즈니스 가치가 있고,
범위가 어느 정도 명확하며,
필요한 데이터를 확보할 수 있고,
결과를 비교적 빠르게 확인할 수 있는 문제가 좋다.
예를 들어
“모든 회사 데이터를 통합하자.”
보다는
“결제·주문·배송 데이터를 이용해
판매자별 일 매출을 정확하게 계산하자.”
가 훨씬 좋은 시작점이다.
4. 첫 번째 데이터 제품을 만든다
유스케이스가 정해졌다면
이제 실제 사용 가능한 데이터 제품(Data Product) 을 만든다.
데이터 제품은 단순한 테이블 하나를 의미하지 않는다.
사용자가 실제로 신뢰하고 사용할 수 있는
데이터 제공 단위라고 생각하면 된다.
예를 들어 판매자 매출 데이터 제품이라면
flowchart TD
n0["결제 데이터"]
n2["주문 데이터"]
n4["배송 데이터"]
n5["정제 및 계산"]
n6["판매자 매출 데이터 제품"]
n7["리포트 / 정산 / 분석"]
n0 --> n5
n2 --> n5
n4 --> n5
n5 --> n6
n6 --> n7
이 될 수 있다.
여기에는 데이터뿐 아니라
데이터 의미,
품질 기준,
갱신 주기,
책임자,
접근 권한
같은 정보도 함께 존재하는 것이 좋다.
5. 데이터 처리 계층을 나눌 수 있다
원본 데이터를 바로 분석에 사용하는 것은
여러 문제를 만든다.
그래서 데이터가
수집되고,
정제되고,
비즈니스 의미가 추가되는
단계를 나누는 경우가 많다.
대표적인 예가 Bronze / Silver / Gold를 쓰는
Medallion Architecture다. 14장에서 다뤘다.
이 구조가 유일한 정답은 아니다.
조직에 따라
flowchart LR
n0["Raw"] --> n1["Clean"] --> n2["Curated"]
같은 다른 이름과 구조를 사용할 수도 있다.
핵심은 이름이 아니라
원본 데이터와 소비용 데이터를 적절하게 분리하는 것
이다.
6. 처음부터 완벽하게 자동화할 필요는 없다
첫 데이터 제품을 만들 때는
아직 플랫폼이 충분하지 않을 수 있다.
예를 들어
권한을 사람이 직접 부여한다.
카탈로그를 수동으로 등록한다.
파이프라인을 직접 실행한다.
장애가 발생하면 운영자가 재처리한다.
같은 일이 생길 수 있다.
초기에는 어느 정도 허용할 수 있다.
오히려 실제 프로젝트를 운영해봐야
무엇이 반복되고 있는가?
를 알 수 있기 때문이다.
중요한 것은 반복을 방치하지 않는 것이다.
flowchart LR
n0["수동 작업"] --> n1["반복 발견"] --> n2["절차 정리"] --> n3["표준화"] --> n4["자동화"]
이런 순서로 발전시키면 된다.
7. 첫 번째 프로젝트가 다음의 본이 된다
첫 번째 데이터 제품의 의미는
그 데이터 제품 하나에만 있지 않다.
첫 프로젝트를 진행하면서
조직은 많은 것을 배우게 된다.
예를 들어
데이터를 어떻게 수집할 것인가?
어디에 저장할 것인가?
누가 품질을 책임질 것인가?
카탈로그에는 무엇을 등록할 것인가?
권한은 어떻게 부여할 것인가?
장애는 어떻게 감지할 것인가?
어떻게 배포할 것인가?
같은 문제를 실제로 경험한다.
이 경험을 정리하면
다음 프로젝트에서는 다시 처음부터 고민할 필요가 없다.
- 첫 번째 프로젝트 — 시행착오
- 두 번째 프로젝트 — 재사용
- 세 번째 프로젝트 — 표준화
- 이후 — 자동화와 플랫폼화
이렇게 정리한 것이 곧
19장과 22장에서 본 Blueprint가 된다.
미리 만들어 둔 표준 구성은 하늘에서 떨어지지 않는다.
한 번 해보고 정리한 결과다.
8. 데이터 도메인은 DB 구조와 같지 않다
데이터 아키텍처를 설계할 때
중요하게 구분해야 하는 것이 있다.
데이터베이스와 비즈니스 도메인은 같은 개념이 아니다.
예를 들어 시스템에
user_db
payment_db
delivery_db
order_db
가 있다고 하자.
그렇다고 반드시
User Domain
Payment Domain
Delivery Domain
Gift Domain
으로 그대로 나눠야 하는 것은 아니다.
도메인은
데이터가 어느 서버에 있는가?
보다
어떤 비즈니스 의미를 가지고 있으며
누가 그 의미와 품질을 책임지는가?
를 중심으로 판단해야 한다.
9. 데이터의 책임자를 명확하게 한다
실제 프로젝트를 시작하면
평소에는 보이지 않던 문제가 드러난다.
예를 들어
이 데이터의 정확한 정의가 뭐지?
이 컬럼을 누가 변경할 수 있지?
값이 이상하면 누가 확인하지?
외부 팀이 이 데이터를 사용해도 되나?
같은 질문이다.
그래서 데이터마다 책임이 필요하다.
회사에 따라
Data Owner,
Data Steward,
Domain Owner,
Data Product Owner
같은 이름을 사용할 수 있다.
하지만 직함 자체가 중요한 것은 아니다.
중요한 것은
누가 데이터의 의미를 정의하는가?
누가 품질을 책임지는가?
누가 변경을 관리하는가?
문제가 생기면 누가 대응하는가?
가 명확한 것이다.
작은 조직에서는 한 사람이
여러 역할을 동시에 담당할 수도 있다.
10. 중앙집중형과 탈중앙형
데이터 조직을 만들다 보면
자주 등장하는 질문이 있다.
중앙 데이터팀이 모든 데이터를 관리해야 할까?
아니면
각 서비스팀이 직접 관리해야 할까?
둘 다 장단점이 있다.
중앙집중형은 대략 이런 모습이다.
flowchart LR
hub["중앙 데이터팀 → 데이터 플랫폼"]
s0["회원팀"] --> hub
s1["결제팀"] --> hub
s2["배송팀"] --> hub
표준을 맞추고
보안과 품질을 관리하기 쉽다.
하지만 중앙팀에 모든 요청이 몰리면
병목이 발생한다.
반대로 탈중앙형은
회원팀 → 회원 데이터 제품
결제팀 → 결제 데이터 제품
배송팀 → 배송 데이터 제품
처럼 각 도메인이 자신의 데이터를 책임진다.
도메인을 잘 아는 팀이 직접 데이터를 관리하므로
빠르게 대응할 수 있다.
하지만 각 팀이 너무 자유롭게 움직이면
데이터 정의,
기술,
보안,
품질 기준
등이 제각각이 될 위험이 있다.
11. 중앙집중과 탈중앙화는 양자택일이 아니다
현실에서는 두 방식 사이에
여러 형태가 존재한다.
예를 들어
| 중앙 플랫폼팀이 맡는 것 | 도메인팀이 맡는 것 |
|---|---|
| 공통 인프라 | 데이터 제품 |
| 보안 | 비즈니스 정의와 품질 규칙 |
| 모니터링 | 운영 책임 |
| 카탈로그 · 표준 · 자동화 |
처럼 역할을 나눌 수 있다.
즉,
중앙은 공통 기반을 제공하고
도메인은 자신의 데이터를 책임진다.
이런 형태가 실무적으로 많이 사용된다.
조직의 데이터 성숙도가 낮다고 해서
반드시 중앙집중형부터 시작해야 하는 것도 아니다.
반대로 성숙도가 높다고 해서
반드시 완전한 탈중앙 구조를 사용해야 하는 것도 아니다.
조직 규모,
인력,
규제,
현재 시스템,
팀 구조,
데이터 종류
등을 고려해야 한다.
12. Data Mesh는 단순한 탈중앙화가 아니다
여기서 Data Mesh를 정확하게 이해할 필요가 있다.
Data Mesh는
데이터를 각 도메인에 나누면 된다.
라는 개념이 아니다.
3장에서 본 네 가지 원칙이 함께 있어야 Data Mesh라고 할 수 있다.
도메인이 데이터를 책임지고, 데이터를 제품처럼 관리하고,
도메인 팀이 쓸 수 있는 플랫폼이 있으며,
전사 규칙을 중앙과 도메인이 함께 관리하는 것이다.
따라서
데이터를 팀별로 나눴다
=
Data Mesh
는 아니다.
13. DataOps란 무엇인가
데이터 제품이 많아지면
개발과 운영 방식도 체계화해야 한다.
여기서 등장하는 개념이 DataOps다.
초보자에게는
데이터 분야에 DevOps 개념을 적용하는 것
이라고 설명할 수 있다.
하지만 DataOps는 그것보다 조금 더 넓다.
DataOps에는
Agile 방식
DevOps
자동화
지속적인 피드백
데이터 품질
오케스트레이션
모니터링
재현성
협업
등의 개념이 함께 포함된다.
따라서 조금 더 정확하게 표현하면
DataOps는 데이터와 분석 시스템을
빠르고 안정적으로 개발·배포·운영하기 위해
협업, 자동화, 테스트, 품질 관리와
지속적인 개선을 적용하는 방식이다.
14. 데이터도 코드처럼 관리한다
DataOps에서는
프로그램 코드만 버전 관리하는 것이 아니다.
다음과 같은 것들도
가능한 범위에서 코드와 함께 관리한다.
SQL
dbt 모델
파이프라인 정의
스키마
설정
테스트
메타데이터 정의
문서
이렇게 하면
누가 변경했는가?
언제 변경했는가?
왜 변경했는가?
이전 상태는 무엇이었는가?
를 추적할 수 있다.
또한 동일한 환경을 다시 만들거나
문제가 생겼을 때 이전 버전으로 돌아가기도 쉬워진다.
15. 데이터 파이프라인 전체를 관리한다
데이터 파이프라인은
단순한 ETL 작업 하나가 아니다.
실제로는 다음과 같은 여러 단계가 있을 수 있다.
데이터 생성
↓
수집
↓
소스 검증
↓
원본 저장
↓
정제
↓
변환
↓
품질 검사
↓
소비 데이터 생성
↓
상태 기록
↓
사용자 알림
↓
카탈로그 갱신
이 전체 과정을
하나의 워크플로로 관리하는 것이 중요하다.
16. 반복 가능한 부분은 공통 컴포넌트로 만든다
모든 데이터 파이프라인이
완전히 같은 것은 아니다.
예를 들어
배치,
CDC,
실시간 스트리밍,
파일 수집,
API 수집,
머신러닝 데이터
는 서로 다른 특성이 있다.
하지만 공통되는 부분도 많다.
로그
모니터링
알림
상태 기록
품질 검사
재시도
권한
배포
같은 기능이다.
이런 공통 기능은
각 팀이 매번 새로 만들기보다
플랫폼에서 제공하는 것이 좋다.
17. 데이터에도 CI/CD를 적용한다
데이터 파이프라인과 변환 로직도
일반 애플리케이션처럼 테스트하고 배포할 수 있다.
예를 들어
flowchart LR
n0["코드 변경"] --> n1["자동 테스트"] --> n2["SQL / 모델 검증"] --> n3["데이터 품질 테스트"] --> n4["테스트 환경 배포"] --> n5["검증"] --> n6["운영 배포"]
와 같은 흐름이다.
여기서 데이터 시스템은
일반 애플리케이션 테스트 외에도
데이터 자체를 검사해야 한다.
예를 들어
NULL이 너무 많지 않은가?
중복이 발생하지 않았는가?
스키마가 예상과 같은가?
데이터 건수가 갑자기 줄지 않았는가?
비즈니스 규칙을 위반하지 않았는가?
등을 확인할 수 있다.
18. 브랜치 전략은 하나의 정답이 아니다
일부 DataOps 사례에서는
flowchart LR
n0["Feature Branch"] --> n1["Development"] --> n2["Test"] --> n3["Production"]
처럼 여러 브랜치와 환경을 연결한다.
이 방식 자체는 사용할 수 있다.
하지만 이것이
CI/CD의 유일한 표준은 아니다.
현대적인 CI에서는
flowchart LR
n0["짧은 브랜치"] --> n1["작은 변경"] --> n2["빠르게 Main / Trunk에 병합"] --> n3["자동 테스트"]
하는 Trunk-Based Development 방식도 많이 사용된다.
중요한 것은 특정 브랜치 전략이 아니라
변경을 작게 유지하고,
자주 통합하고,
자동 테스트를 통해 안전하게 배포하는 것
이다.
19. 자동화와 수동 운영 경로를 함께 준비한다
자동화는 중요하지만
모든 상황을 자동화할 수는 없다.
실제 운영에서는
특정 기간 데이터 재처리
잘못된 배치 재실행
장애 복구
예외 데이터 수정
긴급 대응
같은 일이 발생한다.
따라서 좋은 시스템은
자동화된 기본 경로
+
통제된 수동 처리 경로
를 함께 제공해야 한다.
수동 작업을 완전히 없애는 것이 목표가 아니라
반복적이고 예측 가능한 작업은 자동화하고,
예외 상황에서는 사람이 안전하게 개입할 수 있게 하는 것
이 중요하다.
20. 규모가 커질수록 모니터링도 중앙화한다
각 도메인이 자신의 데이터 제품을 운영하더라도
회사 전체의 상태를 볼 수 있는 기능은 필요하다.
예를 들어
flowchart LR
hub["중앙 관찰 / 모니터링"]
s0["회원 데이터"] --> hub
s1["결제 데이터"] --> hub
s2["배송 데이터"] --> hub
s3["정산 데이터"] --> hub
s4["추천 데이터"] --> hub
형태로
로그,
품질 상태,
장애,
파이프라인 지연,
사용량
등을 통합해서 볼 수 있다.
이때 중앙팀이 데이터를 직접 소유하는 것과
전체 상태를 관찰하는 것은 다른 문제다.
분산 운영 환경에서도
중앙 Observability는 충분히 유용하다.
21. 엔터프라이즈 아키텍트의 역할
조직과 시스템이 복잡해질수록
전체 방향을 연결하는 역할이 필요하다.
이 역할을 수행하는 사람이
엔터프라이즈 아키텍트(Enterprise Architect) 다.
하지만 현대적인 아키텍트는
모든 기술을 혼자 결정하는 사람이 아니다.
오히려
비즈니스
조직
데이터
애플리케이션
플랫폼
보안
운영
사이의 관계를 이해하고
올바른 방향으로 연결하는 역할에 가깝다.
22. 모든 기술의 최고 전문가일 필요는 없다
현대 시스템은 너무 복잡하다.
한 사람이
DB,
네트워크,
클라우드,
스트리밍,
보안,
AI,
데이터 플랫폼,
DevOps,
DataOps
를 모두 최고 수준으로 알기는 어렵다.
따라서 아키텍트에게 중요한 것은
모든 것을 직접 구현하는 능력보다
필요한 전문가와 협력하여
전체 구조를 올바르게 연결하는 능력
이다.
예를 들어
flowchart LR
n0["실시간 처리 필요"] --> n1["아키텍트가 구조 검토"] --> n2["스트리밍 전문가와 협업"] --> n3["적절한 기술 선택"]
처럼 움직일 수 있다.
23. 아키텍처 다이어그램은 의사소통 도구다
아키텍트는 복잡한 구조를
사람들이 이해할 수 있도록 표현해야 한다.
이때 아키텍처 다이어그램이나 데이터 흐름도를 쓴다.
하지만 목적은
예쁜 그림을 그리는 것이 아니다.
서로 다른 사람들이 같은 시스템을
비슷한 방식으로 이해하도록 만드는 것
이 목적이다.
그래서 대상에 따라
그림의 수준도 달라질 수 있다.
경영진에게는
flowchart LR
n0["비즈니스 영역"] --> n1["주요 시스템"] --> n2["데이터 흐름"]
정도로 보여줄 수 있고,
개발팀에는
API
Event
Queue
DB
Cache
Pipeline
Storage
수준까지 보여줄 수 있다.
24. 기술을 비즈니스 가치로 번역한다
좋은 아키텍트는 기술 용어만 말하지 않는다.
예를 들어
“CDC를 도입해야 합니다.”
라고 말하는 것보다
“결제 데이터 변경을 빠르게 전달하면
정산 데이터 반영 지연을 줄일 수 있습니다.”
라고 설명할 수 있어야 한다.
즉,
flowchart LR
n0["기술 선택"] --> n1["비즈니스 효과"]
를 연결해야 한다.
아키텍트에게 기술 지식뿐 아니라
의사소통 능력이 중요한 이유다.
25. 현실적인 다음 단계를 제시한다
아키텍트가 이상적인 미래 구조만 보여준다면
실무팀에는 별 도움이 되지 않을 수 있다.
예를 들어 최종 목표가
Data Mesh
Self-Service Platform
자동 거버넌스
완성된 DataOps
라고 하더라도
현재 조직이 바로 거기까지 갈 수는 없다.
좋은 아키텍트는
flowchart LR
n0["현재 상태"] --> n1["1단계"] --> n2["2단계"] --> n3["3단계"] --> n4["목표 상태"]
를 설계한다.
즉,
최종 목적지뿐 아니라
지금 다음으로 해야 할 일을 제시할 수 있어야 한다.
26. 통제보다는 가드레일을 제공한다
기업에는
보안,
표준,
개인정보,
운영 안정성
등을 위한 규칙이 필요하다.
하지만 모든 기술 결정을
중앙 조직에서 승인하게 만들면
개발 속도가 크게 떨어진다.
반대로 아무런 기준도 없으면
각 팀의 구조가 지나치게 달라진다.
그래서 Guardrail이라는 사고방식이 유용하다.
가드레일은
반드시 지켜야 하는 최소한의 경계
다.
예를 들어
보안 기준
개인정보 처리 기준
API 기본 규칙
로그 기준
모니터링 기준
배포 정책
을 정한다.
그리고 그 범위 안에서는
각 팀이 상황에 맞게 선택하도록 한다.
27. 현대적인 아키텍트는 경찰이 아니다
아키텍처 조직이
규칙 위반입니다.
사용할 수 없습니다.
표준이 아닙니다.
라는 말만 반복하면
현업에서는 아키텍처 조직을
일을 방해하는 조직으로 생각하게 된다.
현대적인 아키텍트는
왜 문제가 되는지 설명한다.
위험을 설명한다.
가능한 대안을 제시한다.
필요한 전문가를 연결한다.
팀이 좋은 결정을 내리도록 돕는다.
는 역할을 해야 한다.
즉,
통제자보다는 기술적 방향을 이끄는
커뮤니티 리더에 가까워져야 한다.
28. 데이터 아키텍처는 완성되는 것이 아니다
서비스도 변하고,
조직도 변하고,
사용자 요구도 변하고,
기술도 계속 변한다.
따라서
설계 완료
→ 끝
이라는 상태는 현실적으로 존재하기 어렵다.
오히려
flowchart LR
n0["설계"] --> n1["실행"] --> n2["운영"] --> n3["피드백"] --> n4["개선"] --> n5["다시 실행"]
이 반복된다.
좋은 데이터 아키텍처는
변하지 않는 구조가 아니라
변화에 대응할 수 있는 구조
라고 보는 것이 좋다.
29. 전체 데이터 여정을 연결해보자
지금까지의 내용을 하나의 흐름으로 연결하면 다음과 같다.
flowchart TB
S1["시작<br/>──────────<br/>비즈니스 문제에서 출발해<br/>데이터 전략을 세운다"]
S2["첫 걸음<br/>──────────<br/>가치 있는 유스케이스를 하나 고르고<br/>첫 데이터 제품을 만든다"]
S3["정리<br/>──────────<br/>운영 경험을 쌓아<br/>도메인과 책임을 정의하고<br/>반복 작업을 표준화한다"]
S4["넓히기<br/>──────────<br/>공통 플랫폼과 Self-Service를 만들고<br/>거버넌스를 강화한다"]
S5["굳히기<br/>──────────<br/>DataOps와 자동화로<br/>여러 도메인의 데이터 제품을 운영한다"]
S1 --> S2 --> S3 --> S4 --> S5
S5 -. "지속적인 개선" .-> S2
style S1 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S2 fill:#f8fbff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style S3 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S4 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style S5 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
이 흐름에서 중요한 것은
순서를 기계적으로 따라야 한다는 뜻이 아니다.
조직에 따라
플랫폼을 먼저 강화할 수도 있고,
거버넌스 문제가 먼저 나타날 수도 있고,
특정 데이터 제품이 먼저 성장할 수도 있다.
중요한 것은
조직의 현재 문제와 역량을 기준으로
다음 단계를 선택하는 것이다.
30. 이번 장에서 꼭 기억해야 할 것
이번 장의 핵심은 크게 네 가지로 압축할 수 있다.
첫째, 기술보다 비즈니스 가치에서 시작한다.
데이터 플랫폼 자체가 목적이 되어서는 안 된다.
둘째, 전체 방향을 알고 작은 범위부터 실행한다.
첫 프로젝트를 통해 실제 문제를 발견하고
그 경험을 다음 프로젝트에 활용한다.
셋째, 규모가 커지면 플랫폼과 자동화가 필요하다.
flowchart LR
n0["수동"] --> n1["반복"] --> n2["표준화"] --> n3["자동화"] --> n4["Self-Service"]
로 발전시킨다.
넷째, 자율성과 거버넌스의 균형을 맞춘다.
중앙
플랫폼
표준
보안
공통 정책
가드레일
+
도메인
데이터 제품
비즈니스 규칙
품질
운영 책임
두 영역이 함께 움직여야 한다.
31. 마치면서
새로운 데이터 기술은 앞으로도 계속 등장할 것이다.
레이크하우스,
실시간 스트리밍,
AI,
머신러닝,
새로운 데이터베이스,
새로운 데이터 플랫폼이 계속 등장한다.
따라서 특정 제품이나 기술 하나를 외우는 것보다
더 중요한 것은 원칙을 이해하는 것이다.
우리는 계속 다음 질문을 할 수 있어야 한다.
왜 이 데이터가 필요한가?
누가 책임져야 하는가?
누가 사용하는가?
어떤 품질을 보장해야 하는가?
어떻게 안전하게 공유할 것인가?
무엇을 중앙에서 제공해야 하는가?
무엇을 도메인이 결정해야 하는가?
어떤 작업을 자동화해야 하는가?
다음 단계는 무엇인가?
좋은 데이터 아키텍처는
처음부터 거대한 플랫폼을 만드는 것에서 시작하지 않는다.
작은 비즈니스 문제를 데이터로 해결하는 것에서 시작한다.
그리고 그 경험을 반복하면서
flowchart LR
n0["데이터 제품"] --> n1["플랫폼"] --> n2["거버넌스"] --> n3["DataOps"] --> n4["데이터 주도 조직"]
으로 발전시켜 나간다.
결국 23장을 한 문장으로 정리하면 다음과 같다.
전체 방향은 분명하게 세우되 완벽한 아키텍처를 한 번에 만들려고 하지 말고,
가치 있는 데이터 제품부터 실행하여 배운 것을 플랫폼·거버넌스·자동화로 발전시키면서
조직 전체의 데이터 역량을 점진적으로 성장시켜라.
부록 A. 클라우드 랜딩 존과 Blueprint
이 부록은 21장 「도메인 토폴로지」에서 이어진다.
클라우드에 도메인을 실제로 배치할 때 필요한 내용이다.
표준 실행 환경인 랜딩 존과, 반복 가능한 템플릿인 Blueprint를 다룬다.
처음 읽을 때는 건너뛰어도 된다.
실제로 클라우드 환경을 설계할 때 돌아오면 된다.
1. 이제 실제 클라우드로 내려가자
지금까지는
어떤 도메인이 있는가?
누가 데이터를 책임지는가?
도메인끼리 어떻게 연결하는가?
를 살펴봤다.
이제 질문이 바뀐다.
이 도메인들을 실제 클라우드 환경에
어떻게 배치할 것인가?
여기서 랜딩 존(Landing Zone) 이라는
개념이 등장한다.
2. 랜딩 존이란
랜딩 존은
클라우드에서 워크로드를 안전하고
일관되게 시작하기 위해 준비해둔
표준 기반 환경
이라고 이해하면 된다.
예를 들어 새로운 프로젝트를 시작할 때마다
VPC 설계
IAM 정책
로그
모니터링
보안
비용 태그
를 처음부터 만들면
시간도 오래 걸리고 구성도 제각각이 된다.
그래서 표준 환경을 미리 준비한다.
3. 호텔 객실로 이해하기
호텔은 손님이 올 때마다
전기 설치
도어락 설치
침대 설치
소방시설 설치
를 하지 않는다.
이미 일정 기준으로 준비된 방을 제공한다.
랜딩 존도 비슷하다.
네트워크
IAM
보안
로그
모니터링
정책
비용 관리
같은 기본 환경을 미리 준비해둔다.
4. 클라우드마다 구현은 다르다
AWS, Azure, Google Cloud 모두
랜딩 존 또는 유사한 개념을 제공한다.
하지만
모든 클라우드가
완전히 동일한 구조와 이름을 사용하는 것은 아니다.
따라서 랜딩 존을
특정 클라우드 제품 이름보다는
표준화된 클라우드 실행 환경
이라는 개념으로 이해하는 것이 좋다.
5. 데이터 관리 랜딩 존
데이터 플랫폼을 설계할 때는
공통 관리 영역을 따로 둘 수도 있다.
이를 여기서는
데이터 관리 랜딩 존이라고 부르자.
대표적인 기능은
데이터 카탈로그
메타데이터
데이터 계보
MDM
데이터 품질
보안 정책
거버넌스
다.
다만 이 명칭과 구조는
모든 클라우드에서 사용하는 절대적인 표준은 아니다.
특정 데이터 플랫폼 아키텍처에서 사용하는
대표적인 설계 패턴이라고 이해하면 된다.
6. 데이터 랜딩 존
반면 데이터 랜딩 존은
실제 데이터 작업이 수행되는 영역이다.
예를 들어
데이터 수집
데이터 저장
데이터 변환
분석
데이터 제품 생성
같은 작업이 이루어진다.
쉽게 비유하면
데이터 관리 랜딩 존
= 아파트 관리사무소
데이터 랜딩 존
= 실제 각 세대
처럼 볼 수 있다.
7. 단일 데이터 랜딩 존
가장 단순한 구조는
모든 데이터 도메인을 하나의 랜딩 존에 넣는 것이다.
flowchart LR
hub["데이터 랜딩 존 하나"]
s0["회원"] --> hub
s1["결제"] --> hub
s2["주문"] --> hub
s3["배송"] --> hub
s4["정산"] --> hub
장점은 명확하다.
구성이 단순
초기 비용 낮음
표준화 쉬움
운영 쉬움
8. 단일 랜딩 존은 언제 좋을까
다음과 같은 환경에서
좋은 출발점이 될 수 있다.
작은 조직
데이터 플랫폼 초기 단계
도메인 수가 많지 않음
강한 표준화 필요
처음부터 복잡한 구조를 만드는 것보다
단순한 구조로 시작하는 것이 좋을 수 있다.
9. 단일 랜딩 존의 한계
조직이 커지면 문제가 생긴다.
회원
결제
주문
배송
광고
추천
정산
AI
모두 하나의 환경을 사용하면
권한 복잡
리소스 경쟁
비용 추적 어려움
성능 간섭
배포 충돌
같은 문제가 생길 수 있다.
그래서 필요에 따라
랜딩 존을 분리하게 된다.
10. 데이터 제공자와 소비자
데이터 흐름을 이해할 때는
Provider
Consumer
관계가 중요하다.
Provider는 데이터를 제공한다.
Consumer는 데이터를 사용한다.
예를 들어
flowchart LR
n0["회원"] --> n1["주문"] --> n2["정산"]
에서 주문 도메인은
회원 데이터에 대해서는
Consumer
이고,
정산에게 주문 데이터를 제공할 때는
Provider
다.
즉 하나의 도메인이
둘 다 될 수 있다.
11. Self-Service가 중요한 이유
도메인이 데이터를 사용할 때마다
중앙 데이터팀에 요청
해야 한다면
조직 규모가 커질수록 병목이 생긴다.
그래서 이상적인 플랫폼은
flowchart LR
n0["카탈로그 검색"] --> n1["데이터 발견"] --> n2["권한 신청"] --> n3["자동 승인 또는 정책 적용"] --> n4["사용"]
할 수 있도록 한다.
이를 Self-Service라고 한다.
12. 랜딩 존과 도메인은 1:1이 아니다
중요한 오해 중 하나다.
도메인 하나
=
랜딩 존 하나
일 필요는 없다.
예를 들어
주문
정산
출금
이 모두 작은 규모라면
하나의 랜딩 존을 공유할 수도 있다.
반대로 매우 큰 도메인은
여러 랜딩 존을 사용할 수도 있다.
결정 기준은
보안
규제
비용
조직
성능
리소스 한도
운영 책임
등이다.
13. 데이터 제품을 실제로 배치하기
데이터 제품은 실제 클라우드에서는
여러 기술 리소스로 구성될 수 있다.
예를 들어
스토리지
처리 로직
테이블
컨테이너
메타데이터
보안 설정
같은 것들이다.
도메인별로 완전히 나눌 수도 있다.
회원 → Storage A
결제 → Storage B
주문 → Storage C
14. 스토리지를 공유할 수도 있다
반대로 하나의 공통 스토리지 안에서
논리적으로 분리할 수도 있다.
flowchart LR
n0["공용 Storage"]
n1["member"]
n2["payment"]
n3["order"]
n4["settlement"]
n0 --> n1
n0 --> n2
n0 --> n3
n0 --> n4
이 방식은 관리가 쉽다.
하지만 도메인별 자율성은 줄어든다.
15. 공유와 격리의 트레이드오프
공유하면
비용 감소
운영 단순
표준화 쉬움
이라는 장점이 있다.
반대로
도메인 독립성 감소
장애 영향 확대
개별 최적화 어려움
이라는 문제가 있다.
분리하면 반대다.
자율성 ↑
격리 ↑
하지만
비용 ↑
운영 복잡도 ↑
따라서 모든 것을 공유하거나
모든 것을 분리할 필요는 없다.
16. 소스 정렬 랜딩 존
데이터 생산과 소비를
분리해서 관리할 수도 있다.
소스 정렬 랜딩 존은
원천 시스템에서 생성되는 데이터를
수집하고 정리하는 영역
이다.
예를 들어 결제 데이터에는
카드
PG
무통장
취소
환불
등이 있을 수 있다.
이를
flowchart LR
n0["수집"] --> n1["정제"] --> n2["표준화"]
한다.
17. 컨슈머 정렬 랜딩 존
반대로 컨슈머 정렬 랜딩 존은
데이터를 사용하는 사람이나 시스템의
목적에 맞춰 데이터를 제공하는 영역
이다.
예를 들어
BI
마케팅
추천
경영 분석
목적으로 데이터를 재구성할 수 있다.
전체 흐름은
flowchart LR
n0["원천 시스템"] --> n1["소스 정렬"] --> n2["정제된 데이터"] --> n3["컨슈머 정렬"] --> n4["BI / 추천 / 분석"]
처럼 볼 수 있다.
18. 허브 데이터 랜딩 존
여러 랜딩 존 사이에 중앙 허브를 둘 수도 있다.
flowchart LR
A["도메인 A"] --> HUB
B["도메인 B"] --> HUB
HUB["허브<br/>──────────<br/>데이터 물류센터"]
HUB --> C["도메인 C"]
HUB --> D["도메인 D"]
HUB --> E["도메인 E"]
style HUB fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
허브는 일종의 데이터 물류센터다.
보내는 쪽은 허브에 넣고, 받는 쪽은 허브에서 가져간다.
서로 직접 연결하지 않는다.
도메인이 늘어날수록 이 차이가 커진다.
| 연결 수 | |
|---|---|
| 서로 직접 연결 | 보내는 쪽 × 받는 쪽 |
| 허브를 거침 | 보내는 쪽 + 받는 쪽 |
19. 허브에서 할 수 있는 일
예를 들어
데이터 배포
공통 스토리지
데이터 라우팅
권한 관리
공통 변환
데이터 계약
같은 기능을 제공할 수 있다.
특히
누가
어떤 데이터를
어디로 보냈는지
관리해야 하는 조직에 유리하다.
20. 허브의 위험
모든 데이터가 허브를 통과하면
병목
중앙 의존
장애 영향 확대
문제가 발생할 수 있다.
따라서 허브가 편하다고 해서
모든 데이터를 반드시 허브로 통과시킬 필요는 없다.
21. 데이터 가상화
허브나 데이터 플랫폼에서는
데이터 가상화 기술을 사용할 수도 있다.
데이터 가상화는
여러 위치에 있는 데이터를
모두 복사하지 않고
하나의 논리적인 데이터처럼 조회하는 방식
이다.
예를 들어
회원 DB
주문 DB
결제 DB
가 서로 다른 위치에 있어도
사용자에게는
하나의 통합 데이터 뷰
처럼 보이게 할 수 있다.
주의할 점
데이터 가상화라고 해서
항상 물리적 데이터 복사가 전혀 없는 것은 아니다.
구현에 따라
캐시
임시 저장
물리화
등이 사용될 수도 있다.
핵심은 소비자가
여러 데이터 위치의 복잡성을
직접 처리하지 않도록 하는 것이다.
22. 다중 데이터 랜딩 존
조직 규모가 커지면
여러 개의 데이터 랜딩 존을 운영할 수 있다.
예를 들어 지역 기준으로
미국 랜딩 존
유럽 랜딩 존
아시아 랜딩 존
을 둘 수도 있다.
또는 비즈니스 기준으로
커머스
구독
광고
를 나눌 수도 있다.
23. 랜딩 존을 나누는 기준
대표적인 기준은 다음과 같다.
보안 수준
데이터 민감도
규제
리전
비용 책임
SLA
조직 구조
비즈니스 프로세스
변경 속도
실험 여부
장애 격리
즉 단순히
팀 하나 = 랜딩 존 하나
처럼 나누는 것이 아니다.
24. 데이터 레지던시
글로벌 서비스를 운영하면
데이터가 저장되는 지역도 중요하다.
데이터 레지던시(Data Residency) 는
데이터를 어느 국가 또는 지역에
저장해야 하는지
와 관련된 문제다.
예를 들어 특정 국가 규제 때문에
해당 지역 안에서 데이터를 저장해야 할 수 있다.
GDPR에 대한 주의
다만
GDPR
= 유럽 데이터는 절대 EU 밖으로 이동 불가
라고 이해하면 안 된다.
GDPR은 국제 데이터 이전을
무조건 금지하는 법이 아니다.
적절한 법적 근거와 보호조치가 있다면
국제 이전도 가능하다.
따라서 아키텍처 관점에서는
데이터 위치와 국제 이전 조건을
규제에 맞게 검토해야 한다.
라고 이해하는 것이 정확하다.
25. 비용 관리
클라우드 비용도
랜딩 존 분리 기준이 될 수 있다.
여기서 자주 나오는 개념이
Showback
Chargeback
이다.
Showback은
"A팀이 이번 달
클라우드 비용 500만 원을 사용했습니다."
처럼 비용을 보여주는 것이다.
Chargeback은
실제로 그 비용을
A팀 또는 해당 사업부에 배부
하는 방식이다.
26. SLA
모든 시스템이 동일한 수준의
가용성을 필요로 하는 것은 아니다.
예를 들어
- 실시간 주문 — 매우 높은 가용성
- 일일 분석 배치 — 일정 시간 지연 가능
일 수 있다.
두 시스템에 같은 인프라를 적용하면
불필요한 비용이 발생할 수 있다.
그래서 SLA 차이가 큰 경우
환경을 분리하는 것도 방법이다.
27. 실험 환경
새로운 기술을 테스트하는 환경도
운영 환경과 분리하는 것이 좋다.
예를 들어
새 데이터베이스
AI PoC
신규 데이터 플랫폼
새로운 처리 엔진
을 실험한다고 하자.
운영 환경과 분리하면
실패하더라도 실제 서비스에 영향을 줄 가능성이 줄어든다.
28. 조직적 요인도 중요하다
아키텍처는 기술만으로 결정되지 않는다.
실제로는
사업부 구조
예산
조직 권한
법인 분리
향후 매각이나 분사 가능성
등도 영향을 미친다.
따라서 좋은 아키텍처란
기술적으로 아름다운 구조
만을 의미하지 않는다.
조직이 실제로 운영할 수 있어야 한다.
29. 다중 데이터 관리 랜딩 존
매우 큰 글로벌 조직이라면
데이터 관리 영역 자체도 여러 개로 나눌 수 있다.
미국 관리 영역
유럽 관리 영역
아시아 관리 영역
하지만 각 지역이 완전히 독립적으로 움직이면
전사 데이터가 다시 파편화된다.
그래서 전체 회사 차원의
공통 보안
공통 감사
공통 메타데이터 기준
공통 데이터 정책
은 필요하다.
30. Blueprint란 무엇인가
새로운 도메인이 생길 때마다
클라우드 환경을 처음부터 만들면 비효율적이다.
그래서 반복해서 사용할 수 있는
표준 환경 템플릿을 만든다.
이 책에서는 이를
Blueprint라고 부를 수 있다.
예를 들어
flowchart LR
n0["분석용 Blueprint"]
n1["Storage"]
n2["Data Processing"]
n3["BI"]
n4["Logging"]
n5["Monitoring"]
n0 --> n1
n0 --> n2
n0 --> n3
n0 --> n4
n0 --> n5
또는
flowchart LR
n0["ML용 Blueprint"]
n1["Data Lake"]
n2["ML Platform"]
n3["Feature Store"]
n4["Monitoring"]
n0 --> n1
n0 --> n2
n0 --> n3
n0 --> n4
같은 형태다.
31. Blueprint는 개념으로 이해하자
여기서 Blueprint는
반복 가능한 표준 인프라 템플릿
이라는 일반 개념으로 이해하는 것이 좋다.
특정 클라우드의Blueprint라는 이름의 제품과는 구분해야 한다.
실제로 구현할 때는
Terraform
CloudFormation
Bicep
각종 IaC 모듈
배포 스택
등 여러 기술을 사용할 수 있다.
32. Blueprint와 Self-Service
이상적인 환경에서는
새 도메인이 생길 때 다음처럼 진행할 수 있다.
flowchart LR
n0["새 도메인 생성"] --> n1["필요한 Blueprint 선택"] --> n2["자동 프로비저닝"] --> n3["표준 환경 생성"] --> n4["도메인 개발 시작"]
중앙 플랫폼팀이
매번 직접 환경을 만드는 대신,
도메인 팀이 준비된 환경을
스스로 사용할 수 있도록 한다.
33. Blueprint에 공통 정책을 포함한다
Blueprint에는 단순한 서버나
스토리지만 들어가는 것이 아니다.
예를 들어
IAM
모니터링
비용 태그
보안 정책
로그
데이터 카탈로그 연결
등을 기본으로 넣을 수 있다.
그러면 새 환경을 만들 때마다
회사의 기본 정책이 자동으로 적용된다.
34. 표준화와 자율성을 동시에 가져간다
이 구조의 목적은
모든 팀을 똑같게 만들기
가 아니다.
대신
- 공통 기반 — 표준화
- 도메인 내부 — 필요한 자율성
을 함께 제공한다.
예를 들어
공통 보안
공통 로그
공통 비용 관리
는 강제하되,
도메인의 데이터 처리 기술은
선택권을 줄 수도 있다.
35. 아키텍처 도입은 작게 시작한다
이 부록에서 가장 중요한 실무 원칙 중 하나다.
처음부터
전사 데이터 메시
전사 데이터 플랫폼
모든 도메인 분리
모든 랜딩 존 자동화
를 한 번에 구축하려 하면
실패 위험이 높다.
대신 작은 영역부터 시작한다.
36. 작지만 전체 흐름을 경험해야 한다
예를 들어
주문 분석 데이터
하나를 선택했다고 하자.
단순히
파일 하나 저장
하고 끝내는 것이 아니라
flowchart LR
n0["데이터 발생"] --> n1["수집"] --> n2["저장"] --> n3["변환"] --> n4["품질 관리"] --> n5["데이터 제품"] --> n6["카탈로그"] --> n7["Consumer 사용"]
까지 경험해보는 것이 좋다.
37. 8~16주는 하나의 경험적 가이드
책에서는 첫 프로젝트를
대략 8~16주 정도 범위로 잡는 방식을 제안할 수 있다.
하지만 이것은
산업 표준 규칙
이 아니다.
핵심은
몇 년짜리 거대한 프로젝트로 시작하지 말고
짧은 기간 안에 실제 결과를 만들어보라.
는 것이다.
38. 이해관계자를 초기부터 참여시킨다
아키텍트와 플랫폼팀만
설계해서는 안 된다.
실제로 사용할 사람들도 참여해야 한다.
예를 들어
도메인 개발자
데이터 엔지니어
분석가
보안팀
운영팀
등이다.
실제 사용자를 통해
불편한 점
복잡한 점
부족한 기능
불필요한 기능
을 확인해야 한다.
39. 완벽한 미래를 미리 설계하지 않는다
5년 뒤의 모든 요구사항을
처음부터 예측하려 하면
설계가 지나치게 복잡해질 수 있다.
대신
flowchart LR
n0["현재 문제 해결"] --> n1["운영"] --> n2["문제 발견"] --> n3["개선"] --> n4["확장"]
방식으로 발전시키는 것이 현실적이다.
40. 아키텍처는 살아 있는 구조다
아키텍처를 한 번 만들어놓고
끝내는 것이 아니다.
flowchart LR
n0["설계"] --> n1["구현"] --> n2["운영"] --> n3["피드백"] --> n4["개선"]
을 반복한다.
Blueprint도
flowchart LR
n0["Blueprint v1"] --> n1["Blueprint v2"] --> n2["Blueprint v3"]
처럼 계속 발전할 수 있다.
41. 데이터 제품의 기본 조건을 정의한다
조직에서는
무엇을 데이터 제품이라고 부를 것인가?
에 대한 기본 기준을 마련하는 것도 좋다.
예를 들어
소유자 존재
메타데이터 존재
품질 정보 제공
접근 정책 존재
카탈로그 등록
같은 기준을 둘 수 있다.
구체적인 항목은 조직마다 달라질 수 있다.
42. 보안과 컴플라이언스는 처음부터 넣는다
보안을 나중에 추가하면
비용도 많이 들고 구조도 복잡해진다.
따라서 초기 설계부터
접근제어
암호화
감사 로그
데이터 보존
개인정보
지역 규제
를 고려해야 한다.
즉,
기능 먼저 개발
→ 나중에 보안
보다는
처음부터 보안이 포함된 플랫폼
이 더 좋은 방향이다.
43. 기존 환경을 무조건 버리지 않는다
새로운 아키텍처를 도입한다고 해서
기존 시스템 전부 폐기
부터 할 필요는 없다.
가능하면
기존 시스템
+
새로운 거버넌스
+
공통 플랫폼
+
자동화
를 결합해서
점진적으로 개선하는 것이 현실적이다.
44. 과도한 커스터마이징을 피한다
처음부터
우리 회사만의
완벽한 데이터 플랫폼
을 만들려고 하면 위험하다.
시간이 지나면
개발 비용 증가
운영 비용 증가
업그레이드 어려움
표준 기술 활용 어려움
이 생길 수 있다.
가능하면 검증된 기술과
클라우드 기본 기능을 활용한다.
45. 자동화가 매우 중요하다
도메인이 2~3개일 때는
사람이 직접 처리할 수도 있다.
하지만 도메인이 수십 개가 되면 어렵다.
예를 들어 모든 도메인에 대해 사람이
계정 생성
권한 설정
스토리지 생성
로그 설정
카탈로그 등록
을 반복하면 확장할 수 없다.
그래서
Infrastructure as Code
CI/CD
Policy as Code
Self-Service
같은 자동화가 중요하다.
46. 자동화하기 어려운 기능은 다시 검토한다
어떤 기능이 항상
담당자가 직접 승인
담당자가 직접 생성
담당자가 직접 설정
해야 한다면
규모가 커졌을 때 병목이 될 가능성이 높다.
따라서 반복 작업은 최대한
정책화
표준화
자동화
해야 한다.
47. 부록 A 정리
랜딩 존과 Blueprint를 처음부터 끝까지 연결하면 이렇다.
flowchart TB
B1["① 논리 설계<br/>──────────<br/>도메인을 나누고 데이터 책임을 정한다<br/>연결 방식과 중앙화 정도를 결정한다"]
B2["② 실행 환경<br/>──────────<br/>랜딩 존 구조를 설계하고<br/>데이터 제품을 실제 인프라에 배치한다"]
B3["③ 반복 제거<br/>──────────<br/>Blueprint와 Self-Service를 제공한다"]
B4["④ 지켜야 할 것<br/>──────────<br/>보안 · 규제 · 비용 · 데이터 지역을 관리한다"]
B5["⑤ 넓히기<br/>──────────<br/>작은 범위에서 검증한 뒤 점진적으로 확장한다"]
B1 --> B2 --> B3 --> B4 --> B5
style B1 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style B2 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style B3 fill:#f8fbff,stroke:#4a90e2,color:#1a1a1a
style B4 fill:#fafafa,stroke:#bbb,color:#1a1a1a
style B5 fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
①은 21장 「도메인 토폴로지」에서 이미 정한 것이다.
이 부록은 ②부터를 다뤘다.
조금 더 자세히 보면 이렇게 내려간다.
flowchart TB
BIZ["비즈니스<br/>회원 · 결제 · 배송 · 주문 · 정산"]
DOM["도메인 정의 · 데이터 소유권 · 도메인 토폴로지"]
CEN["중앙화"]
DEC["분산 / 연합"]
PLAT["공통 데이터 플랫폼"]
LZ["랜딩 존 토폴로지"]
MGMT["데이터 관리 영역<br/>카탈로그 · 정책 · 보안 · 거버넌스"]
EXEC["데이터 실행 영역<br/>도메인 · 데이터 제품"]
BP["Blueprint"]
SS["Self-Service · 자동화"]
OPS["실제 클라우드 운영"]
BIZ --> DOM
DOM --> CEN
DOM --> DEC
CEN --> PLAT
DEC --> PLAT
PLAT --> LZ
LZ --> MGMT
LZ --> EXEC
MGMT --> BP
EXEC --> BP
BP --> SS --> OPS
style BIZ fill:#fafafa,stroke:#bbb,color:#1a1a1a
style LZ fill:#f8fbff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style BP fill:#f8fbff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
style OPS fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
아래로 내려갈수록 비즈니스 개념에서 실제 인프라로 구체화된다.
위쪽 절반은 21장에서 정하는 것이고,
랜딩 존부터 아래가 이 부록의 범위다.
세 가지만 기억하면 된다
용어를 다 외울 필요는 없다.
랜딩 존은 표준화된 클라우드 실행 환경이다.
보안, 네트워크, 로그, 정책을 미리 준비해 둔다.
새 도메인이 생길 때마다 처음부터 만들지 않아도 된다.
Blueprint와 Self-Service로 반복을 없앤다.
표준 구성을 한 벌 만들어 두고 팀이 직접 가져다 쓰게 한다.
단, 바꿀 수 없으면 기본값이 아니라 규제가 된다.
처음부터 완벽한 구조를 만들려고 하지 않는다.
flowchart LR
n0["작게 시작"] --> n1["실제 운영"] --> n2["피드백"] --> n3["개선"] --> n4["확장"]
도메인을 어떻게 나누고 무엇을 중앙화할지는
21장 「도메인 토폴로지」에서 다뤘다.
이 부록은 그렇게 정한 것을 클라우드에 어떻게 내려놓을지의 이야기였다.
좋은 데이터 아키텍처는 모든 것을 중앙에 모으거나
모든 것을 분산하는 것이 아니다.
비즈니스 책임은 명확하게 나누고, 공통으로 관리할 것은 표준화하며,
조직이 감당할 수 있는 수준에서 점진적으로 자율성을 확대하는 것이다.
부록 B. 지식 그래프와 시맨틱 웹
이 부록은 15장 「메타데이터와 데이터 지도」에서 이어진다.
메타데이터의 관계를 그래프로 다루는 기술을 모았다.
지식 그래프, RDF, OWL, SPARQL, SHACL, SKOS,
그리고 메타데이터 통합 기반과 데이터 마켓플레이스다.
15장을 이해하는 데 반드시 필요한 내용은 아니다.
메타데이터를 본격적으로 다루게 될 때 읽으면 된다.
1. 지식 그래프
메타데이터가 많아질수록
단순 목록보다 관계가 중요해진다.
이때 활용할 수 있는 것이
지식 그래프(Knowledge Graph) 다.
지식 그래프는
개념과 데이터 사이의 관계를
그래프 형태로 연결하는 방식
이다.
예를 들어
flowchart LR
d["주문 데이터"]
d -- "속한다" --> a["주문 도메인"]
d -- "소유된다" --> b["주문팀"]
d -- "저장된다" --> c["MariaDB"]
d -- "사용된다" --> e["정산 시스템"]
d -- "집계된다" --> f["주문 Dashboard"]
처럼 표현할 수 있다.
2. 지식 그래프가 메타데이터와 잘 맞는 이유
메타데이터에는 관계가 많다.
flowchart LR
n0["컬럼"] --> n1["테이블"] --> n2["데이터 프로덕트"] --> n3["도메인"] --> n4["애플리케이션"] --> n5["조직"] --> n6["담당자"]
그래프 모델은 이런 관계를
자연스럽게 표현하고 탐색하기 좋다.
다만
그래프 DB가 관계형 DB보다
항상 빠르거나 항상 우수하다
는 뜻은 아니다.
성능은 데이터 모델, 데이터 크기,
쿼리 형태와 제품에 따라 달라진다.
지식 그래프의 장점은
복잡한 관계와 의미를 표현하고
탐색하는 데 자연스럽다는 것
이다.
3. RDF
지식 그래프에서 자주 등장하는 기술이
RDF(Resource Description Framework) 다.
RDF에서는 정보를 다음처럼 표현한다.
주어 - 관계 - 목적어
정확한 용어로는
Subject
Predicate
Object
이고 이를 Triple이라고 한다.
예를 들어
payment
belongsTo
commerce
라고 표현할 수 있다.
즉,
payment는
commerce에 속한다.
라는 의미다.
4. OWL
OWL(Web Ontology Language)은
개념과 관계를 보다 형식적으로 정의하는
온톨로지 언어다.
예를 들어
카드결제는
결제의 한 종류다.
결제는
주문과 연결될 수 있다.
같은 개념 관계와 제약을 표현할 수 있다.
OWL은 단순한 업무 규칙 엔진이라기보다
컴퓨터가 개념의 의미와 관계를
해석하고 추론할 수 있도록 만드는
형식적인 온톨로지 표현 언어
라고 이해하는 것이 정확하다.
5. SPARQL
RDF 그래프에서 데이터를 검색할 때
사용할 수 있는 대표적인 질의 언어가
SPARQL이다.
쉽게 비교하면
- 관계형 DB — SQL
- RDF Graph — SPARQL
이다.
예를 들어
커머스 도메인에 속하면서
정산 서비스가 사용하는 데이터는?
같은 관계 중심 질문을
그래프에서 조회할 수 있다.
6. SHACL
SHACL(Shapes Constraint Language) 은
RDF 그래프가 특정 조건을 만족하는지
검증하는 데 사용할 수 있다.
예를 들어 조직의 규칙이
모든 데이터 프로덕트에는
Owner가 있어야 한다.
라면
이 조건을 검증하도록 만들 수 있다.
즉,
그래프 데이터의 구조와 조건을 검증하는 기술
이라고 이해하면 된다.
7. SKOS
SKOS(Simple Knowledge Organization System) 는
용어집과 분류체계를 표현하는 데 사용할 수 있다.
예를 들어
flowchart LR
n0["결제"]
n1["카드결제"]
n2["무통장입금"]
n3["간편결제"]
n0 --> n1
n0 --> n2
n0 --> n3
같은 구조나
판매자
≈ 셀러
≈ 입점 업체
같은 관련 용어를 표현할 수 있다.
따라서 비즈니스 용어집이나
분류체계를 표현할 때 유용하다.
8. 관련 기술을 쉽게 기억하면
RDF
= 관계 표현
OWL
= 개념과 관계를 형식적으로 정의
SPARQL
= 그래프 검색
SHACL
= 그래프 검증
SKOS
= 용어와 분류 체계
정도로 기억하면 충분하다.
9. 메타레이크
지식 그래프를 만들려면 재료가 있어야 한다.
회사의 메타데이터는 DB, API, Kafka, S3, BI, ML 같은
여러 곳에 흩어져 있다.
이것을 한곳에 모아 두는 기반을
메타레이크(Metalake) 라고 부른다.
여러 시스템에서 수집한 메타데이터를
모아서 저장하고 연결하고 가공하기 위한 기반
데이터 레이크가 데이터를 모으듯
메타레이크는 메타데이터를 모은다고 보면 된다.
흐름은 이렇다.
flowchart LR
n0["DB"]
n1["API"]
n2["Kafka"]
n3["S3"]
n4["BI"]
n5["ML"]
n6["메타데이터 수집"]
n7["메타레이크"]
n8["정제 / 연결"]
n9["지식 그래프"]
n0 --> n6
n1 --> n6
n2 --> n6
n3 --> n6
n4 --> n6
n5 --> n6
n6 --> n7
n7 --> n8
n8 --> n9
메타레이크는 Data Warehouse처럼
모든 조직이 같은 뜻으로 쓰는 확립된 용어는 아니다.
개념으로 이해하면 충분하다.
10. 메타레이크와 데이터 카탈로그
둘의 역할을 구분하면 이해하기 쉽다.
메타레이크
= 메타데이터를 저장하고 연결하는 기반
데이터 카탈로그
= 사용자가 메타데이터를 검색하고 탐색하는 서비스
비유하면
메타레이크
= 도서관의 책과 관리 시스템
데이터 카탈로그
= 도서 검색 시스템
정도로 볼 수 있다.
실제 제품에서는 두 역할이
하나의 플랫폼에 합쳐질 수도 있다.
11. 데이터 패브릭
데이터 패브릭(Data Fabric) 은
메타데이터 시스템 하나를 의미하지 않는다.
보다 넓은
분산된 데이터 환경을
통합적으로 발견하고, 연결하고, 접근하고,
거버넌스하기 위한 아키텍처 접근법
이다.
데이터를 반드시 하나의 저장소로
옮겨야 하는 것은 아니다.
실제 데이터가
MariaDB
Kafka
S3
Data Warehouse
Cloud
SaaS
등 여러 곳에 있어도 된다.
대신
메타데이터
자동화
데이터 통합
카탈로그
거버넌스
보안
API
등을 이용해
하나의 연결된 환경처럼 사용할 수 있게 한다.
12. 데이터 패브릭의 개념적 흐름
쉽게 표현하면 다음과 같다.
flowchart LR
SRC["여러 데이터 소스<br/>──────────<br/>DB · API · Kafka · S3"]
COL["메타데이터 수집"]
STD["정제 · 표준화 · 통합"]
KG["지식 그래프와<br/>메타데이터 관리"]
SVC["카탈로그 · 접근<br/>통합 · 거버넌스"]
USR["사용자 · 분석 · AI"]
SRC --> COL --> STD --> KG --> SVC --> USR
style KG fill:#e8f4ff,stroke:#4a90e2,stroke-width:2px,color:#1a1a1a
지식 그래프는 데이터 패브릭을 구현할 때
활용할 수 있는 중요한 기술 중 하나이지,
데이터 패브릭 자체와
동일한 개념은 아니다.
13. 데이터 마켓플레이스
데이터 마켓플레이스는 일종의
사내 데이터 상품 쇼핑몰
이라고 생각하면 이해하기 쉽다.
상품 상세 페이지처럼 이런 정보가 보인다.
| 항목 | 예 |
|---|---|
| 데이터 프로덕트 | 판매자별 일별 주문 통계 |
| 소유자 | 주문 데이터팀 |
| 갱신 주기 | 5분 |
| 품질 | 정상 |
| 접근 방법 | SQL / API |
| 접근 권한 | 승인 필요 |
사용자는 데이터를 찾은 다음 이렇게 이어 간다.
flowchart LR
F["발견"] --> D["설명 확인"] --> Q["품질 확인"] --> O["소유자 확인"] --> R["접근 신청"] --> U["사용"]
style U fill:#f2fbf4,stroke:#4caf50,stroke-width:2px,color:#1a1a1a
14. 카탈로그와 무엇이 다른가
두 개념은 상당히 겹친다.
초점이 다르다고 보면 쉽다.
| 어디에 초점이 있나 | |
|---|---|
| 데이터 카탈로그 | 데이터를 발견하고 이해하는 데 |
| 데이터 마켓플레이스 | 데이터 프로덕트를 발견하고 평가하고 신청하고 소비하는 경험에 |
카탈로그가 도서관 검색이라면
마켓플레이스는 주문과 배송까지 포함한 쇼핑몰에 가깝다.
다만 반드시
카탈로그 → 마켓플레이스
순서로 발전해야 하는 것은 아니다.
어떤 제품에서는 두 기능을 하나의 플랫폼으로 제공한다.
15. 본문으로 돌아가며
여기서 다룬 것들은 모두
15장 「메타데이터와 데이터 지도」의 연장선이다.
| 이 부록의 주제 | 15장에서 이어진 지점 |
|---|---|
| 지식 그래프와 시맨틱 웹 기술 | 메타모델 — 메타데이터를 관계로 연결한다 |
| 메타레이크 | 메타데이터를 어디에 모아 둘 것인가 |
| 데이터 패브릭 | 분산된 데이터를 하나처럼 다룬다 |
| 데이터 마켓플레이스 | 데이터 민주화의 한 형태 |
기술 이름보다 중요한 것은 방향이다.
메타데이터를 목록이 아니라 관계로 다루면
조직이 데이터를 훨씬 더 잘 찾고 이해할 수 있다.
다만 이 기술들이 없어도 15장의 내용은 성립한다.
필요해질 때 돌아오면 된다.
부록 C. 용어집
본문에 나오는 용어를 한곳에 모았다.
각 용어를 처음 만났을 때
자세한 설명이 있는 장을 함께 적어 두었으니
필요하면 그 장을 펼치면 된다.
다루는 곳이 —인 항목은 본문에서 따로 설명하지 않는다.
알아 두면 좋지만 이 책의 흐름에서는 곁가지인 용어들이다.
주제별로 묶었기 때문에
관련 개념을 나란히 놓고 비교하기도 좋다.
1. 경계와 도메인
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| Business Capability | 회사가 할 수 있어야 하는 일 | 5장 |
| Domain | 해결하려는 비즈니스 문제 영역 | 5장 |
| Subdomain | 큰 문제를 나눈 작은 문제 영역 | 5장 |
| Bounded Context | 같은 용어가 일관된 의미를 갖는 경계 | 5장 |
| Ubiquitous Language | Context 안에서 함께 쓰는 공통 언어 | 5장 |
| 데이터 도메인 (Data Domain) | 데이터 책임을 가지는 비즈니스 영역 | 6장 |
| Data Ownership | 데이터의 의미·품질·정책을 책임지는 일 | 6장 |
| Data Sprawl | 데이터가 무질서하게 퍼지는 상태 | 6장 |
| 응집도 | 함께 변경되는 것이 얼마나 가까이 있는가 | 4장 |
| 결합도 | 상대의 내부를 얼마나 알아야 하는가 | 4장 |
2. 연결과 통신
API
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| API Contract | 제공자와 소비자 사이의 약속 | 8장 |
| OpenAPI | HTTP API 계약을 표현하는 표준 | 8장 |
| REST | 리소스 중심의 아키텍처 스타일 | 8장 |
| ESB | 여러 시스템을 잇는 중앙 통합 계층 | 8장 |
| API Gateway | 진입점에서 공통 정책을 처리하는 계층 | 8장, 12장 |
| Composite Service | 여러 API 결과를 묶어 제공 | 8장 |
| BPM | 며칠씩 걸리는 업무 흐름의 진행 상태를 관리하는 분야. 비즈니스 데이터 자체의 저장소는 아니다 | — |
| BFF | 특정 프론트엔드 전용 백엔드 | 9장 |
| GraphQL | 필요한 필드를 지정해 조회하는 질의 언어 | 9장 |
| Service Mesh | 서비스 간 통신을 인프라에서 처리 | 9장 |
| CQRS | 쓰기와 읽기의 책임을 분리하는 패턴 | 9장 |
| Read Model | 조회에 최적화된 데이터 모델 | 9장 |
이벤트
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| Event | 이미 발생한 사실 | 10장 |
| Command | 무엇을 해달라는 요청 | 10장 |
| Producer / Consumer | 이벤트를 만드는 쪽과 쓰는 쪽 | 10장 |
| Event Broker | Producer와 Consumer를 잇는 중개자 | 10장 |
| Event-Carried State Transfer | 이벤트에 필요한 상태까지 담아 보내는 방식 | 10장 |
| Event Sourcing | 상태가 아니라 상태를 만든 이벤트를 저장 | 10장 |
| Schema Registry | 이벤트 스키마와 버전을 관리 | 10장 |
| AsyncAPI | 이벤트 계약을 표현하는 표준 | 10장 |
| Idempotency | 여러 번 처리해도 결과가 같게 만드는 성질 | 11장 |
| At-least-once | 최소 한 번은 전달하되 중복될 수 있는 방식 | 11장 |
| DLQ | 계속 실패한 메시지를 옮겨 두는 공간 | 11장 |
| Backpressure | 처리 능력에 맞춰 생산 속도를 조절 | 11장 |
| Eventual Consistency | 시간이 지나면 같은 상태로 수렴하는 성질 | 11장 |
조합과 정합성
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| Saga | 여러 시스템에 걸친 업무를 보상 처리로 잇는 패턴 | 12장 |
| Transactional Outbox | 저장과 이벤트 발행을 함께 묶는 방법 | 10장, 12장 |
| Circuit Breaker | 장애가 번지지 않도록 호출을 끊는 패턴 | 12장 |
| CDC | DB 변경을 감지해 다른 시스템으로 전달 | 12장, 14장 |
3. 데이터 제품과 모델링
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| Data Product | 의미·품질·계약을 갖춰 제공하는 데이터 | 13장 |
| Input Port / Output Port | 데이터 제품의 입력과 출력 계약 | 14장 |
| Star Schema | Fact와 Dimension 중심의 분석 모델 | 13장 |
| Data Vault | Hub·Link·Satellite 기반 모델 | 13장 |
| SCD | Dimension 속성의 변경 이력을 관리하는 기법 | 14장 |
| Snapshot | 특정 시점의 전체 상태를 저장 | 14장 |
| Append-only | 기존 사실을 덮지 않고 계속 추가 | 14장 |
| Data Quality | 데이터를 믿고 쓸 수 있는 정도 | 14장 |
| Reconciliation | 원천과 결과를 대조해 차이를 찾는 일 | 14장 |
| Medallion Architecture | Bronze / Silver / Gold 처리 패턴 | 14장 |
4. 메타데이터와 거버넌스
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| Metadata | 데이터를 설명하는 데이터 | 15장 |
| Metamodel | 메타데이터 사이의 관계를 정의한 설계도 | 15장 |
| 개념 · 논리 · 물리 모델 | 비즈니스 개념에서 구현까지의 세 단계 | 15장 |
| Data Lineage | 데이터의 출처·변환·이동 경로 | 15장 |
| Data Catalog | 데이터를 찾고 이해하는 검색 포털 | 15장 |
| Data Democratization | 필요한 사람이 안전하게 직접 활용하는 것 | 15장 |
| Data Governance | 여러 도메인이 따라야 하는 공통 원칙 | 16장 |
| Data Owner | 데이터에 대한 책임자 | 16장 |
| Data Steward | 데이터 관리 실무 역할 | 16장 |
| Data Contract | 제공자와 소비자의 데이터 약속 | 16장 |
| Usage Agreement | 어떤 목적으로 쓸 수 있는지 정한 약속 | 16장 |
| Data Observability | 데이터와 파이프라인 상태를 지속 관찰 | 16장 |
| RACI | 책임 소재를 네 역할로 정리하는 방법 | 16장 |
5. 마스터 데이터
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| Master Data | 여러 시스템이 공통으로 쓰는 핵심 기준 데이터 | 18장 |
| Reference Data | 다른 데이터를 분류하는 기준값 | 18장 |
| Golden Record | 신뢰할 수 있는 기준 레코드 | 18장 |
| Surrogate Key | 비즈니스 의미 없이 대상을 식별하는 키 | 18장 |
| Registry / Consolidation / Centralized / Coexistence | MDM의 네 가지 구현 스타일 | 18장 |
6. 보안
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| Classification | 데이터 중요도와 민감도 분류 | 17장 |
| Trust Boundary | 같은 신뢰 수준이 적용되는 영역의 경계 | 17장 |
| ACL | 대상별 사용자 권한 목록 | 17장 |
| RBAC | 역할을 기준으로 권한을 결정 | 17장 |
| ABAC | 여러 속성을 조합해 권한을 결정 | 17장 |
| IdP | 사용자의 신원을 제공하는 시스템 | 17장 |
| PDP / PEP | 정책을 판단하는 지점과 집행하는 지점 | 17장 |
| RLS / CLS | 행 단위·열 단위 접근 제어 | 17장 |
| Masking / Tokenization | 민감한 값을 가리거나 다른 값으로 치환 | 17장 |
7. 활용과 플랫폼
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| Semantic Layer | 물리 구조와 업무 의미를 잇는 계층 | 19장 |
| Self-Service | 사용자가 직접 찾고 활용할 수 있는 구조 | 19장, 22장 |
| Feature Engineering | 모델이 쓸 입력 변수를 만드는 일 | 20장 |
| Feature Store | 공통 피처를 모아 관리하는 저장소 | 20장 |
| Model Registry | 모델의 버전과 상태를 관리 | 20장 |
| Drift | 입력·예측·관계가 시간이 지나며 달라지는 현상 | 20장 |
| MLOps | ML 개발과 운영을 위한 엔지니어링 체계 | 20장 |
| ONNX | 프레임워크에 묶이지 않는 모델 저장 형식. 학습 환경과 서비스 환경이 다를 때 쓴다 | 20장 |
8. 아키텍처와 조직
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| Data Mesh | 도메인 중심의 분산 데이터 운영 방식 | 3장 |
| Data Fabric | 분산 데이터의 발견·연결·거버넌스 접근법 | 3장, 부록 B |
| DataOps | 데이터 시스템을 빠르고 안정적으로 운영하는 방식 | 23장 |
| Federated Governance | 중앙 표준과 도메인 자율성의 결합 | 3장, 22장 |
| Team Topologies | 팀 유형과 상호작용 방식을 다루는 모델 | 22장 |
| Playbook | 자주 마주치는 상황마다 「이럴 땐 이렇게」를 모아 둔 문서 | 22장 |
| Golden Path | 올바른 방법이 가장 쉬운 방법이 되도록 만들어 둔 표준 경로 | 22장 |
| Blueprint | 미리 맞춰 둔 한 벌의 표준 구성. Golden Path의 출발점에 놓인다 | 19장 · 부록 A |
| Collaboration | 두 팀이 한동안 붙어 함께 만드는 방식. 한시적으로 쓴다 | 22장 |
| X-as-a-Service | 만들어 둔 것을 다른 팀이 문서 보고 알아서 쓰는 방식 | 22장 |
| Facilitation | 한 팀이 다른 팀의 역량을 키워 주고 빠지는 방식 | 22장 |
| Guardrail | 반드시 지켜야 하는 최소한의 경계 | 23장 |
| Serverless | 서버 설치·확장·운영을 직접 하지 않는 실행 모델. 물리 서버가 없다는 뜻은 아니다 | — |
| FaaS | 함수 단위로 코드를 실행하는 방식. 서버리스의 대표적인 한 형태 | — |
| Landing Zone | 표준화된 클라우드 실행 환경 | 부록 A |
9. 메타데이터 심화
| 용어 | 쉽게 말하면 | 다루는 곳 |
|---|---|---|
| Knowledge Graph | 데이터와 개념의 관계망 | 부록 B |
| RDF | 관계를 Triple 형태로 표현 | 부록 B |
| OWL | 개념과 관계를 형식적으로 정의 | 부록 B |
| SPARQL | RDF 그래프에 대한 질의 언어 | 부록 B |
| SHACL | RDF 그래프의 구조와 조건을 검증 | 부록 B |
| SKOS | 용어집과 분류 체계를 표현 | 부록 B |
| 데이터 마켓플레이스 | 데이터 제품을 발견·신청·사용하는 환경 | 부록 B |
부록 D. 흔한 오해
본문 곳곳에서 바로잡은 오해를 한곳에 모았다.
처음 공부할 때 가장 많이 헷갈리는 것들이고,
실무에서 잘못된 결정으로 이어지기 쉬운 것들이다.
각 항목은 본문에서 이유와 함께 설명하므로
궁금하면 해당 장을 펼치면 된다.
읽는 방법은 두 가지다.
처음이라면 그냥 훑어보고 넘어가도 된다.
나중에 설계를 앞두고 판단이 서지 않을 때
이 목록을 다시 보는 쪽이 더 도움이 된다.
1. 두 개념을 같은 것으로 보는 오해
| 이렇게 알기 쉽다 | 실제로는 | 다루는 곳 |
|---|---|---|
| Data Product = Data Mesh | 데이터 제품은 개념, 데이터 메시는 운영 방식이다. 메시 없이도 제품은 만들 수 있다 | 13장 |
| CQRS = DB 두 개 | 읽기와 쓰기의 책임을 나누는 것이다. 같은 DB에서도 가능하다 | 9장 |
| CQRS = Event Sourcing | 함께 쓰는 경우가 많을 뿐 서로 다른 패턴이다 | 9장 |
| REST = CRUD | CRUD는 흔한 관례일 뿐이다. 주문 취소처럼 CRUD로 담기 어려운 업무가 많다 | 8장 |
| FaaS = Serverless | FaaS는 서버리스의 한 형태다 | 부록 C |
| MDM = 데이터 통합 | 모으는 것보다 무엇이 같은 대상이고 어떤 값을 믿을지 정하는 일이 핵심이다 | 18장 |
| MDM = 데이터 프로덕트 | MDM 결과를 데이터 프로덕트로 제공할 수 있을 뿐 같은 개념이 아니다 | 18장 |
| 통합 뷰 = MDM | 통합 뷰는 값을 나란히 보여 주고, MDM은 어느 값이 기준인지 판단한다 | 18장 |
| 비즈니스 역량 = Bounded Context | 무엇을 할 수 있는가와 어디까지 같은 모델을 쓰는가는 다른 질문이다 | 5장 |
| DB 변경 = 비즈니스 이벤트 | 잔액이 줄었다는 사실만으로는 주문인지 조정인지 알 수 없다 | 10장 |
| 데이터 민주화 = 보안 완화 | 셀프서비스와 적절한 통제는 함께 간다 | 15장 |
| API = 동기 통신 | 요청을 받고 나중에 처리하는 비동기 API도 있다 | 12장 |
2. 범위를 넓게 잡는 오해
| 이렇게 알기 쉽다 | 실제로는 | 다루는 곳 |
|---|---|---|
| Single Source of Truth = 회사 전체 숫자를 하나로 | 정의마다 권위 있는 출처를 정하는 것이다. 매출도 여러 정의가 모두 옳을 수 있다 | 14장, 18장 |
| Ubiquitous Language = 전사 용어 통일 | Context 안에서 일관되면 된다. Context가 다르면 같은 단어가 다른 뜻일 수 있다 | 13장 |
| Data Mesh = 데이터를 팀별로 나누는 것 | 네 가지 원칙이 함께 있어야 한다. 나누기만 하면 새로운 사일로가 된다 | 3장, 23장 |
| 분산 = 각자 마음대로 | 도메인 자율성과 공통 거버넌스는 함께 간다 | 6장 |
| 복사하면 소유권도 넘어온다 | 원본의 책임은 그대로다. 다만 새로 계산한 값에는 새 소유자가 생긴다 | 6장 |
| Raw Data는 쓸모없다 | 재처리, 장애 복구, 감사에 필요하다. 소비자에게 그대로 던지는 것이 문제일 뿐이다 | 14장 |
| 마이크로서비스는 작을수록 좋다 | 크기가 아니라 경계가 기준이다 | 9장 |
| 데이터가 있으면 쓸 수 있다 | 어디 있고 무슨 뜻이며 믿을 수 있는지 알아야 쓸 수 있다 | 15장 |
| 이벤트는 공짜다 | 중복·순서·재처리·운영이라는 새로운 복잡성이 따라온다 | 12장 |
| Data Lake가 문제를 해결한다 | 저장 문제는 풀지만 소유권과 품질 문제는 남는다 | 2장 |
| GraphQL은 REST 위에서만 동작한다 | DB, gRPC, 캐시 등 다양한 소스를 쓸 수 있다 | 9장 |
3. 반드시 그래야 한다고 보는 오해
| 이렇게 알기 쉽다 | 실제로는 | 다루는 곳 |
|---|---|---|
| 모든 것을 이벤트로 만들어야 한다 | 단순한 시스템에서는 얻는 것보다 운영 비용이 클 수 있다 | 11장 |
| 모든 내부 통신은 Gateway를 거쳐야 한다 | Gateway는 주로 외부 진입점에서 쓴다 | 12장 |
| 실시간으로 만들 수 있으면 실시간이어야 한다 | 실시간성을 높이면 비용과 난이도도 함께 오른다 | 12장 |
| 모든 데이터를 MDM으로 관리해야 한다 | 여러 시스템이 공통으로 쓰고 틀리면 영향이 큰 데이터에만 적용한다 | 18장 |
| 마스터 ID를 모든 시스템이 써야 한다 | 로컬 ID를 유지하고 매핑만 관리해도 된다 | 18장 |
| 운영 시스템은 MDM을 직접 호출해야 한다 | 핵심 거래 경로에 두면 MDM 장애가 곧 서비스 장애가 된다 | 18장 |
| 데이터 프로덕트는 원천 DB를 직접 읽어야 한다 | 신뢰할 수 있는 상위 데이터 프로덕트를 입력으로 써도 된다 | 13장 |
| 다른 도메인 DB는 절대 읽으면 안 된다 | 핵심 비즈니스 로직이 남의 내부 구현에 의존하지 않는 것이 원칙이다 | 7장 |
| 데이터 프로덕트에는 CQRS가 필요하다 | 쓰기 구조와 조회 구조가 크게 다를 때 쓸모가 있다 | 13장 |
| Bronze / Silver / Gold를 따라야 한다 | 널리 쓰이는 패턴일 뿐 필수 구조가 아니다 | 14장 |
| 모든 데이터에 같은 품질 수준이 필요하다 | 정산 금액과 행동 로그에 같은 기준을 적용할 이유가 없다 | 16장 |
| 처음부터 완벽히 자동화해야 한다 | 무엇이 반복되는지는 운영해 봐야 알 수 있다 | 23장 |
| 아키텍트는 모든 기술의 전문가여야 한다 | 전문가와 협력해 전체를 연결하는 능력이 더 중요하다 | 23장 |
4. 도구를 들이면 끝이라고 보는 오해
| 이렇게 알기 쉽다 | 실제로는 | 다루는 곳 |
|---|---|---|
| 저장 기술을 바꾸면 데이터 관리가 된다 | 메타데이터, 소유권, 품질, 거버넌스가 함께 필요하다 | 2장 |
| Kafka를 쓰면 이벤트 기반 아키텍처다 | 설계·소비·스키마·중복·순서·장애 처리까지가 EDA다 | 11장 |
| DLQ를 만들었으니 실패는 처리된다 | 아무도 보지 않는 DLQ는 쓰레기통이다 | 11장 |
| Schema Registry가 있으면 안전하다 | CI에서 호환성을 검증하고 변경 정책을 함께 적용해야 한다 | 10장 |
| 카탈로그를 사면 거버넌스가 된다 | 책임자와 합의된 정의가 먼저다 | 16장 |
| 머신러닝을 쓰면 MDM이 완성된다 | 데이터 모델·품질 규칙·오너십이 먼저 마련되어야 한다 | 18장 |
| Service Mesh가 서비스 구조를 정리해 준다 | 통신의 복잡성을 다룰 뿐 잘못 그은 경계는 고쳐주지 않는다 | 4장 |
| 거버넌스는 기술 프로젝트다 | 역할·책임·프로세스가 함께 바뀌어야 하는 조직 변화다 | 16장 |
5. 하나의 정답이 있다고 보는 오해
| 이렇게 알기 쉽다 | 실제로는 | 다루는 곳 |
|---|---|---|
| 도메인 구조에 정답이 있다 | 자율성과 통제 사이에서 조직에 맞는 균형을 찾는 일이다 | 21장 |
| 중앙집중이냐 탈중앙화냐를 골라야 한다 | 그 사이에 여러 형태가 있고 한 회사 안에서 섞어 쓸 수 있다 | 23장 |
| 도메인은 Peer-to-Peer로 연결해야 한다 | 공통 플랫폼이나 이벤트 플랫폼을 거쳐도 된다 | 21장 |
| 이력 관리에는 정해진 방식이 있다 | 현재 상태만 중요한지, 과거까지 필요한지에 따라 다르다 | 13장 |
| CI/CD 브랜치 전략에는 표준이 있다 | 작게 바꾸고 자주 통합하고 자동으로 검증하는 것이 핵심이다 | 23장 |
6. 끝이 있다고 보는 오해
| 이렇게 알기 쉽다 | 실제로는 | 다루는 곳 |
|---|---|---|
| 아키텍처는 설계하면 끝난다 | 설계·실행·운영·피드백·개선이 계속 반복된다 | 22장 |
| 데이터 아키텍처는 완성할 수 있다 | 비즈니스와 기술이 계속 변하므로 변화에 대응하는 구조를 만드는 일이다 | 23장 |
| 메타데이터는 한 번 정리하면 된다 | 담당팀도 테이블도 정의도 바뀐다. 메타데이터 자체도 낡는다 | 15장 |
| 플랫폼 팀이 다 해 주면 된다 | 모든 요청이 몰리면 플랫폼 팀이 새 병목이 된다 | 22장 |
| 거버넌스는 중앙이 통제하는 것이다 | 여러 팀이 안전하고 일관되게 일하도록 돕는 것이 목적이다 | 22장 |
| 아키텍트는 규칙을 집행한다 | 위험을 설명하고 대안을 제시해 좋은 결정을 돕는 역할에 가깝다 | 23장 |