앞 장의 설비 정지가 남긴 이벤트를 따라갑니다. 이벤트 스토어와 아웃박스, Kafka, 서비스를 넘는 인과 추적, 스트림 재생, 시점 조회, 프로젝션 재구축을 이벤트 소싱 탐색기에서 직접 봅니다.
무엇을 · 왜#
보통의 MES 는 현재 값을 덮어씁니다. 그러면 왜 바뀌었는지, 그때 상태가 어땠는지를 나중에 알기 어렵습니다. uEngine MES 는 값 대신 일어난 사실(이벤트)을 추가만 하며 저장하고, 현재 상태와 조회 화면은 이벤트에서 계산합니다.
| 개념 | 뜻 | 이 장에서 보는 곳 |
|---|---|---|
| 이벤트 스토어 | 서비스마다 있는 추가 전용 원장. 수정·삭제 없음 | 이벤트 스토어 탭 |
| 아웃박스 | 이벤트와 같은 트랜잭션에 기록해, 저장과 발행이 어긋나지 않게 함 | 이벤트 스토어 탭 아래 |
| 상관(correlation) · 원인(causation) | 한 업무로 묶는 ID와, 직접 원인 이벤트를 가리키는 ID | 프로세스 추적 |
| 시점 조회 | 어느 시각의 상태를 이벤트 재생으로 복원 | 모니터링 |
| 프로젝션 재구축 | 조회용 읽기 모델을 지우고 이벤트로 다시 만듦 | 프로젝션 재구축 탭 |
앞 장 설비 이상 대응을 먼저 따라 하면 같은 사건을 보게 됩니다. 건수와 시각은 환경의 상태에 따라 다릅니다.
따라 하기#
- 탐색기 열기. 오른쪽 위 분기 아이콘으로 이벤트 소싱 탐색기를 엽니다. 오른쪽 위에 프로세스 추적, 이벤트 스토어, Kafka, 스트림 재생, 프로젝션 재구축 탭이 있습니다.

이벤트 소싱 탐색기 - 서비스별 이벤트 스토어. 이벤트 스토어 탭을 엽니다. 서비스 10개의 카드에 쌓인 이벤트 수와 스트림 수가 있습니다. 녹화 때는 설비 26건, 생산 183건, 영업 345건이었습니다.

서비스별 이벤트 수 - 원본 행 보기. 생산 카드를 누릅니다.
production.event_store의 최신 60건이 나옵니다.global_seq, 애그리거트, 버전, 이벤트 유형, 사용자, correlation, causation 입니다. (테넌트, 애그리거트 유형, 애그리거트 ID, 버전)의 유니크 키가 동시 변경 충돌을 막습니다.
production.event_store - 판단 근거 보기. 표에서 앞 장의
WorkOrderRescheduled행을 누릅니다. 오른쪽 metadata (판단 근거) 에 사유(reason), 화면(screen), 사용자, 승인자(approvedBy)가 있습니다. 같은 표에는 용접 시나리오의 에이전트(weld-exec-agent)가 남긴 재계획도 있으니 사용자가 게스트인 행을 고릅니다.
재계획 이벤트의 메타데이터 - 아웃박스 보기. 아래
production.outbox는 이벤트와 같은 트랜잭션에 기록됩니다. 릴레이가 이 표를 읽어 Kafka 로 발행합니다. created, published, 지연 칸으로 발행까지 걸린 시간을 봅니다.
production.outbox - Kafka 토픽. Kafka 탭을 엽니다. 서비스마다
mes.<서비스>.events토픽이 있고 파티션은 3개(P0~P2)입니다. 메시지 키가테넌트:애그리거트ID라서 같은 작업지시의 이벤트는 같은 파티션에서 순서가 유지됩니다.mes.anomaly.events는 이상 신호만 모으는 토픽입니다.
Kafka 토픽 - 프로세스 추적. 프로세스 추적 탭 왼쪽 목록에서 설비 정지를 누릅니다. 이벤트 4건이 서비스 3곳(설비, 분석, 생산)의 레인에 펼쳐집니다. 점선 화살표가 Kafka 를 건너간 원인과 결과입니다. 목록을 누르면 최신 자동 추적이 꺼져 화면이 고정됩니다.

