API 명세: 워크플로우 / 템플릿 기반 생성
기준일: 2026-03-04
대상 코드:backend-vivid-ai/src/workflows,backend-vivid-ai/src/generation
워크플로우 템플릿(그룹/변형) 관리와 템플릿 기반 생성 요청 API를 정리합니다.
Base Path
/api/v1
1. 워크플로우 그룹 관리 (/workflows)
1.1 GET /workflows
- 워크플로우 그룹 목록 조회
visibility쿼리 지원:public(기본),private,all,archived
1.2 GET /workflows/:id
- 특정 워크플로우 그룹 상세 조회
- 그룹에는
variants[]가 포함되며sortOrder기준 정렬됩니다.
1.3 POST /workflows
- 워크플로우 그룹 + variants 생성
- variant별
inputConfig,workflowJson,requiredMappings,userInputs저장
1.4 PATCH /workflows/:id
- 그룹/variants 수정 (variants는 전체 교체 방식)
1.5 DELETE /workflows/:id
- 아카이브 처리 (
isArchived = true,isPublic = false)
1.6 POST /workflows/:id/restore
- 아카이브 해제
1.7 DELETE /workflows/:id/permanent
- 영구 삭제 (아카이브된 그룹만 허용)
2. 기능 키 매핑 (/workflows/mappings)
Feature Key와 Workflow Group을 연결하는 추상화 레이어입니다.
2.1 GET /workflows/mappings
- 매핑 전체 조회
- 일반 유저:
PUBLIC만 조회 - 관리자:
PUBLIC,ADMIN_ONLY,PRIVATE조회
2.2 GET /workflows/mappings/:featureKey
- 특정 featureKey 매핑 조회
2.3 POST /workflows/mappings (Admin)
- 매핑 생성/수정(upsert)
featureKey,workflowGroupId,visibility등 설정
2.4 DELETE /workflows/mappings/:featureKey (Admin)
- 매핑 삭제
3. 템플릿 기반 생성 요청 (/generation)
3.1 POST /generation/from-template
워크플로우 템플릿 기반 생성 API입니다.
Request Body
{
"featureKey": "PERSONA_TO_IMAGE_GEN",
"modifications": {
"persona_id": "7d8f9d52-....",
"text_1": "cinematic portrait, soft rim light",
"text_2": "",
"image_2": "s3://.../ref-a.png",
"aspect_ratio": "1:1",
"quality": "FHD"
}
}
입력 규칙
workflowId또는featureKey중 최소 1개 필수- 둘 다 전달한 경우,
featureKey매핑 결과와workflowId가 일치해야 함 modifications는 동적 입력 값 맵quality는SD,HD,FHD중 하나를 사용text_2를 사용하지 않는 경우에도""전달을 권장
서버 처리 핵심
- 매핑 해석:
featureKey가 있으면 매핑된workflowGroupId결정 - 공개성 검증:
- 아카이브된 워크플로우 사용 불가
- 비공개 워크플로우는 관리자만 사용 가능
- 페르소나 컨텍스트 검증:
persona_id전달 시 소유권 검증- 검증 통과 시
image_1을 페르소나의 신뢰 가능한 S3 경로로 강제 대체
- Variant 선택:
text입력 개수는 정확히 일치해야 함- 비합성 Variant(
useCompositeReferenceImage !== true)의image/video/audio설정값은 각각 최대 입력 개수이며, 요청 개수가 각 최대치 이하면 후보가 됨 - 합성 참조 이미지 Variant(
useCompositeReferenceImage === true)는 라우팅 시점의image/video/audio개수도 정확히 일치해야 함 - 후보 중 미디어 여유 슬롯 수의 합이 작은 Variant를 우선 선택하고, 동률이면
sortOrder오름차순, 이후 전달된 Variant 배열 순서를 적용함. 합성 Variant의 여유 슬롯 점수는 0임 - 미매칭 시 400 에러
- 사용자 입력 주입:
requiredMappings+userInputs기준 주입targetNodeField는 dot 키(resize_type.width)를 flat/nested 모두 처리- 비합성 Variant에서 실제 미디어 개수가 설정과 다르면 실행용 JSON 복사본에서 매핑된 미사용 미디어 입력과 삭제된 로더를 참조하는 연결을 제거함. 원본 템플릿은 유지함
- 합성 Variant 및 미디어 개수가 설정과 모두 일치하는 Variant에는 이 제거 처리를 적용하지 않음
- 비용 계산:
quality+batch_size기준 VT 차감
- 큐 적재:
creationId생성 후 SQS에 작업 등록
Response (202 Accepted)
{
"creationId": "db0dd7e5-2d0b-4802-bf47-a60707387396"
}
3.2 POST /generation
워크플로우 JSON 직접 실행 API입니다.
운영 기능보다는 관리/실험성 요청(예: admin/generate) 용도로 사용합니다.
Request Body
{
"workflow": {
"3": { "...": "..." }
}
}
Response (202 Accepted)
{
"creationId": "f0d0e6aa-...."
}
4. 데이터 스키마 (요약)
4.1 WorkflowGroup
interface WorkflowGroup {
id: string;
name: string;
description?: string;
type: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'TEXT';
isPublic: boolean;
isDefault: boolean;
isPreload: boolean;
isArchived: boolean;
priceSD: number;
priceHD: number;
priceFHD: number;
variants: WorkflowVariant[];
createdAt: string;
updatedAt: string;
}
4.2 WorkflowVariant
interface WorkflowVariant {
id: string;
// text는 정확한 개수. 비합성 image/video/audio는 최대 개수, 합성은 정확한 개수.
inputConfig: { text?: number; image?: number; video?: number; audio?: number };
workflowJson: object;
requiredMappings: Record<string, { nodeId: string; field: string }>;
userInputs?: UserInputSchema[];
sortOrder: number; // 미디어 여유 슬롯 점수가 같을 때 오름차순 우선순위
useCompositeReferenceImage: boolean;
}
가변 참조 이미지 워크플로우 등록 예시
GPT Image 2처럼 참조 이미지 입력을 생략할 수 있는 노드는 최대 슬롯을 준비한 Variant 하나로 여러 입력 개수를 처리할 수 있습니다.
- ComfyUI JSON에
LoadImage16개를 준비하고OpenAIGPTImageNodeV2의model.images.image_1부터model.images.image_16까지 각각 직접 연결합니다. inputConfig를{ "text": 1, "image": 16 },useCompositeReferenceImage를false로 설정합니다.requiredMappings에서text_1은 GPT 노드의inputs.prompt로,image_1부터image_16은 각 로더의inputs.image로 매핑합니다. 이미지 경로는 GPT 노드의 연결 필드에 직접 주입하지 않습니다.- 이미지 3장 요청 시 사용하지 않는 13개 로더와 해당 GPT 입력 연결이 실행용 JSON에서 제거됩니다. 16장 요청 시에는 모든 슬롯을 유지합니다.
미사용 입력은 requiredMappings 또는 userInputs에 등록된 image_N/video_N/audio_N 매핑을 기준으로 찾습니다. 해당 로더를 다른 사용 중 미디어 매핑이 공유하면 로더 자체는 삭제하지 않습니다. 로더가 아닌 대상은 매핑된 입력 필드를 제거합니다.
이 처리는 임의의 전처리 분기 전체를 자동으로 정리하는 기능이 아닙니다. 로더 뒤에 필수 입력을 요구하는 전처리 노드가 있으면 연결 제거 후 실행이 실패할 수 있으므로, 입력 생략이 가능한 노드에 직접 연결하거나 별도 분기 처리가 필요합니다. 현재 inputConfig에는 최소 개수 계약이 없으므로 이미지 0장도 라우팅 후보가 될 수 있습니다. 편집 전용 기능에 최소 1장이 필요하면 별도 요청 검증이 필요합니다.
ComfyUI 노드의 입력 정의는 공식 구현을 참고합니다. 이 설명은 로컬 코드 계약 기준이며 운영 서버 배포 및 실제 ComfyUI 실행 검증을 의미하지 않습니다.
4.3 WorkflowMapping
interface WorkflowMapping {
featureKey: string;
displayName: string;
category: string;
visibility: 'PUBLIC' | 'ADMIN_ONLY' | 'PRIVATE';
workflowGroupId: string;
description?: string;
updatedAt: string;
}
4.4 UserInputSchema
interface UserInputSchema {
id: string;
label: string;
type: 'text' | 'number' | 'image_upload' | 'video_upload' | 'audio_upload' | 'checkbox' | 'select';
targetNodeId: string;
targetNodeField: string;
defaultValue?: string | number | boolean;
min?: number;
max?: number;
options?: Array<{ label: string; value: string | number }>;
}
5. 운영 메모
- Persona/Scene 계열 기능은
workflowId직접 전달보다featureKey전달을 우선 사용합니다. featureKey기반 생성은 관리자가 비공개 전환한 워크플로우를 일반 유저가 우회 호출하지 못하도록 방어합니다.- 재현성 저장 정책:
creations.snapshot(jsonb)을 원본으로 저장:- 최소 키:
text_1,text_2,personaId,lookId,featureKey,workflowGroupId,variantId - 선택 키:
quality(SD/HD/FHD),ratio,refs,seed,batchSize,recipePrompts
- 최소 키:
creationsprojection 컬럼 저장:resolved_prompt,resolved_negative_prompt,ratio,refs
creation_results필수 컬럼 저장:seed,resultIndex,s3Path,thumbnailS3Path
- 배치/정렬 정책:
- 관계:
Creation(1) : CreationResult(N)(Persona 계열 기본N=4) - 히스토리/API 정렬:
creation.createdAt DESC, 동일creationId내resultIndex ASC
- 관계: