아키텍처
이 문서는 vivid-ai 프로젝트의 전체 시스템 아키텍처와 생성/후처리 데이터 흐름을 설명합니다.
현재 기준의 인프라 결정은 현재 권장 인프라 플랜을 우선합니다.
현재 기준 요약
local: MacBook Docker Compose + AWS SQS/S3 + local Redis/Postgres
dev: EC2 Docker Compose + AWS SQS/S3 + ElastiCache/RDS
prod: Kubernetes + AWS SQS/S3 + ElastiCache/RDS
생성 파이프라인은 다음처럼 분리합니다.
backend
-> SQS computation queue
-> ai-node-agent
-> ComfyUI
-> external generation API node
-> S3 raw/
-> SQS post-processing queue
-> post-processing-worker
-> S3 creations/
-> backend / Postgres / Redis
핵심 아키텍처 원칙
- 환경 분리:
local,dev,prod환경은 서로 영향을 주지 않도록 SQS queue, S3 bucket/prefix, Postgres, Redis를 분리합니다. - Managed boundary: Postgres/RDS, SQS, S3, ElastiCache는 managed resource로 유지하고, frontend/backend/ComfyUI/
ai-node-agent/post-processing-worker는 컨테이너 실행부로 관리합니다. - 생성/후처리 분리:
ai-node-agent는 generation orchestration을 담당하고,post-processing-worker는 thumbnail, preview, resize/crop, upload, backend sync를 담당합니다. - 실시간 피드백:
ai-node-agent와 backend는 relay/Redis Pub/Sub을 통해 작업 상태를 공유하고, backend는 사용자에게 실시간 상태를 전달합니다.
공통 인프라
- Containerized generation runtime: ComfyUI와
ai-node-agent를 컨테이너로 실행합니다. API 노드 기반 workflow를 기본으로 운영합니다. - Public Agent Relay + Redis:
ai-node-agent는 public relay에 상태/이벤트를 전달하고, backend는 Redis Pub/Sub과 progress cache를 통해 사용자에게 realtime update를 제공합니다. - Managed data plane: SQS, S3, RDS, ElastiCache는 실행부와 분리된 managed service로 유지합니다.
Local 개발 환경 아키텍처
로컬 머신(MacBook 등)에서 전체 실행부를 Docker Compose로 띄우고, SQS/S3는 실제 AWS cloud resource를 사용합니다.
구성 요소
- Frontend container: Next.js 애플리케이션.
- Backend container: NestJS API, generation queue enqueue, realtime gateway.
- ComfyUI container: workflow 실행 엔진.
ai-node-agentcontainer: SQS generation queue polling, ComfyUI orchestration, S3raw/upload, post-processing queue enqueue.post-processing-workercontainer: S3raw/download, thumbnail/preview/resize/crop/transcode, S3creations/upload, backend result sync.- Local Redis container: progress cache, pub/sub, websocket 보조 상태.
- Local Postgres container: local 개발 전용 DB.
- AWS Services:
- SQS:
vivid-ai-computation-queue-local,vivid-ai-post-processing-worker-queue-local - S3: local media bucket.
raw/,creations/,generation/source/,generation/work-input/,temp/prefix를 사용합니다.
- SQS:
데이터 흐름
Dev 환경 아키텍처
Dev 환경은 EC2에서 Docker Compose로 실행부를 운영하고, Postgres/Redis/SQS/S3는 AWS managed resource를 사용합니다.
구성 요소
- EC2 Docker Compose:
- frontend
- backend
- ComfyUI
ai-node-agentpost-processing-worker
- AWS Managed Services:
- SQS:
vivid-ai-computation-queue-dev,vivid-ai-post-processing-worker-queue-dev - S3: dev media bucket. local과 같은 prefix 구조를 사용합니다.
- RDS: PostgreSQL database.
- ElastiCache: dev Redis/Valkey.
- SQS:
데이터 흐름
Prod 환경 아키텍처
Prod 환경은 Kubernetes에서 실행부를 역할별 Pod/Deployment로 운영하고, Postgres/Redis/SQS/S3는 AWS managed resource를 사용합니다.
구성 요소
- Kubernetes Deployments:
- frontend
- backend
ai-node-agent+ ComfyUI Podpost-processing-worker
- AWS Managed Services:
- SQS: prod generation/post-processing queues.
- S3: prod media bucket. local/dev와 같은 prefix 구조를 사용합니다.
- RDS: PostgreSQL database.
- ElastiCache: prod Redis/Valkey.
ai-node-agent와 ComfyUI는 같은 Pod의 두 컨테이너로 묶고 input/output/temp shared volume을 공유하는 구성을 우선 고려합니다.
Pod: ai-node
- container: comfyui
- container: ai-node-agent
- shared volume: input/output/temp
시스템 아키텍처 상세 (이미지/비디오 생성 파이프라인 중심)
AWS Cloud & Backend Services
-
진입점:
- ALB/Ingress: prod Kubernetes 환경의 웹/앱 트래픽 진입점입니다. Host-based 및 Path-based 라우팅을 통해 Front/Back 서비스를 Pod으로 분산합니다.
- 배스천 호스트: 관리자가 SSH 터널링을 통해 프라이빗 리소스(예: RDS, ElastiCache)에 접근해야 할 때 사용하는 보안 게이트웨이입니다.
- API Gateway: (향후 도입 예정) AI 연산 요청의 최전방 인증, 스로틀링, 트래픽 통제를 담당합니다.
-
핵심 실행부:
- Frontend (Next.js): 사용자 인터페이스 제공.
- Backend (Nest.js):
- API 버전 관리: 모든 백엔드 API는
/api/v1접두사를 사용하여 버전 관리를 시작합니다. 헬스 체크 엔드포인트는/api/v1입니다. - 워크플로우 템플릿 관리: 관리자가 등록한 ComfyUI 워크플로우와 동적 UI 생성을 위한
userInputs스키마를 DB에 저장하고 관리합니다 (/api/v1/workflows엔드포인트). - 창작물(Creation) 관리:
POST /api/v1/generations요청 시,Creation테이블에 레코드를PENDING상태로 생성합니다.GET /api/v1/creations를 통해 사용자에게 창작물 목록을 제공합니다. - 동적 워크플로우 생성: 사용자가 템플릿과 파라미터를 보내면(
POST /api/v1/generation/from-template), DB에서 템플릿을 조회한 후userInputs스키마를 기반으로 사용자 요청(modifications)을 실제 ComfyUI 워크플로우 JSON의 정확한 위치에 주입하여 최종 워크플로우를 완성합니다. - 비즈니스 로직, 이메일/비밀번호 인증, DB/Redis 접근 관리.
SqsProducerService를 통해 최종 생성된 워크플로우 JSON과creationId를 환경에 맞는 연산 SQS 큐에 작업을 발행합니다.
- API 버전 관리: 모든 백엔드 API는
- AiRealtimeGateway (Nest.js, 백엔드에 포함):
- relay가 shared Redis에 반영한 채널(
ai-comfyui-events)을 구독하여 모든 실시간 이벤트(작업 진행 상황, ComfyUI 상태, AI 연산 노드 시스템 모니터링 데이터)를 수신합니다. - 수신한 이벤트를
userId에 따라 적절한Socket.IO룸으로 필터링하여 프론트엔드 클라이언트에 실시간으로 전달(Push)합니다. 관리자 클라이언트에게는 모든 노드의 모니터링 데이터를 전송합니다. RedisIoAdapter를 사용하여 백엔드 서버가 여러 인스턴스로 확장되어도 WebSocket 메시지를 안정적으로 브로드캐스팅합니다.
- relay가 shared Redis에 반영한 채널(
- 후처리 워커 (Post-processing Worker):
- 환경에 맞는 후처리 SQS 큐를 폴링하여 메시지(S3
raw/경로 포함)를 가져옵니다. - S3
raw/prefix에서 원본 파일을 다운로드합니다. ffmpeg를 사용하여 비디오 최적화(Preview 생성) 및 썸네일 생성 작업을 수행합니다.- 최종 결과물과 썸네일(또는 Preview 영상)을 S3
creations/prefix에 업로드합니다. - 백엔드 API(
PATCH /api/v1/creations/:id)를 호출하여 데이터베이스의Creation레코드 상태를COMPLETED로 업데이트하고 S3 경로를 저장합니다. - Kubernetes 배포 특이사항:
- 이미지 아키텍처: EKS 워커 노드가 주로
linux/amd64아키텍처를 사용하므로, Docker 이미지 빌드 시--platform linux/amd64를 명시해야 합니다. (예: Apple Silicon Mac에서 빌드 시). - ECR 이미지 풀 권한: 파드가 ECR(Elastic Container Registry)에서 이미지를 가져오려면 IRSA(IAM Role for Service Accounts)를 통해 Service Account에 ECR pull 권한이 있는 IAM Role이 연결되어야 합니다 (정책 예:
AmazonEC2ContainerRegistryReadOnly). - 환경 변수 주입: SQS URL, S3 버킷 이름, 백엔드 API URL 등의 민감한 정보는 Kubernetes Secret으로 관리되며, Deployment에서 컨테이너의 환경 변수로
secretKeyRef를 통해 안전하게 주입됩니다. - 네트워크 접근: 워커 노드가 프라이빗 서브넷에 배포된 경우, ECR API, ECR Docker, S3 서비스에 대한 VPC Endpoint 생성이 필요할 수 있습니다. 관련 상세 내용은 인프라 및 배포 문서를 참조하십시오.
- 이미지 아키텍처: EKS 워커 노드가 주로
- 환경에 맞는 후처리 SQS 큐를 폴링하여 메시지(S3
-
데이터 흐름:
- RDS (PostgreSQL) & Shared Redis (ElastiCache):
- 보안: 주요 데이터와 캐시를 저장하는 이 서비스들은 외부 인터넷에서 직접 접근할 수 없는 프라이빗 서브넷에 위치하여 보안을 강화합니다.
- 접근 방식:
- local backend: Docker Compose의 local Redis/Postgres에 연결합니다.
- dev backend: EC2에서 RDS/ElastiCache와 통신합니다.
- prod backend: Kubernetes/VPC 내부에서 RDS/ElastiCache와 통신합니다.
ai-node-agent: RDS에 직접 붙지 않고 SQS/S3와 relay/backend API를 통해 필요한 상태/작업 정보만 주고받습니다.
- SQS Queue (Computation Queue):
vivid-ai-computation-queue-{env}큐를 통해 백엔드로부터ai-node-agent로 전달될 이미지/비디오 생성 작업 큐. - SQS Queue (Post-processing Queue):
ai-node-agent로부터post-processing-worker로 전달될 생성 완료 알림 및 임시 파일 경로 큐 (vivid-ai-post-processing-worker-queue-{env}). - S3 raw storage: 환경별 media bucket의
raw/prefix에 생성 raw output을 임시 저장. - S3 final storage: 환경별 media bucket의
creations/prefix에 후처리가 완료된 최종 원본, 썸네일, preview를 저장 및 제공.
- RDS (PostgreSQL) & Shared Redis (ElastiCache):
External Provider Boundary
- ComfyUI workflow는 API 노드를 통해 외부 이미지/비디오 생성 provider를 호출합니다.
- provider API key는 frontend에 노출하지 않고 ComfyUI/
ai-node-agent실행 환경의 secret으로만 주입합니다. - provider 비용은 provider 계정에서 먼저 차감되고, 사용자 크레딧 차감은 backend의 billing/credit 로직에서 별도로 처리합니다.
- provider rate limit, 장애, 비용은
ai-node-agent의 retry/error handling과 backend의 job 상태 관리로 흡수합니다.
실시간 파이프라인
ai-node-agent와 ComfyUI에서 발생하는 작업 진행 상황(시작, 진행률, 완료 등)은 public relay + Redis 기반의 실시간 파이프라인을 통해 프론트엔드에 전달됩니다. 이를 통해 사용자는 자신의 작업 상태를 실시간으로 확인할 수 있습니다.
자세한 내용은 실시간 파이프라인 아키텍처 문서를 참조하십시오.
프론트엔드 낙관적 업데이트 (Optimistic Update)
사용자가 갤러리 페이지에 진입할 때 REST API(GET /creations)를 호출하면, 최신 작업이 아직 데이터베이스에 반영되지 않아 PENDING 상태이거나 이미지가 없는([]) 상태일 수 있습니다. 그러나 화면에는 이미지가 즉시 표시됩니다.
이는 프론트엔드가 **WebSocket(IMAGE_ADDED 이벤트)을 통해 수신한 이미지 데이터를 React Query 캐시(['creations'])에 직접 주입(Injection)**하기 때문입니다. API를 다시 호출하지 않고도 로컬 캐시를 즉시 업데이트함으로써, 사용자는 지연 없이 실시간으로 생성된 결과물을 확인할 수 있습니다.
다이어그램 보기 (Link)
워크플로우 템플릿 기반 생성 흐름 (Multi-Variant System)
이 시스템의 핵심은 워크플로우 템플릿의 유연성과 Feature Key 기반 추상화입니다.
다양한 모델(예: OmniGen, Qwen)은 입력 이미지/비디오 개수에 따라 서로 다른 ComfyUI 워크플로우 구조를 요구하므로, 워크플로우 그룹(Workflow Group) + 워크플로우 변형(Workflow Variant) + 워크플로우 매핑(Workflow Mapping) 3계층을 사용합니다.
핵심 개념: 1:N 구조
- Workflow Group (1): 갤러리에 표시되는 '상품'의 단위입니다. (예: "OmniGen Image Edit") 제목, 설명, 가격, 카테고리 등 메타데이터를 관리합니다.
- Workflow Variant (N): 실제 '구현체'입니다. 입력 데이터의 형태(예: 텍스트 1개 + 이미지 2개)에 따라 실행되어야 할 구체적인 ComfyUI JSON과 매핑 정보를 담고 있습니다.
- Workflow Mapping (Feature Key): 서비스 기능 키(
PERSONA_PROFILE_IMAGE_GEN등)와 워크플로우 그룹을 연결합니다.
4단계 워크플로우 생성 프로세스 (관리자)
관리자는 다음 4단계를 통해 하나의 완벽한 기능을 정의합니다.
- 1단계: 기본 정보 (Basic Info)
- 워크플로우 그룹의 제목, 설명, 가격, 카테고리(
TEXT_TO_IMAGE,IMAGE_TO_IMAGE등)를 설정합니다.
- 워크플로우 그룹의 제목, 설명, 가격, 카테고리(
- 2단계: 변형 구성 (Variant Configuration)
- 해당 기능이 지원할 다양한 입력 케이스를 정의합니다.
- 예를 들어, "OmniGen" 기능을 위해 [변형 A: 이미지 1장용], [변형 B: 이미지 2장용] 탭을 추가하고, 각각에 맞는 ComfyUI 워크플로우 JSON을 입력합니다.
- 3단계: 필수 매핑 (Required Mappings)
- 각 변형별로 시스템이 제어할 표준 입력을 매핑합니다.
- 통일성을 위해
prompt대신text_1, **text_2**를 사용합니다. - 이미지 입력은
image_1,image_2, **image_3**로 고정합니다. - 현재 Persona/Coordi/Scene MVP 계약에서는 Scene 생성 시
image_1을 반드시내 outfit으로 사용합니다.
- 4단계: 사용자 입력 설정 (User Inputs)
- 각 변형별로 사용자에게 보여줄 UI 폼(슬라이더, 드롭다운 등)을 독립적으로 설정합니다.
실행 흐름 (Execution Logic)
사용자는 복잡한 내부 구조를 알 필요가 없습니다.
- 사용자 요청: 사용자가 "OmniGen" 모델을 선택하고 이미지 2장을 업로드하여 생성을 요청합니다.
- 전송: 프론트엔드는
featureKey(권장) 또는workflowId와 입력 데이터(text_1,image_1,image_2...)를 전송합니다. - 라우팅 (Backend): 백엔드는 입력 개수(text/image/video/audio)에 대한 exact-match 기준으로 Variant를 선택하고 실행합니다.
- 우선순위: exact-match 후보가 여러 개인 경우
sortOrder(오름차순) 우선으로 선택합니다.
End-to-End 전체 프로세스 상세
1단계: 생성 요청 (Frontend → Backend)
- 사용자 액션 (Frontend): 사용자가 웹사이트에서 프롬프트를 입력하거나 옵션을 선택한 후 '생성하기' 버튼을 클릭합니다.
- API 호출 (Frontend): 프론트엔드는 인증 토큰(JWT)과 함께 백엔드의
POST /api/v1/generation/...API를 호출합니다.
2단계: 작업 접수 및 대기열 추가 (Backend)
- 요청 접수 (Backend):
GenerationService는 사용자의 요청을 검증합니다. - DB 레코드 생성 (Backend):
GenerationService는 데이터베이스(PostgreSQL)에 이 생성 작업에 대한Creation레코드를 생성합니다. 이때 초기 상태는status: 'PENDING'입니다. - SQS 메시지 발행 (Backend): 백엔드는 처리해야 할 작업 정보(
userId,creationId,workflow등)를 담아 해당 환경의연산 SQS 큐 (Computation Queue)에 메시지를 보냅니다.
3단계: AI 연산 및 원본 저장 (AI Node Agent)
- 작업 수신 (AI Agent):
ai-node-agent는local과dev연산 SQS 큐를 동시에 주시하다가, 새 작업 메시지를 받습니다. - AI 연산 (AI Agent): 메시지 정보를 바탕으로 ComfyUI API를 호출하여 이미지/비디오 생성을 시작합니다. 진행 상황과 heartbeat는 agent 전용 WebSocket을 통해 relay로 실시간 중계됩니다.
- 결과물 업로드 (AI Agent): 생성이 완료되면, 결과물(이미지/비디오 원본)을 해당 환경 media bucket의
raw/prefix 에 업로드합니다. - 후처리 요청 (AI Agent): 업로드 완료 후,
ai-node-agent는post_processing상태를 relay의 HTTP ingress로 반영하고,후처리 SQS 큐에 메시지를 보냅니다.
4단계: 후처리 및 최종 저장 (Post-processing Worker)
- 작업 수신 (후처리 작업자):
post-processing-worker는 후처리 SQS 큐를 주시하다가 새 작업을 받습니다. - 파일 다운로드 (후처리 작업자): 메시지에 포함된
raw_s3_path를 이용해 S3raw/prefix에서 원본 파일을 다운로드합니다. - 후처리 실행 (후처리 작업자):
- 이미지: 썸네일 이미지 생성.
- 비디오:
ffmpeg를 사용하여 웹 최적화된 미리보기 MP4 (H.264, Muted) 생성.
- 최종 업로드 (후처리 작업자): 후처리가 완료된 최종 결과물과 썸네일/미리보기를 S3
creations/prefix에 업로드합니다.
5단계: 상태 업데이트 및 완료 (Post-processing Worker → Backend)
- 상태 업데이트 API 호출 (후처리 작업자):
post-processing-worker는 백엔드의PATCH /api/v1/creations/:idAPI를 호출합니다. - DB 업데이트 요청 (후처리 작업자): API 요청 본문에 최종 상태(
status: 'COMPLETED')와 S3 경로(s3Path,thumbnailPath)를 전달합니다. - DB 최종 업데이트 (Backend): 백엔드는 DB를 업데이트하고, Redis Pub/Sub으로 최종
completed이벤트를 발행합니다. - 클라이언트 업데이트 (Frontend): 프론트엔드는 이벤트를 수신하여 작업 상태를 '완료'로 변경하고 결과물을 표시합니다.
6단계: 갤러리 조회 (Frontend ↔ Backend)
- 갤러리 페이지 접속 (Frontend): 사용자가 '내 생성물' 갤러리 페이지로 이동합니다.
- 생성물 목록 요청 (Frontend): 프론트엔드는 백엔드의
GET /api/v1/creationsAPI를 호출합니다. - Pre-signed URL 생성 (Backend): 백엔드는 DB에서 조회한 생성물(
COMPLETED)의 S3 경로를 Pre-signed URL로 변환하여 반환합니다.
워크플로우 매핑 시스템 (Workflow Mapping System)
단순 도구를 넘어 서비스 중심의 기능을 제공하기 위한 추상화 레이어입니다.
핵심 개념
- Feature Key: 서비스 기능 단위 고유 키 (예:
PERSONA_PROFILE_IMAGE_GEN,PERSONA_COORDI_GEN,PERSONA_OUTFIT_GEN,PERSONA_TO_IMAGE_GEN,PERSONA_TO_VIDEO_GEN) - Visibility:
PUBLIC/ADMIN_ONLY/PRIVATE단계로 노출 제어 - Workflow Group Mapping: Feature Key를 실제 구현체(
WorkflowGroup)에 연결 - Variant Routing: 요청 입력 개수 기준 exact-match +
sortOrder우선순위 적용
작동 원리 (Persona → Coordi → Scene 기준)
- Selection: 유저가 기능(예: 페르소나 생성, 페르소나 i2i)을 선택합니다.
- Mapping Resolution: 시스템이
Feature Key로workflowGroupId를 조회합니다. - Payload Assembly:
image_1: 내outfitimage_2,image_3: Scene 선택 참조text_1,text_2:coordi + scene최종 프롬프트
- Smart Routing: 백엔드는 입력 카운트 기준으로 정확히 일치하는 Variant를 선택합니다.
- Persistence:
creations.snapshot(jsonb)를 재현성 원본으로 저장하고(기본 키:text_1,text_2,personaId,featureKey,workflowGroupId,variantId, 조건부 키:coordiId,outfitId), 조회 성능을 위해resolved_prompt/resolved_negative_prompt/ratio/refs를 projection 컬럼으로 함께 저장합니다. 결과 단위 메타(seed,resultIndex,s3Path,thumbnailS3Path)는creation_results에 저장하며, 관계는Creation(1):CreationResult(N)를 따릅니다.
가시성 제어 (Visibility)
- PUBLIC: 모든 일반 유저에게 공개.
- ADMIN_ONLY: 관리자 페이지 및 관리자 권한 유저에게만 노출 (테스트 단계).
- PRIVATE: 비공개 상태. 모든 UI에서 숨겨짐.