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

Agent UI 공통 패키지

Agent 제품마다 반복하던 입력·실행·결과 UI를 npm 패키지로 묶어 공통 영역의 약 60%를 재사용했습니다.

배경

Agent마다 입력과 결과 형식은 달랐지만, 사용자가 입력하고 실행한 뒤 결과를 확인하는 흐름은 같았습니다. 화면을 복사해서 새 제품을 만들면 공통 동작이 바뀔 때마다 여러 저장소를 함께 수정해야 했습니다.

문제

  • 입력 UI와 실행 상태, 결과 화면을 제품마다 다시 구현했습니다.
  • 에러 처리 기준이 바뀌면 여러 저장소에 같은 수정을 반복했습니다.
  • 새 제품을 시작할 때마다 상태와 화면 구조가 조금씩 달라졌습니다.

선택

화면 일부만 공통 컴포넌트로 만드는 대신, 컴포넌트와 Hook, 상태 규약을 함께 npm 패키지로 배포했습니다. 공통 실행 흐름은 한 곳에서 고치되 고객사별 입력과 결과 형식은 각 앱이 소유하도록 경계를 정했습니다.

구현

반복되던 동작을 @ara/agent-ui 패키지로 분리했습니다. 제조 MLOps, 유통, 의료 등 세 도메인에 걸친 Agent 제품 4종은 이 패키지를 설치하고 도메인 전용 UI만 추가합니다.

공통 패키지를 Agent 제품에서 사용하는 구조
flowchart TB
pkg["@ara/agent-ui npm"]
subgraph package [Published package]
  common[Common UI]
  core[Hooks + Zustand stores]
  parsers[Stream parsers + query keys]
end
pkg --> package
package --> mlops[제조 MLOps]
package --> retail[유통]
package --> medical[의료]

공통 흐름과 레이어

사용자 흐름과 패키지 경계
flowchart LR
subgraph flow [공통 사용자 흐름]
  in[입력] --> run[실행]
  run --> out[결과 동기화]
end
subgraph pkg [npm package]
  L1[Common]
  L2[Execution hooks]
  L3[State stores]
end
subgraph app [Consumer app]
  D[Domain UI only]
end
pkg --> app
flow -.-> pkg

실행 상태와 도메인 확장

패키지는 idle, running, success, error 상태를 공통으로 관리합니다. SSE, WebSocket, polling 같은 전송 방식과 결과 화면은 제품별 요구에 맞게 앱에서 구현합니다.

공통 실행 상태와 도메인별 구현
flowchart TB
state["공통 상태: idle → running → success / error"]
state --> ml[제조 MLOps]
state --> rt[유통]
state --> md[의료]
ml --> ml_run["SSE + Workflow 폴링"]
ml --> ml_out["실행 큐 · 로그"]
rt --> rt_run["SSE parser"]
rt --> rt_out["매칭 · 다운로드"]
md --> md_run["WebSocket partial"]
md --> md_out["Question · Report"]
도메인 패키지에서 가져옴 앱에서만 구현
제조 MLOps Common, execution store, SSE Hook Workflow 노드 입력, 큐와 로그 패널
유통 stream store, SSE parser, Common 엑셀 업로드, 매칭 결과 버블
의료 stream store, agent parser, Common 선택지 UI, 리포트와 지식 그래프

공통 UI와 store, 실행 Hook, parser를 패키지에서 가져오는 비율을 기준으로 재사용 영역을 약 60%로 추정했습니다. API schema와 event type, 결과 렌더링, 인증, routing은 고객사 요구가 달라 각 앱에 남겼습니다.

결과

  • Agent 제품 4종에 공통 패키지를 적용했습니다.
  • 공통 영역의 약 60%를 재사용했습니다. 패키지와 앱 전용 화면의 비율을 기준으로 한 추정치입니다.
  • 공통 동작은 패키지 한 곳에서 수정하고 버전으로 배포할 수 있게 됐습니다.

AI 코딩 도구 활용

Codex에는 기존 상태 흐름과 제품별 변경 지점, 공통화하지 않을 API 경계를 먼저 제공했습니다. 생성된 변경은 바로 병합하지 않고 다음 항목을 확인했습니다.

  1. 컴포넌트와 Hook의 책임이 기존 규약과 맞는지 diff에서 확인
  2. TypeScript 타입과 테스트로 계약 변경 확인
  3. 각 앱에서 입력, 실행, 결과, 에러 흐름을 브라우저로 확인
  4. 도메인 schema나 상태 소유권까지 패키지로 옮긴 제안은 직접 수정

반복 코드를 정리하고 변경 후보를 만드는 데 AI를 사용했지만, 패키지 경계와 실제 채택 여부는 제품 요구를 기준으로 판단했습니다.

다음 단계

  • semver와 CHANGELOG 기준을 정리해 앱 사이의 의존성 충돌을 줄입니다.
  • breaking change가 있을 때 패키지 README에 migration guide를 함께 제공합니다.