프로세스 추적 - 이벤트의 여정. 설비 정지 카드를 누릅니다. 오른쪽에 ① 이벤트 스토어 저장, ② 아웃박스 발행(
mes.equipment.events와mes.anomaly.events두 토픽), ③ Kafka 전송(파티션과 오프셋), ④ 구독 서비스 반응이 나옵니다. 생산과 분석 서비스가 각각 후속 이벤트 1건을 만들었습니다.
설비 정지 이벤트의 여정 - 원인 확인. 생산 영향 분석 카드를 누르고 이벤트 엔벨로프를 봅니다.
user는production-service,trigger는equipment.EquipmentStopped입니다.causationId는 설비 정지 이벤트의eventId와 같고,correlationId도 설비 정지와 같습니다.
영향 분석 이벤트의 엔벨로프 - 스트림 재생. 스트림 재생 탭에서 작업지시 목록의 2610-0002 를 누르고 처음부터 재생을 누릅니다. 버전이 한 단계씩 올라가며 오른쪽 상태가 바뀝니다. 강조된 칸이 그 이벤트로 바뀐 값입니다. 현재 상태는 저장된 값이 아니라 이 이벤트들을 차례로 적용한 결과입니다.

스트림 재생 - 시점 조회. 모니터링에서 해소 포함을 켜고 설비 정지 사건을 고른 뒤, 판단 근거 · 실행 이력의 생산 영향 분석을 누릅니다. 위쪽에 그 시각의 공장 상태 안내가 나오고, CNC-M01 타일이 정지로 돌아옵니다. 녹화 때 안내는 「보류 작업지시 0건 · 미해소 이상 1건」이었습니다. 현재로를 누르면 지금 상태로 돌아옵니다.

시점 조회 - 프로젝션 재구축. 탐색기의 프로젝션 재구축 탭에서 설비를 고르고 읽기 모델 삭제 후 이벤트로 재구축을 누릅니다. 왼쪽이 재구축 전, 오른쪽이 이벤트 재생 결과입니다. 위쪽 띠에 재구축 결과 동일이 나오면 두 표가 같다는 뜻입니다.

프로젝션 재구축 결과
화면을 읽을 때
- 시점 조회가 복원하는 것은 설비 타일과 위쪽 안내 줄입니다. 위쪽 지표, 이상 상황 목록, 실시간 이벤트는 지금 값 그대로입니다.
- 재구축의 재생 건수는 모든 테넌트 기준입니다. 설명 문구의 건수는 지금 테넌트 기준이라, 녹화 때 26건과 27건으로 달랐습니다(다른 테넌트 설비 등록 1건).
- 재구축은 읽기 모델을 지우고 다시 만듭니다. 시연 환경을 여럿이 함께 쓰고 있다면 다른 사람의 작업이 도는 동안에는 누르지 않습니다.
확인 문제#
- 저장과 발행이 어긋나지 않게 하는 장치는 무엇이며, 어떻게 동작하나요?
- 생산 영향 분석이 설비 정지 때문에 일어났다는 것을 어떤 값으로 확인하나요?
- 스트림 재생에서 강조된 칸은 무엇을 뜻하나요?
- 읽기 모델을 지워도 괜찮은 이유는 무엇인가요?
정답
- 트랜잭셔널 아웃박스입니다. 이벤트와 같은 트랜잭션에 아웃박스 행을 기록하고, 릴레이가 그 행을 읽어 Kafka 로 발행합니다.
- 생산 영향 분석 이벤트의
causationId가 설비 정지 이벤트의eventId와 같습니다.correlationId도 같습니다. - 그 이벤트를 적용해 값이 바뀐 필드입니다.
- 읽기 모델은 이벤트에서 파생된 값이라, 이벤트 스토어만 있으면 다시 만들 수 있기 때문입니다.