16장. ComfyUI를 다른 시스템과 연결하기
16장. ComfyUI를 다른 시스템과 연결하기
ComfyUI를 오래 쓰다 보면 어느 순간 깨닫게 된다. 캔버스 안에서 노드를 잘 잇는 능력만으로는 프로덕션이 완성되지 않는다는 사실이다. 진짜 실무에서는 생성 버튼을 누르는 사람보다, 언제 누를지 결정하는 시스템이 더 중요하다. 폼이 제출되면 이미지가 나와야 하고, 상품 데이터가 들어오면 배너가 만들어져야 하며, 승인 메시지가 오면 영상 후반 작업이 이어져야 한다.
그 순간 ComfyUI의 정체가 바뀐다. 더 이상 혼자 쓰는 생성 도구가 아니라, 다른 시스템이 호출하는 추론 엔진이 된다. 이 장의 목표는 바로 그 전환이다. REST와 WebSocket API로 워크플로를 원격 실행하고, Python으로 트리거하고, MCP를 통해 LLM 에이전트가 호출하게 만들고, n8n·Make 같은 자동화 도구와 연결하고, 웹앱과 브라우저 확장 프로그램까지 얹어 보는 것이다. 이 장을 지나면 ComfyUI는 도구가 아니라 인프라가 된다.

