이번 작업에서는 제조 이벤트가 발생하면 AGV가 실시간으로 출발하고, 공정 흐름도에 즉시 반영되는 기능을 구현했다.
단순히 AGV를 움직이는 것이 아니라 Assembly Service → Kafka → Main Backend → Redis → WebSocket → Frontend까지 하나의 이벤트가 여러 서비스를 거쳐 화면에 표시되는 전체 흐름을 구성하는 것이 목표였다.
최종적인 데이터 흐름은 아래와 같다.
Manufacturing Event
│
▼
Assembly Service
(Process Risk Analysis)
│
▼
Kafka
(factory.manufacturing.analysis)
│
▼
Main Backend
│
├── AGV Dispatch
├── Redis 저장
└── WebSocket Push
│
▼
Frontend Process Flow
기존에는 공정 흐름도가 모두 하드코딩되어 있었지만, 이번 작업을 통해 제조 이벤트가 발생하면 실제 AGV가 출발하고 화면에서도 실시간으로 움직이도록 변경하였다.
처음에는 같은 이벤트인데도 어떤 이벤트는 AGV가 출발하고, 어떤 이벤트는 출발하지 않는 문제가 있었다.
원인을 확인해보니 하나의 Kafka Topic에서
등 여러 종류의 분석 결과가 함께 전달되고 있었다.
AGV 제어는 Process Risk Analysis 결과만 사용하도록 수정하였다.
if (!PROCESS_RISK_ANALYSIS.equals(event.analysisType())) {
return;
}
그리고 위험 공정으로 판단된 경우에는 AGV를 출발시키지 않도록 구현하였다.
if (event.analysisResult().isAbnormal()) {
return;
}
이렇게 수정하면서 AGV 출발 조건을 명확하게 분리할 수 있었다.
AI 분석 결과는 동일한 eventId가 여러 번 전달될 수 있다.
동일 이벤트가 여러 번 처리되면 AGV도 중복 출발할 수 있기 때문에 Redis를 이용하여 Duplicate 처리를 추가하였다.
redisTemplate.opsForValue().setIfAbsent(
PREFIX + eventId,
"1",
Duration.ofMinutes(1)
);
Redis의 SETNX를 이용하여 동일한 eventId는 최초 한 번만 처리하도록 구현하였다.
이번 작업에서 가장 오래 걸렸던 부분이다.
DB에서는
analysis_status = ABNORMAL
인데 AGV는 정상적으로 출발하는 현상이 발생하였다.
원인을 확인해보니 Assembly Service에서는
등도 모두 ABNORMAL로 처리하고 있었지만,
Main Backend에서는
analysisResult.isAbnormal()
만 기준으로 AGV를 제어하고 있었다.
즉, 서비스마다 ABNORMAL을 판단하는 기준이 달랐다.
최종적으로는 isAbnormal 값만 AnalysisStatus를 ABNORMAL로 변경하도록 수정하여 Main Backend와 동일한 기준을 사용하도록 변경하였다.
Frontend도 기존 하드코드를 제거하고 WebSocket(STOMP)을 통해 실시간 데이터를 수신하도록 변경하였다.
Backend에서는
DB
+
Redis
↓
AgvOperationResponse
↓
WebSocket
↓
Frontend
형태로 데이터를 전달한다.
AGV의 위치와 상태는 WebSocket을 통해 실시간으로 갱신된다.
WebSocket만 사용할 경우 새로고침하거나 다른 페이지를 이동한 뒤 다시 들어오면 AGV가 하나도 보이지 않는 문제가 있었다.
이를 해결하기 위해
GET /api/main/process-flow
API를 추가하였다.
페이지 진입 시
REST API
↓
현재 AGV 상태 조회
↓
WebSocket 연결
↓
실시간 업데이트
순서로 동작하도록 수정하였다.
덕분에 페이지를 다시 진입해도 현재 운행 중인 AGV 상태를 그대로 복원할 수 있게 되었다.
이번 작업을 통해 Process Flow도 실시간 데이터 기반으로 변경하였다.
현재 AGV 상태는
총 4가지 상태를 표현한다.
오른쪽 관제 현황에서는
AGV 수를 실시간으로 집계하도록 구현하였다.
또한 전체 AGV 수는 항상 20대로 유지되도록 수정하였다.
이번 작업을 통해
제조 이벤트 발생
↓
Kafka 전달
↓
Main Backend AGV Dispatch
↓
Redis 상태 저장
↓
WebSocket Push
↓
Frontend 실시간 공정 흐름도 반영
까지 하나의 흐름을 구성하였다.
여러 서비스가 하나의 이벤트를 중심으로 연결되어 동작하는 구조를 직접 구현할 수 있었다.
이번 작업에서 가장 어려웠던 부분은 기능 구현 자체보다 서비스 간 상태 기준을 맞추는 것이었다.
처음에는 단순히 AGV가 출발하는 조건의 문제라고 생각했지만, 실제 원인은 Assembly Service와 Main Backend가 같은 데이터를 서로 다른 기준으로 해석하고 있었기 때문이었다.
MSA 환경에서는 기능 구현뿐만 아니라 서비스 간 데이터의 의미와 기준을 동일하게 유지하는 것이 중요하다는 점을 다시 한번 확인할 수 있었다.
이번 작업을 통해 Kafka 기반 이벤트 처리, Redis를 이용한 상태 관리, WebSocket을 활용한 실시간 화면 구성까지 하나의 흐름으로 연결해볼 수 있었고, 이벤트 기반 아키텍처를 실제 프로젝트에 적용하는 경험을 할 수 있었다.