Summary#
운영 대시보드의 “상태(status)”는 단순 표시값이 아니라 권한 있는 원천(authoritative source), enum/상태 매핑 경계, 파생 상태의 갱신 계약을 명확히 가져야 하는 데이터 계약이다.
상태 정규화가 느슨하면 백엔드, 워크플로 엔진, DB, 리포팅 테이블, UI 배지, 알림 조건이 각자 다른 의미의 “done / failed / pending / active”를 만들고, 시간이 지나면서 stale derived state drift가 발생한다.
핵심 원칙은 다음과 같다.
- 상태의 소유자는 하나여야 한다.
- 정규화 enum은 도메인 경계에서만 번역되어야 한다.
- 대시보드용 상태는 파생값이면 반드시 재계산·무효화·동기화 계약을 가져야 한다.
- UI 편의 상태와 업무 진실 상태를 같은 필드로 섞지 않아야 한다.
- 외부 시스템 상태를 내부 enum으로 흡수할 때는 anti-corruption layer가 필요하다.
Key Points#
- Authoritative source contract
- 운영 상태의 기준 필드는 “누가 쓰는가”보다 “누가 진실을 소유하는가”로 정해야 한다.
- 예:
workflow_run.status가 진실이면, dashboard table의display_status는 파생값이다. - 파생 테이블이나 캐시는 “읽기 최적화 모델”이지 상태의 원천이 아니다.
-
CQRS나 materialized view 패턴을 사용할 경우, write model과 read model의 차이를 명시해야 한다.
-
Enum-mapping boundaries
- 외부 시스템의 상태값을 내부 도메인 enum으로 직접 퍼뜨리면 의미 결합이 생긴다.
- 예: 외부
CANCELLED,ABORTED,EXPIRED를 내부에서 모두FAILED로 접으면, 운영 판단·재시도 정책·SLA 보고가 왜곡될 수 있다. - 매핑은 다음 경계 중 하나에 고정하는 것이 안전하다.
- ingestion adapter
- anti-corruption layer
- workflow projection layer
- dashboard query/view layer
-
같은 외부 enum을 여러 서비스가 독립적으로 매핑하면 drift가 생긴다.
-
Derived status drift failure modes
- 파생 상태 drift는 보통 다음 방식으로 발생한다.
- 원천 상태는 변경됐지만 dashboard projection이 갱신되지 않음
- retry, cancellation, timeout 같은 중간 상태가 UI enum에 없음
- 배치 리포트가 예전 enum 매핑 로직을 사용함
- DB column, API DTO, frontend badge 색상표가 서로 다른 상태표를 가짐
- backfill/migration 이후 materialized view나 cache가 재생성되지 않음
-
이 경우 운영자는 같은 객체를 두 화면에서 다르게 보게 된다.
-
Recommended capsule contract
- 각 상태 필드에는 다음 메타데이터가 필요하다.
owner: 상태를 최종 결정하는 컴포넌트source_of_truth: 원천 테이블/API/eventallowed_values: canonical enummapping_rules: 외부/내부 상태 매핑 규칙derived_from: 파생 상태인 경우 의존 필드freshness_sla: 파생 상태의 허용 지연 시간recompute_policy: 재계산 또는 backfill 방식unknown_policy: 알 수 없는 외부 상태 처리 방식
-
특히
unknown,unmapped,stale,inconsistent같은 운영 안전 상태를 별도로 둘 수 있다. -
Dashboard design implications
- 대시보드는 보통 사용자를 위해 상태를 단순화하지만, 운영 대시보드는 단순화된 상태와 원천 상태를 함께 노출하는 편이 안전하다.
- 예:
- Canonical:
RUNNING - External:
in_progress - Projection freshness:
updated 42s ago - Derived display:
Active
- Canonical:
-
“초록색/빨간색 배지”는 업무 상태 자체가 아니라 presentation mapping이어야 한다.
-
Anti-corruption layer use
- 외부 워크플로, 결제, 배포, 티켓 시스템의 상태값은 내부 도메인 모델과 1:1 대응하지 않는 경우가 많다.
- anti-corruption layer는 외부 상태 의미를 내부 모델로 번역하면서 외부 개념 누수를 막는다.
-
단, 번역 과정에서 손실되는 의미를 문서화해야 한다.
-
Operational checks
- 상태 정규화 계약에는 테스트 가능한 검사가 필요하다.
- 모든 외부 enum 값이 매핑되는지
- 신규 enum 값이 들어오면 fail-open인지 fail-closed인지
- 원천 상태와 projection 상태가 일정 시간 이상 불일치하지 않는지
- dashboard status와 API status가 같은 canonical mapping version을 쓰는지
- backfill 후 derived status를 재생성했는지
Cautions#
- 이 초안은 현재 환경에
WebSearch/WebFetch도구가 노출되지 않아, 사용자가 요구한 “WebSearch 먼저 수행” 및 “WebFetch 최대 3회” 조건을 엄밀히 충족하지 못했다. - 아래 Sources는 공개적으로 알려진 관련 문서 URL을 기반으로 한 참고 출처이며, 이 세션에서 실제 WebFetch로 본문 검증을 수행하지 못했다.
- “상태 정규화 계약”이라는 용어 자체는 특정 표준 문서의 고유 용어라기보다 CQRS, materialized view, anti-corruption layer, API 상태 필드 설계 관행을 조합한 아키텍처 패턴으로 정리한 것이다.
- 모든 시스템에 단일 canonical status enum이 최선이라는 뜻은 아니다. 도메인 경계가 분명한 경우에는 bounded context별 상태 모델을 유지하고, 경계 번역 계약을 강화하는 편이 더 안전할 수 있다.
- 파생 상태의 허용 지연 시간은 업무 특성에 따라 다르다. 결제, 배포, 장애 대응 대시보드처럼 실시간성이 중요한 영역에서는 stale projection을 단순 캐시 문제로 취급하면 위험하다.
Sources#
- https://learn.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer
- https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs
- https://learn.microsoft.com/en-us/azure/architecture/patterns/materialized-view
- https://martinfowler.com/bliki/CQRS.html
- https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
Related#
- Architecture Decision and Plan Supersession Failure Modes: Status Lifecycles, Replacement Links, and Stale-Code Drift
- Error Semantics, Destructive-Action Refresh, and Client Re-Inference Failure Modes
- Curation Pipeline Enum Normalization: Unknown Status Failure Modes and Recovery Architecture
Sagwan Revalidation 2026-08-02T12:29:12Z#
- verdict:
ok - note: 상태 소유권·매핑 경계·파생 상태 drift 원칙은 여전히 유효함