-
Notifications
You must be signed in to change notification settings - Fork 0
reference api
기준일: 2026-06-09
상태: 구현 완료 (Dashboard Backend 기준)
근거: docs/specs/data_storage_pipeline.md, docs/ops/22_data_dashboard_vpc_runbook.md, apps/dashboard-backend
이 문서는 Dashboard Backend가 제공하는 REST / WebSocket / 인증 API의 단일 명세다. Backend는 ECS Fargate에서 실행되는 FastAPI 애플리케이션이며, Spoke K3s·EKS·ArgoCD·Tailscale 관리망을 직접 호출하지 않고 DynamoDB, S3, RDS, Redis 같은 read model과 메타데이터만 조회한다.
Browser (정적 SPA)
-> Route53 (api.<dashboard-domain>)
-> ALB (HTTPS / TLS, ACM)
-> ECS Fargate Dashboard Backend (FastAPI)
-> Cognito JWT 앱 레벨 검증
-> DynamoDB LATEST / HISTORY / GRAPH#5M / CLOUD#infra (read-only)
-> S3 processed / reports / image_snapshot (read-only)
-> RDS PostgreSQL (사용자·공장·권한 메타데이터)
-> Redis (캐시 + Pub/Sub subscribe)
Authorization: Bearer <Cognito Access Token>
- Cognito Hosted UI의 OIDC Authorization Code + PKCE flow로 JWT를 발급받는다.
- Backend가 JWKS 기반으로 서명·만료·audience를 앱 레벨에서 검증한다.
- 사용자-공장 권한은 RDS PostgreSQL 메타데이터(
app_user,user_factory_access,factory,audit_log)를 기준으로 필터링한다. 미인가 공장 직접 호출은 거부한다. - WebSocket은 브라우저가 커스텀 헤더를 보낼 수 없으므로
?token=<JWT>쿼리 파라미터로 전달한다.
| Method | Path | 인증 | 동작 | 백엔드 조회 |
|---|---|---|---|---|
| GET | /healthz |
없음 | liveness | {"status":"ok"} |
| GET | /readyz |
없음 | readiness (DynamoDB, Redis, RDS metadata 의존성 점검) | DDB + Redis + RDS |
| GET | /factories |
Cognito JWT | 공장 목록 + latest 요약 | DDB Query (pk=FACTORY#*, sk=LATEST) |
| GET | /factories/{factory_id} |
Cognito JWT | 단일 공장 latest 전체 | DDB GetItem |
| GET | /factories/{factory_id}/history?window=…[&limit=N][&since=<iso>] |
Cognito JWT | 시계열 조회 (아래 window 분기) | DDB Query |
| GET | /cloud-infra |
Cognito JWT | Cloud Infra 현재 상태(LATEST) + staleness | DDB GetItem (pk=CLOUD#infra, sk=LATEST) |
| GET | /cloud-infra/history?window=1h|6h|24h&track=fast|slow |
Cognito JWT | Cloud Infra 추이 | DDB Query (HISTORY#FAST#|HISTORY#SLOW#) |
| GET | /image-snapshots/range?factory_id= |
JWT (System) | 이미지 스냅샷 picker용 가용 범위 | S3 ListObjectsV2 (image_snapshot/) |
| GET | /image-snapshots?factory_id=&start=&end=[&limit=N] |
JWT (System) | 시간 범위 내 스냅샷 목록 + presigned GET URL | S3 ListObjectsV2 + presign |
| POST | /chat/query |
Cognito JWT | 자연어 질의(상태/원인/추이/스파이크/보고서) | DDB + S3 read model, 선택적 Bedrock |
| GET | /reports |
Cognito JWT | 일간 보고서 목록 | S3 ListObjectsV2 (reports/daily/) |
| GET | /reports/{report_date}/{factory_id} |
Cognito JWT | 공장 또는 cloud-infra 보고서 본문 (text/markdown) |
S3 GetObject |
| GET | /auth/me |
Cognito JWT | 현재 사용자 프로필·역할·접근 가능 공장 | RDS |
| GET | /admin/users |
JWT (super_admin/org_admin) | 활성 사용자 목록 | RDS |
| POST | /admin/users |
JWT (super_admin/org_admin) | 사용자 생성 (Cognito + RDS + 공장 권한) | Cognito Admin API + RDS |
| PATCH | /admin/users/{user_id} |
JWT (super_admin/org_admin) | 역할/공장 권한 수정 | RDS |
| DELETE | /admin/users/{user_id} |
JWT (super_admin/org_admin) | 사용자 삭제 (Cognito + RDS) | Cognito Admin API + RDS |
/factories·/factories/{id}·/reports·/ws는 사용자에게 허용된 공장만 노출한다. /reports의
cloud-infra target은 System 권한 사용자에게만 노출한다. 비인증 호출은 401, 인가 부족은 403을 반환한다.
조회 window에 따라 backend가 읽는 DynamoDB sort key prefix가 달라진다.
| window | sort key | 내용 | 기본 limit |
|---|---|---|---|
10m |
HISTORY#STATE#* |
원시 시계열 (risk/factory_state/infra_state 통합) | 250 |
1h |
HISTORY#STATE#* |
원시 시계열 | 2000 |
6h / 12h / 24h
|
GRAPH#5M#* |
5분 avg/min/max 집계 (24h 기준 최대 288 items) | 500 |
-
since=<iso timestamp>를 지정하면 해당 시각보다 최신 item만 반환한다. Dashboard 자동 refresh는 첫 로드 후 이 delta 조회 결과를 브라우저 state에 append/merge한다. - Timeline의 원인 설명은
HISTORY#STATE.risk.top_causes에서 추출한top_cause_names만 사용한다.GRAPH#5M집계 item에는 원인 설명 필드가 없다. -
HISTORY#RISK,HISTORY#FACTORY,HISTORY#INFRAprefix는 사용하지 않는다.
timestamp, risk_score, risk_level(safe/warning/danger), temperature_celsius_avg,
humidity_percent_avg, pressure_hpa_avg, fire_score / fall_score / bend_score(0~1),
node_summary, nodes(노드별 CPU/memory/disk).
5분 버킷 집계로, 각 지표의 avg와 함께 min/max를 분리해 음영·tooltip·spike marker에 사용한다.
| 그룹 | 필드 |
|---|---|
| risk |
risk_score_avg, risk_score_min, risk_score_max
|
| 환경 센서 |
temperature_celsius_avg/min/max, humidity_percent_avg/min/max, pressure_hpa_avg/min/max
|
| AI 탐지 |
fire_score·fall_score·bend_score(mean), *_score_max(버킷 내 최대, 0.8↑ spike) |
| 노드 |
cpu_usage_percent_mean, memory_usage_percent_mean, disk_usage_percent_last
|
공장에 GRAPH#5M 데이터가 없으면 빈 배열 []을 반환한다.
risk.score는 이름과 달리 높을수록 안전한 값이다 (100 = 최안전, 0 = 최위험).
| 구간 | level | Frontend 표시 |
|---|---|---|
| 85 ~ 100 | 안전 | threshold line y=85 |
| 50 ~ 84 | 주의 | threshold line y=50/85 |
| 0 ~ 49 | 위험 | threshold line y=50 |
공장 상태와 분리된 Cloud Infra 화면용이다. Backend는 collector가 써둔 pk=CLOUD#infra item만
읽으며 EKS/ArgoCD/CloudWatch에 직접 붙지 않는다(수집은 collector 책임).
- item이 없으면(collector write 전) HTTP
200 + {"available": false}를 반환한다(404 아님). Frontend는 "수집 대기" empty-state로 표시한다. - staleness(
fast_stale/slow_stale/*_age_seconds)는 backend가 read 시점에*_updated_at으로 계산해 덧붙인다. 기준은 fast > 180초, slow > 900초이며 응답에stale_threshold_seconds로 동봉된다. - 응답 본문(
fast/slow/reasons[]/errors[])은 collector가 저장한CLOUD#infra스키마를 그대로 따른다.
보고서 조회 경로는 S3 기반이다. Backend는 reports/daily/ prefix를 읽는다(보고서 본문 생성은
Reporting 파이프라인 책임).
- S3 object 경로:
reports/daily/yyyy={YYYY}/mm={MM}/dd={DD}/{target}/report.md -
GET /reports:report_date(YYYY-MM-DD) 내림차순 정렬된 객체 배열. 각 항목은report_date,factory_id또는target,s3_key,last_modified,size_bytes. -
GET /reports/{report_date}/{factory_id}:factory_idpath 변수에는 공장 ID 또는cloud-infra가 들어갈 수 있다. Frontend가 받은text/markdown본문을 자체 Markdown 파서로 렌더링하고 PDF(인쇄)/Word 내보내기를 제공한다. - S3에 객체가 없으면
/reports는 빈 배열,/reports/{date}/{factory_id}는404를 반환한다.
근거 요구사항: FR-DASH-06, FR-DATA-07/08.
AI 이벤트 이미지 스냅샷 조회 경로다. 원본 binary는 S3 image_snapshot/ prefix에 있고, Backend는 객체 목록과 presigned GET URL만 생성한다. 실제 download는 브라우저가 presigned URL로 S3에서 직접 받는다(이미지가 Backend를 통과하지 않음).
- 두 endpoint 모두 System 권한(
require_system_access)을 강제한다. 권한 없으면403. -
GET /image-snapshots/range?factory_id=: picker용 가용 범위.available_start(가장 이른 partition),available_latest_hour,object_count. -
GET /image-snapshots?factory_id=&start=&end=[&limit=N]: 시간 범위 내 목록.start/end는 ISO 8601 local time이며start < end여야 한다(아니면400).limit기본 120, 최대 300. - 각 항목:
s3_key,filename,url(presigned GET, 기본 900초 만료),last_modified,size_bytes,detection_type(파일명_event_<TYPE>에서 파생). - 시간 범위가 겹치는
yyyy=/mm=/dd=/hh=partition prefix만 list해 비용을 제한한다. S3 지연/실패는504.
자세한 데이터 경로는 Image Snapshot Pipeline의 대시보드 조회 절을 따른다.
POST /chat/query — 자연어 질의에 대해 Backend가 read model을 조회해 근거(Evidence)와 답변을 돌려준다. RBAC를 데이터 조회 이전에 강제해 채팅이 권한 우회 통로가 되지 않게 한다.
요청 본문:
{ "question": "<최대 500자>", "factory_id": "factory-a", "model_tier": "auto" }-
factory_id는 선택. 비우면 질문에서 공장을 식별하며, 식별 실패 시 데이터 조회 없이 재질문을 안내한다. -
model_tier:auto|fast|precise. - intent에 따라 DynamoDB(
LATEST/HISTORY/GRAPH#5M)와 S3(processed/reports)를 읽고, 과거 구간은 TTL 없는 S3 processed를 우선한다. - 이미지 키워드가 있으면
image_ref로 증빙 이미지(presigned GET URL)를 동봉하며, 이 경로도 System 권한을 통과해야 한다. - 미인가 공장 호출은
403, DynamoDB/S3 지연은504. Bedrock 비활성/실패 시 규칙 파서·템플릿으로 degrade한다.
응답 envelope: answer(Markdown), intent, factory_id, time_scope, evidence(confirmed/inferred/missing), image_ref, generator(bedrock|rule), model_tier, router(llm|rule). raw model id는 노출하지 않는다.
자세한 동작은 AI 채팅 어시스턴트를 따른다.
| Method | Path | 인증 | 동작 | 백엔드 경로 |
|---|---|---|---|---|
| WS | /ws/factories/{factory_id} |
Cognito JWT (?token=) |
공장 상태 변경 push | Redis Pub/Sub factory:update:<factory_id> subscribe |
실시간 경로는 DynamoDB Streams -> Lambda notifier -> Redis Pub/Sub -> Backend WebSocket push다.
WebSocket 단절 시 REST polling이 대체 경로가 된다. 자세한 구조는 실시간 갱신 구조를 따른다.
- ALB listener는 HTTPS만 허용하고 HTTP는 redirect.
- CORS는 정적 SPA 도메인(
https://dashboard.<dashboard-domain>)만 Allow-Origin. - Backend IAM은 DDB
Query/GetItem, S3GetObject, Secrets Manager read 등 최소 권한. - 구조화 JSON 로그를 CloudWatch Logs로 남기고, ECS service circuit breaker와
/healthzhealth check를 사용한다.
일반 상태 변화: 10~35초
infra_state 지연 표시: warning > 60초, critical > 120초
DDB Streams -> WebSocket push: 1~2초
- 쓰기 API(관리자가 관제 데이터를 직접 수정/이벤트 입력) — MVP 범위 외
- Replay / Near-miss API — 후속
- Timestream / Kinesis / OpenSearch 조회 API — Phase 2 후속
이 문서에는 실제 endpoint 전체 주소, 계정 번호, 토큰 원문을 싣지 않는다. 도메인은
<dashboard-domain> 패턴으로 일반화한다.
- 시스템 아키텍처
- 제어 & 데이터 플레인
- Dashboard VPC 설계
- 하드웨어 배치
- Hub EKS 네임스페이스
- Tailscale Mesh VPN
- 데이터 생명주기
- 데이터 조회 모델
- 실시간 갱신 구조
- IoT 데이터 계약
- Reporting Pipeline
- 로컬 스토리지
- 클라우드 스토리지
- Edge Agent
- Edge AI 탐지
- Factory-A Log Adapter
- Dummy Sensor
- Edge IoT Publisher
- Lambda Data Processor
- Risk Normalizer
- Risk Score Engine
- Pipeline Status Aggregator
- Graph Aggregator 5m
- Cloud Infra Collector
- Daily Report Generator
- Risk Alert Dispatcher
- Image Snapshot Pipeline
- Dashboard Backend
- Dashboard Web
- AI 채팅 어시스턴트