16.1 ComfyUI를 API 서버로 사용하기: REST와 WebSocket의 역할 분담
ComfyUI에는 이미 외부 호출을 위한 HTTP API와 WebSocket 인터페이스가 들어 있다. 즉, 별도 플러그인을 붙이지 않아도 워크플로 실행, 큐 관리, 결과 조회, 이미지 업로드, 실시간 진행 상황 수신이 가능하다.13 중요한 것은 이 기능을 "숨겨진 개발자 기능" 정도로 보지 않는 것이다. 프로덕션에서는 이 API가 사실상 ComfyUI의 두 번째 얼굴이다.
먼저 출발점은 workflow_api.json이다. UI에서 만든 그래프를 그대로 외부 프로그램이 실행하려면, 개발자 옵션을 켠 뒤 Save (API format) 으로 내보낸 JSON이 필요하다.23 이 파일은 말하자면 "워크플로 설계도"다. 사람은 노드를 보지만, 외부 시스템은 이 JSON을 본다.
ComfyUI API의 기본 흐름은 놀랄 만큼 단순하다.
| 단계 | 엔드포인트 | 하는 일 |
|---|---|---|
| 1 | /upload/image 또는 /upload/{image_type} | 입력 이미지나 마스크를 서버에 올린다 |
| 2 | /prompt | 워크플로 JSON을 실행 큐에 넣고 prompt_id를 받는다 |
| 3 | /ws | 실행 중인 노드, 샘플링 진행률, 에러를 실시간으로 받는다 |
| 4 | /history/{prompt_id} | 완료된 실행의 출력 메타데이터를 조회한다 |
| 5 | /view | 실제 이미지 파일을 바이너리로 가져온다 |
| 6 | /queue, /interrupt 등 | 대기열 조회와 중단 같은 운영 제어를 한다 |
여기서 REST와 WebSocket은 경쟁 관계가 아니다. 둘은 분업 관계다. REST는 "일을 맡기는 손"이고, WebSocket은 "무슨 일이 벌어지는지 듣는 귀"다. 생성 작업이 몇 초에서 몇 분까지 걸릴 수 있기 때문에, /prompt만 호출한 뒤 무작정 sleep(30) 같은 코드로 기다리는 방식은 금세 한계에 닿는다. 특히 영상 생성처럼 긴 작업에서는 진행률, 현재 실행 노드, 캐시된 노드, 완료 여부를 실시간으로 받아야 사용자 경험도 좋아지고 장애 처리도 쉬워진다.24
WebSocket에서 자주 보게 되는 이벤트도 미리 익혀 두면 좋다. status는 큐 상태를, executing은 현재 어떤 노드가 도는지를, progress는 KSampler 같은 샘플링 단계의 진행률을, executed는 노드 완료를 알려 준다. 캐시가 사용되면 execution_cached가 오고, 실패하면 execution_error 메시지와 traceback이 따라온다. 경우에 따라 미리보기 이미지가 바이너리로 흘러오기도 한다.4
프로덕션에서 특히 유용한 추가 엔드포인트도 있다. /queue는 현재 큐 상황을 파악하는 데 좋고, /system_stats는 장비 상태와 런타임 정보를 확인하는 데 도움을 주며, /object_info는 사용 가능한 노드 정의를 가져와 동적 UI를 만드는 데 쓸 수 있다.3 즉, ComfyUI API는 단순 실행기만이 아니라, 운영과 모니터링까지 염두에 둔 표면을 갖고 있다.
실무에서는 보통 이런 식으로 생각하면 된다. 사용자의 요청이 들어오면 백엔드가 워크플로 JSON을 조정해 /prompt에 넣고, 진행률은 /ws로 받아 프론트엔드에 흘려 보내고, 완료 후 /history와 /view로 결과를 회수한다. 이 구조만 잡히면 ComfyUI는 이미 앱의 백엔드다.12
16.2 Python 스크립트로 워크플로우 트리거하기
Python은 ComfyUI를 외부에서 다룰 때 가장 자연스러운 첫 도구다. 이유는 간단하다. 노트북 환경, 백엔드 서버, 배치 스크립트, 크론 작업, 데이터 파이프라인까지 전부 Python이 잘 어울리기 때문이다. 그리고 ComfyUI의 API 사용 패턴도 Python 코드로 표현하기 쉽다.25
가장 기본적인 구조는 네 단계다. 먼저 workflow_api.json을 읽는다. 다음으로 사용자 입력에 맞춰 프롬프트, 시드, 해상도, 입력 이미지 파일명 같은 값을 바꾼다. 그 뒤 /prompt로 큐에 넣고, WebSocket으로 완료를 기다린 다음 /history와 /view로 결과를 받아 온다.2
아주 짧게 쓰면 구조는 이런 느낌이다.
import json, uuid, requests, websocket
server = "127.0.0.1:8188"
client_id = str(uuid.uuid4())
with open("workflow_api.json", "r", encoding="utf-8") as f:
workflow = json.load(f)
# 예: 프롬프트와 시드 수정
workflow["6"]["inputs"]["text"] = "cinematic product photo, soft studio light"
workflow["3"]["inputs"]["seed"] = 987654321
# 실행 요청
resp = requests.post(
f"http://{server}/prompt",
json={"prompt": workflow, "client_id": client_id}
).json()
prompt_id = resp["prompt_id"]
# 진행 상황 수신
ws = websocket.WebSocket()
ws.connect(f"ws://{server}/ws?clientId={client_id}")
while True:
message = json.loads(ws.recv())
if message["type"] == "executing":
data = message["data"]
if data["node"] is None and data["prompt_id"] == prompt_id:
break
ws.close()
# 결과 조회
history = requests.get(f"http://{server}/history/{prompt_id}").json()
print(history.keys())이 코드는 간단해 보이지만, 개념적으로는 아주 중요하다. ComfyUI 워크플로를 함수처럼 호출하고 있기 때문이다. 입력값을 바꿔 같은 워크플로를 여러 번 실행할 수 있고, 다른 시스템에서 받은 값을 그대로 주입할 수도 있다. 예를 들어 전자상거래 시스템에서 상품명과 색상 정보를 받아 배너를 만들거나, CMS에서 글 제목을 받아 썸네일을 생성하거나, 음성 파일이 업로드되면 영상 워크플로를 자동 실행하는 식이다.
Python 방식의 장점은 단순 자동화에만 있지 않다. Jupyter Notebook과 붙이면 생성 과정을 인터랙티브하게 실험할 수 있고, 백엔드 서버와 붙이면 웹 서비스가 되며, 배치 워커와 붙이면 야간 대량 생성기가 된다.5 같은 ComfyUI라도, 어떤 Python 프로그램과 연결하느냐에 따라 역할이 완전히 달라진다.
다만 실무에서는 몇 가지 습관이 중요하다.
워크플로 JSON은 매번 새로 작성하지 말고, 검증된 템플릿을 불러와 필요한 값만 바꾼다.
노드 ID를 하드코딩할 때는 어떤 노드가 무엇인지 주석이나 매핑을 남겨 둔다.
결과 파일만 받지 말고
prompt_id, 입력값, 시드, 모델명도 함께 저장한다.긴 작업은 반드시 WebSocket이나 명시적 상태 확인으로 추적한다.
실패 시 재시도 정책과 타임아웃 정책을 분리한다.
이런 습관이 쌓이면 Python 스크립트는 단순 호출기가 아니라 작은 오케스트레이터가 된다.
16.3 MCP 서버 연동: Claude·LLM 에이전트가 ComfyUI를 호출하게 만들기
여기서 한 단계 더 가 보자. 사람이 버튼을 누르는 대신, LLM 에이전트가 상황을 이해하고 적절한 워크플로를 고른 다음 ComfyUI를 호출하게 만들 수 있을까? 2026년의 답은 "그렇다, 단 조건이 있다"이다.
MCP(Model Context Protocol)는 LLM이 외부 도구와 표준화된 방식으로 연결되도록 돕는 인터페이스 계층이다. 쉽게 말하면, 에이전트에게 "이 버튼을 눌러라"가 아니라 "이 도구는 이런 입력을 받으면 이런 결과를 준다"라고 설명해 주는 통역사에 가깝다. ComfyUI 자체가 곧바로 MCP 서버인 것은 아니지만, ComfyUI API를 감싸 MCP로 노출하는 관리 도구와 프로젝트들이 이미 등장해 있다.7
이 구조의 핵심은 놀라울 만큼 단순하다. Claude나 다른 에이전트는 MCP 도구 목록에서 "이미지 생성", "워크플로 목록 조회", "결과 확인", "서비스 상태 점검" 같은 기능을 발견한다. 그리고 자연어 지시를 해석해 필요한 도구를 호출한다. 내부적으로는 결국 ComfyUI의 /prompt, /history, /ws 같은 API가 돌아가지만, 에이전트 입장에서는 함수 호출처럼 느껴진다.
이 방식이 강력한 이유는, ComfyUI가 LLM의 손발이 되기 때문이다. 예를 들어 사용자가 "지난주 캠페인 스타일을 유지하면서 신제품용 3개의 배너 시안을 만들어 줘"라고 말하면, 에이전트는 다음 순서를 스스로 조합할 수 있다. 먼저 관련 스타일 템플릿을 찾고, 다음으로 허용된 워크플로를 고른 뒤, 상품명과 카피를 프롬프트에 주입하고, ComfyUI를 실행하고, 결과를 요약해 다시 사용자에게 보여 주는 식이다.
하지만 여기서 가장 중요한 단어는 자유가 아니라 제어다. 에이전트에게 ComfyUI 전체를 무제한으로 열어 주면, 멋진 자동화보다 먼저 혼란이 온다. 프롬프트를 이상하게 바꿀 수도 있고, 잘못된 모델을 고를 수도 있고, GPU를 비싼 영상 작업으로 오래 점유할 수도 있다. 그래서 MCP 연동에서는 보통 다음 원칙이 필요하다.
에이전트가 호출할 수 있는 워크플로를 허용 목록으로 제한한다.
입력 가능한 파라미터 범위를 정해 둔다.
결과 저장 위치와 파일 접근 범위를 분리한다.
비밀값과 API 키는 운영체제 보안 저장소나 서버 비밀 관리 계층에 둔다.7
MCP 기반 관리 도구 중에는 ComfyUI 상태 모니터링, 워크플로 검색, 메모리 관리, 서비스 시작·중지 같은 기능까지 함께 제공하는 사례도 있다. 이런 도구는 단순한 "LLM 연결기"가 아니라, ComfyUI 운영 콘솔에 더 가깝다.7 다시 말해 에이전트 시대의 ComfyUI는 캔버스 위 노드보다, 정책이 걸린 실행 엔진으로 보는 편이 정확하다.
16.4 N8N, Make 등 노코드 자동화와 결합하기
Python이 개발자 친화적인 길이라면, n8n과 Make는 운영 친화적인 길이다. 둘의 공통점은 ComfyUI를 창작 도구가 아니라 자동화 스텝으로 다룬다는 점이다. 웹훅이 오면 실행하고, DB에 행이 추가되면 실행하고, 슬랙 승인 메시지가 달리면 다음 단계로 넘긴다. ComfyUI는 그 흐름 안에서 이미지나 영상을 생성하는 엔진 한 칸이 된다.6
특히 n8n은 ComfyUI와 결합했을 때 그림이 잘 그려진다. 이유는 간단하다. n8n은 원래 수많은 외부 서비스 사이를 잇는 오케스트레이터이고, ComfyUI는 생성 품질과 커스텀 제어가 강한 엔진이기 때문이다. 둘을 붙이면 "누가 요청했는가, 무엇을 만들 것인가, 어디에 저장할 것인가, 누구에게 알릴 것인가"를 하나의 흐름으로 묶을 수 있다.6
연동 방식은 두 갈래다. 하나는 커뮤니티 노드를 쓰는 방법이고, 다른 하나는 HTTP Request 노드로 ComfyUI API를 직접 두드리는 방법이다. 전자는 빠르게 붙이기 좋고, 후자는 동작을 세밀하게 통제하기 좋다.6 프로덕션에서는 후자를 알아 두는 편이 유리하다. 결국 본질은 /prompt에 JSON을 보내고, 완료를 기다린 뒤, /history와 /view에서 결과를 가져오는 구조이기 때문이다.3
가장 전형적인 n8n 흐름은 이렇다.
| 순서 | n8n/Make에서 하는 일 | ComfyUI 쪽 동작 |
|---|---|---|
| 1 | Webhook, Form, Schedule, Chat Trigger로 시작 | 실행 요청을 받을 준비 |
| 2 | Code/Set 노드에서 workflow_api.json의 일부 값 수정 | 프롬프트, 시드, 입력 이미지 경로 반영 |
| 3 | HTTP POST로 /prompt 호출 | 큐에 워크플로 등록 |
| 4 | Wait 또는 상태 체크 루프 | 생성 진행 |
| 5 | GET /history/{prompt_id} | 결과 메타데이터 확인 |
| 6 | GET /view | 이미지 바이너리 다운로드 |
| 7 | Drive, S3, Slack, Notion, Airtable 등으로 전달 | 결과물 배포 완료 |
n8n에서는 이 구조를 시각적으로 다룰 수 있다는 점이 좋다. 승인 플로우, 실패 시 재시도, 업로드 후 후처리, 메타데이터 기록, 다른 AI 모델과의 조합 같은 업무 로직을 한 화면에서 관리할 수 있다.6 ComfyUI 혼자서는 강하지만, n8n과 붙으면 비로소 조직의 일감 흐름 속에 들어간다.
Make도 본질은 같다. 전용 생태계가 n8n만큼 풍부하지 않더라도, HTTP 모듈과 Webhook, 파일 저장 모듈만 있으면 충분하다. 오히려 Make는 비개발 부서가 빠르게 실험용 자동화를 만들 때 강점이 있다. 예를 들어 구글 시트에 상품 정보가 들어오면 ComfyUI로 썸네일을 만들고, 결과를 드라이브에 저장한 뒤 슬랙으로 보내는 시나리오는 Make에서도 어렵지 않다. 핵심은 도구 이름이 아니라 패턴이다. 이벤트 → JSON 주입 → /prompt → 상태 확인 → 결과 회수 → 배포. 이 패턴만 이해하면 어떤 노코드 도구로도 ComfyUI를 붙일 수 있다.
운영 팁도 하나 기억해 두자. n8n이나 Make가 Docker 안에서 돌고 ComfyUI가 호스트 머신에서 돌면, 127.0.0.1이 서로 다른 세계를 가리킬 수 있다. 이때는 실제 내부 IP나 host.docker.internal 같은 경로를 써야 한다는 점을 자주 놓친다.6 현업에서는 모델보다 네트워크 주소 때문에 더 오래 헤매는 날도 있다.
16.5 Chrome Extension, 웹앱과의 연결: ComfyUI를 사용자 인터페이스 뒤로 숨기기
이제 마지막 퍼즐 조각은 인터페이스다. 외부 시스템과 연결하는 궁극적인 이유는 대부분 하나다. ComfyUI를 직접 보여 주지 않고도, ComfyUI의 힘을 쓰고 싶기 때문이다.
웹앱 쪽에서 가장 실용적인 방법은 ComfyUI를 백엔드로 두고, 앞단에는 필요한 입력만 노출한 얇은 UI를 만드는 것이다. 사용자는 프롬프트, 이미지 업로드, 해상도, 브랜드 옵션 정도만 보고, 복잡한 노드 그래프는 보지 않는다. 이런 접근을 돕는 오픈소스 도구와 서비스들이 이미 나와 있다. 예를 들어 ViewComfy는 workflow_api.json을 바탕으로 워크플로를 앱처럼 포장해 공유할 수 있게 해 주고, ComfyFlowApp도 ComfyUI 워크플로를 사용자 친화적인 웹앱으로 바꾸는 흐름을 제시한다.910
이 접근이 중요한 이유는 아주 현실적이다. 팀원이나 고객은 노드 그래프를 배우고 싶어 하지 않는다. 그들은 "상품 사진을 올리면 배경 합성본이 나온다" 같은 기능을 원한다. 그러니 ComfyUI를 직접 가르치는 대신, ComfyUI가 돌아가는 제품을 만드는 편이 훨씬 낫다. 이때 필요한 것은 복잡한 생성 엔진이 아니라, 잘 설계된 입력 폼과 상태 표시, 결과 다운로드 버튼이다.
웹앱을 만들 때는 아예 외부 프론트엔드로 분리할 수도 있지만, ComfyUI 클라이언트 자체를 확장하는 방법도 있다. ComfyUI는 커스텀 노드 패키지 안에 WEB_DIRECTORY를 내보내고, JavaScript 파일에서 app.registerExtension()을 호출하는 식으로 웹 클라이언트를 확장할 수 있다.8 즉, 내부 전용 패널, 프리셋 선택기, 사내 스타일 버튼, 큐 대시보드, 전용 입력 폼 같은 것을 ComfyUI 프론트엔드 안에 직접 심을 수 있다는 뜻이다.
브라우저 확장 프로그램도 흥미로운 연결 지점이다. Chrome 확장은 사용자가 보고 있는 웹페이지의 컨텍스트를 바로 잡아낼 수 있다. 예를 들어 상품 상세 페이지의 제목과 이미지를 읽어 ComfyUI 워크플로에 보내거나, 브라우저에서 캡처한 이미지를 바로 업로드해 리터치 파이프라인으로 넘길 수 있다. 이미 ComfyUI Studio 같은 확장은 브라우저 툴바에서 RunPod 관리와 CivitAI 연계를 제공하면서, 브라우저가 ComfyUI 운영 콘솔이 될 수 있음을 보여 준다.11
실무적으로 보면 16.5의 핵심은 "무엇을 붙일 수 있나"가 아니라 "누구에게 무엇을 숨길 것인가"다. 디자이너에게는 스타일 옵션만 보이고, 마케터에게는 카피와 포맷만 보이며, 운영자에게는 큐와 에러 로그만 보이게 만드는 식이다. ComfyUI가 뒤에서 돌고 있다는 사실은 중요하지만, 모두가 그 사실을 직접 볼 필요는 없다.
엔진에서 인프라로
이 장의 앞부분에서 ComfyUI를 API 서버로 다루는 법을 봤고, 중간에서는 Python과 MCP, n8n·Make로 호출하는 법을 봤고, 마지막에는 웹앱과 브라우저까지 연결했다. 이 흐름을 한 문장으로 정리하면 이렇다.
ComfyUI를 직접 쓰는 사람보다, ComfyUI를 호출하는 시스템이 많아질수록 그 조직의 생성 파이프라인은 강해진다.
도구는 사람이 열어야 움직인다. 인프라는 사건이 생기면 스스로 움직인다. 새 상품이 등록되면 배너가 생기고, 원고가 승인되면 썸네일이 만들어지고, 음성이 업로드되면 영상 시안이 렌더된다. ComfyUI가 이 흐름의 중심 엔진이 되면, 노드는 더 이상 화면 위 박스가 아니다. 그것은 조직의 제작 공정을 이루는 작은 기계들이다.
이제 다음 단계는 자연스럽다. 이렇게 중요한 엔진을 계속 남의 노드에만 의존해도 될까? 다음 장에서는 바로 그 질문으로 들어간다. ComfyUI를 진짜 내 인프라로 만들기 위한 첫 걸음, 커스텀 노드 개발이다.
참고
1HTTP and WebSocket API | comfyanonymous/ComfyUI | DeepWiki
2Building a Production-Ready ComfyUI API: A Complete Guide
3ComfyUI API Endpoints Guide: Complete Reference for Image Generation Workflows
4WebSocket Protocol | Comfy-Org/ComfyUI | DeepWiki
5WebSockets & ComfyUI: Building Interactive AI Applications
6Automating Image Generation with n8n and ComfyUI
7lazniak/comfy-mcp: manage comfy API endpoints by mcp
8Javascript Extensions - ComfyUI
9How to turn a ComfyUI workflow into a web app in minutes
10xingren23/ComfyFlowApp: From comfyui workflow to web app, in seconds
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.