Data 분해는 source 간 상호작용이 없거나 격리가 절대적일 때 선택한다
·수정 1회
요약
- 여러 source를 처리하는 작업은 Task 분해(stage 단위)와 Data 분해(source 단위) 둘 중 하나를 선택한다.
- Data 분해는 source끼리 합치거나 비교할 일이 없고, 한 source의 장애가 다른 source에 영향을 주면 안 될 때 적합하다.
- "source 합쳐서 가공" 작업은 Task 분해, "source끼리 섞을 일 없음 + 격리 절대적"이면 Data 분해.
본문
두 분해 방식의 차이
같은 작업을 source별로 같은 파이프라인 전체를 반복하면 Data 분해, 단계를 가로질러 모든 source 데이터를 한꺼번에 처리하면 Task 분해다.
[Data 분해] [Task 분해 / Stage]
for each source: Stage 1: 모든 source에서 fetch
fetch → transform → save Stage 2: 모든 데이터 transform
Stage 3: dedup + save
Data 분해가 우월한 7가지 시나리오
-
source 간 상호작용이 없을 때
- dedup, cross-reference, fan-in 불필요
- 예: 지점별 매출을 지점별 destination에 저장 — 합칠 일 없음
-
source별 정책이 완전히 다를 때
- 스케줄, destination, retry, 보존 기간이 모두 다름
- 예: A→S3(hourly), B→BigQuery(daily), C→Kafka(realtime)
-
격리(blast radius)가 최우선일 때
- 한 source의 장애·느림이 다른 source 처리를 절대 막으면 안 됨
- 예: 멀티 테넌트 ETL — A 테넌트 폭증이 B 테넌트 SLA를 깨면 안 됨
-
메모리/streaming 제약이 있을 때
- 전체 데이터셋을 한 번에 메모리에 못 둠
- source 단위로 끊어야 OOM 회피
- 예: 수십 GB 일별 access log → hour chunk로 처리
-
scale-out 단위가 source일 때
- source = sharding key, 분산 worker로 수평 확장
- 예: 100개 region 데이터 → region별 worker pod
-
부분 결과의 즉시성이 중요할 때
- source 1개 끝나자마자 dashboard 반영 필요
- 전체 stage 완료를 못 기다림
- 예: realtime monitoring, alert
-
source 단위 idempotency / 재실행 boundary
- "어제 4001 포트 수집만 실패했으니 그것만 재실행" 같은 운영 단위
- source가 자연스러운 replay boundary
결정 휴리스틱
| 질문 | Yes → Data | No → Task |
|---|---|---|
| source 간 데이터 합칠 일이 없나? | ✅ | |
| 한 source 실패가 다른 source를 절대 막으면 안 되나? | ✅ | |
| source별 처리 정책/destination이 다른가? | ✅ | |
| streaming/메모리 제약이 큰가? | ✅ | |
| source 단위로 분산/확장할 건가? | ✅ | |
| cross-source dedup / join이 필요한가? | ✅ | |
| 확장 시 새 source 추가가 빈번한가? (인터페이스화 이득) | ✅ | |
| 정해진 SLA window에 전체 한 번에 끝내야 하나? | ✅ |
한 줄 판단 기준
source끼리 섞을 일이 없거나 격리가 절대적이면 Data 분해, source를 합쳐서 가공해야 하면 Task 분해.
안티패턴
- 격리만 보고 Data 분해 선택 후 cross-source dedup 요구사항 추가됨 → source별로 모은 데이터를 나중에 또 모아서 dedup하는 우회 로직이 생긴다. 격리는 Task 분해에서도
Promise.allSettled로 source 단위로 확보할 수 있으므로 dedup 요구사항이 보이면 Task 분해를 우선 고려해야 한다. - 확장성 = Data 분해라고 착각 → 새 source 추가가 빈번한 경우 오히려 Task 분해에서 Fetcher 인터페이스 하나만 늘리는 게 더 단순하다. 확장성은 분해 축과 별개로 인터페이스 설계 문제다.
관련 노트
- 동시성 프로그래밍 모델
- 배치 작업의 Promise 병렬화는 Pipeline보다 Stage-by-stage가 안전하다
- 배치 시스템 설계
- 동시성 카운터 업데이트는 Fanout 패턴으로 row lock 경합을 분산한다
참고
함께 읽기 좋은 글
- 배치 작업의 Promise 병렬화는 Pipeline보다 Stage-by-stage가 안전하다
- 팬아웃은 push로 미리 꽂고 pull로 즉석에서 합치는데, 유명인만 pull로 빼는 하이브리드가 답이다
- UPDATE WHERE 조건부 갱신은 SELECT FOR UPDATE보다 lock 대기 없이 동시성 경합을 해결한다
- HTTP fan-out 동시성 캡은 TCP 연결 풀로 걸어야 ephemeral port가 안 터진다
- INSERT ON DUPLICATE KEY UPDATE는 UNIQUE 인덱스 충돌을 에러가 아닌 UPDATE 트리거로 바꾸는 절이다