본문으로 건너뛰기
김민찬 포트폴리오

시뮬레이션 재생 동기화

공통 pose 모델로 리포트와 Konva 맵의 시각·카트·위치를 동기화했습니다.

배경

시뮬레이션 결과는 병목 리포트와 공장 맵에 함께 표시됩니다. 리포트에서 선택한 카트가 특정 시각에 어디에 있었는지 맵에서 바로 확인할 수 있어야 했습니다.

문제

  • 백엔드는 이동 구간을 segment 목록으로 전달했지만, 화면에서는 카트가 직선과 곡선 도로를 따라 움직여야 했습니다.
  • 리포트와 맵이 각자 보간하면 같은 시각에 서로 다른 위치를 보여줄 수 있었습니다.
  • 배속, seek, 카트 선택이 바뀌어도 두 화면의 현재 시각은 같아야 했습니다.

설계

pose와 경로 계산을 simulationCartMovement.ts에 모았습니다. 리포트와 Konva 맵은 이 모듈이 반환한 같은 값을 사용합니다. 화면별로 좌표를 다시 계산하지 않았습니다.

타임라인을 pose로 변환해 리포트와 맵에 공유하는 구조
flowchart LR
timeline["TMS timeline JSON"] --> movement["pose / 경로 계산"]
movement --> playback["rAF 재생 루프"]
playback --> report["병목 리포트"]
playback --> map["Konva 공장 맵"]
control["배속 / seek / 카트 선택"] --> playback

경로 보간

segment의 시작점과 끝점을 도로 형태에 맞게 보간했습니다. LINE 구간은 선형 보간하고, 코너는 2차 베지어와 호 길이 샘플링으로 이동 거리를 맞췄습니다. 방향이 바뀐 때는 360도 최단각을 기준으로 회전값을 계산했습니다.

재생 상태

requestAnimationFrame으로 재생 시각을 갱신하고 배속과 seek를 같은 시계에 반영했습니다. 카트 선택은 보여주는 대상만 바꾸고, 현재 시각은 유지합니다.

API 경계

백엔드의 스트리밍 방식이 확정되기 전에도 시연을 준비할 수 있도록 execute, subscribe, getResult, dispose로 인터페이스를 먼저 정했습니다. Mock 스트림과 실제 API는 같은 계약을 사용했습니다.

검증

  • 리포트에서 카트를 선택하면 맵이 같은 대상을 따라갑니다.
  • 타임라인을 seek해도 리포트와 맵의 시각과 pose가 같습니다.
  • 배속을 바꿔도 두 화면은 하나의 재생 시계를 사용합니다.

남은 일

API 계약, 대량 카트 성능, 맵 레이어 우선순위는 추가로 검증해야 합니다. 초기 구현은 fixture와 Mock 스트림을 기준으로 작성했습니다.

전달

프론트엔드 리드와 스크럼 마스터를 맡아 연동 조건과 선행 업무를 조율했습니다. 1·2차 PoC 프론트엔드 요구사항을 완료했고 프로젝트 수주에 기여했습니다.