Skip to content

component dashboard web

JJong-03 edited this page Jun 11, 2026 · 3 revisions

Dashboard Web

apps/dashboard-web에 구현된 본사 관제용 React SPA의 구성과 데이터 흐름을 설명한다.

기술 구성

영역 구현
빌드 Vite 6, TypeScript 5.6
UI React 18, React Router 6
차트 Recharts
아이콘 Lucide React
인증 클라이언트 oidc-client-ts
보고서 내보내기 docx 동적 import, 브라우저 인쇄/PDF
테스트 Vitest

진입점은 src/main.tsx, route 정의는 src/App.tsx, 공통 shell은 src/components/Layout.tsx다.

Route

Route 화면 인증
/login Cognito 로그인 시작 불필요
/callback Authorization Code callback 처리 callback 처리 중
/ Fleet 전체 개요 필요
/factory/:factoryId 공장 상세 필요, 공장 권한은 Backend가 강제
/cloud-infra Cloud Infra 상태 필요, System 권한은 Backend가 강제
/image-snapshots AI 이벤트 이미지 스냅샷 갤러리 필요, System 권한은 Backend가 강제
/chat AI 채팅 어시스턴트 필요, 공장/System 범위는 Backend가 강제
/reports 일간 보고서 필요
/admin/users 사용자 관리 필요, 사용자 관리 권한은 Backend가 강제
그 외 /로 이동 결과적으로 인증 필요

RequireAuth는 브라우저에 만료되지 않은 OIDC user가 있는지만 확인한다. SPA route 자체에는 역할별 route guard가 없다. Sidebar 조건부 메뉴는 사용성을 위한 숨김이며, 권한의 최종 경계는 Backend의 401/403이다.

인증 흐름

src/auth/auth.ts는 Cognito Hosted UI와 OIDC Authorization Code flow를 사용한다. oidc-client-ts가 code flow의 PKCE 생성과 검증을 담당한다.

관련 환경 변수:

VITE_COGNITO_AUTHORITY
VITE_COGNITO_DOMAIN
VITE_COGNITO_CLIENT_ID
VITE_COGNITO_REDIRECT_URI
VITE_COGNITO_LOGOUT_URI
VITE_API_BASE_URL
VITE_WS_BASE_URL

OIDC manager 생성에는 authority, client ID, redirect URI가 필수다. Cognito domain은 logout 시 필요하고, logout URI는 redirect URI로 fallback한다. API/WS base URL은 미설정 시 각각 현재 origin 상대 경로와 WebSocket offline 상태를 사용한다.

요청 scope는 openid email profile이며 silent renew를 사용한다. REST 요청은 access token을 Authorization: Bearer header에 넣는다. WebSocket은 브라우저 제약 때문에 ?token=<JWT> query parameter를 사용한다.

코드 계층

디렉터리 역할
auth/ Cognito 로그인, callback, token, logout
api/ REST client, 응답 타입, AuthError/ApiError
hooks/ fetch 상태, 메모리 cache, refresh, WebSocket 연결
adapters/ Backend 응답을 화면 모델과 label로 정규화
utils/ 상태/시간/추이, history 병합, Timeline, Markdown, DOCX
components/ Shell, Sidebar, badge, chart, 연결 상태, error boundary
pages/ route별 실제 화면

Hooks는 마지막 성공 데이터를 메모리에 유지하는 stale-while-revalidate 성격을 가진다. 공장/공장 이력/Cloud Infra 이력은 route 이동 때 cache를 재사용하며, 강제 refresh 시 since 이후 이력을 받아 timestamp 기준으로 병합한다.

REST와 WebSocket

주요 REST 호출:

GET    /auth/me
GET    /factories
GET    /factories/{factory_id}
GET    /factories/{factory_id}/history
GET    /cloud-infra
GET    /cloud-infra/history
GET    /image-snapshots/range
GET    /image-snapshots
POST   /chat/query
GET    /reports
GET    /reports/{date}/{factory_id}
GET    /admin/users
POST   /admin/users
PATCH  /admin/users/{user_id}
DELETE /admin/users/{user_id}

공장 상세는 GET /factories/{id}와 10분 history를 먼저 표시한다. 이후 /ws/factories/{id}에서 Redis Pub/Sub update를 받아 현재 화면과 10분 추이에 추가한다. 연결 상태는 connecting, connected, reconnecting, offline으로 표시하며 최대 5회 지수형 재연결을 시도한다.

WebSocket이 끊겨도 REST 수동/자동 새로고침은 별도로 동작한다. 자동 새로고침 선택지는 Off, 5s, 10s, 30s, 1m이다.

보고서

Reports 화면은 Backend가 S3에서 읽은 Markdown 원문을 받는다. 공통 parser가 다음 subset을 화면, 인쇄 HTML, DOCX에 동일하게 적용한다.

  • 제목 h1~h3
  • 문단
  • 순서/비순서 목록
  • pipe table
  • bold와 inline code

PDF 버튼은 새 창의 인쇄 dialog를 열고, Word 버튼은 실제 Office Open XML .docx를 브라우저에서 생성한다. docx 패키지는 Word 내보내기를 누를 때만 동적으로 로드한다.

System 권한 사용자는 공장 selector와 별도로 cloud-infra 보고서를 선택할 수 있다. 이 선택지는 Sidebar의 Cloud Infra 표시와 같은 /auth/me.can_view_system 값을 사용한다.

이미지 스냅샷 (/image-snapshots)

AI 이벤트 스냅샷을 사람이 검토하는 갤러리 화면이다. System 권한 사용자만 사용한다.

  • 진입 시 GET /image-snapshots/range로 S3 가용 시작 시각을 받아 picker 하한을 맞춘다. 공장 selector와 시작/종료 시각 picker로 범위를 고르면 GET /image-snapshots로 카드 그리드를 갱신한다.
  • 각 카드는 Backend가 만든 presigned GET URL<img loading="lazy">로 표시하고, 클릭 시 새 탭에서 원본을 연다. 메타로 탐지 종류·수정 시각·크기를 보여준다.
  • 권한 부족 시 안내 empty-state를 띄우고 조회하지 않으며, 최종 경계는 Backend 403이다. 빈 범위·S3 지연·오류 상태를 각각 구분한다.

자세한 데이터 경로는 Image Snapshot Pipeline의 대시보드 조회 절을 따른다.

AI 채팅 (/chat)

자연어로 공장 상태·원인·보고서·증빙 이미지를 묻는 대화형 화면이다.

  • 추천 질문/자유 입력(최대 500자)과 공장 selector, 응답 모드(자동·빠른·정밀)를 POST /chat/query로 보낸다.
  • 응답 대기 동안 진행 단계를 표시하고, 답변은 Markdown으로 렌더링한다. 답변 아래 Evidence 패널에 증빙 이미지 / 확인된 값 / 추정 / 데이터 한계를 구분해 보여준다.
  • 데이터 조회와 RBAC 강제는 Backend가 수행한다. Frontend는 결과 envelope(answer/evidence/image_ref/generator/router)를 표시만 한다.

상세 동작은 AI 채팅 어시스턴트를 따른다.

화면 상태

상태 처리
최초 loading spinner와 화면별 loading 문구
refresh 중 기존 성공 데이터를 유지하고 백그라운드 갱신
REST 오류 오류 메시지와 다시 시도 버튼
인증 오류 로그인 화면 이동 동작 제공
빈 Fleet 등록된 공장이 없다는 empty state
빈 history 차트 대신 데이터 없음 안내
보고서 404 아직 생성되지 않은 보고서로 구분
Cloud Infra unavailable available:false를 수집 대기 상태로 표시
stale 공장 snapshot 또는 Cloud fast/slow 수집 지연 badge
unknown 장애로 단정하지 않고 미확인 회색 상태와 errors[] 표시

Cloud Infra의 status, reasons[], errors[], stale 판정은 collector/Backend 계약을 따른다. Frontend는 임계값을 다시 계산해 원래 상태를 덮어쓰지 않는다.

Shell과 반응형

Sidebar는 Fleet, Factories, System, Workspace로 구분된다. 데스크톱에서는 접기 상태를 localStorage에 보존하고, 800px 이하에서는 overlay drawer로 전환한다. icon button에는 aria-labeltitle이 있고, 주요 control에는 focus-visible이 적용된다. table과 tab/selector는 좁은 화면에서 가로 스크롤 또는 단일 열로 전환한다.

관련 문서

Aegis-Pi Wiki

· 대표 문서 목록은 홈의 문서 탐색 표 참조

시작하기

요구사항

핵심 개념

아키텍처

컴포넌트 (Edge → Cloud → Dashboard)

Dashboard & 운영

시나리오 · 사례 · 참조

Clone this wiki locally