프로젝트로 돌아가기
ComfyUI API 파이프라인 구축 가이드12 min

Linux에서 Windows ComfyUI 원격 호출: 엔드투엔드 실전 테스트

Linux 서버에서 job.json을 만들어 Windows로 전송하고, SSH로 worker.ps1을 실행한 뒤 생성된 이미지를 다시 가져오는 전체 흐름을 실제 명령어로 실행합니다.

전체 흐름 한눈에 보기

지금까지 준비한 것들을 이어서 실행합니다. Linux 서버에서 시작해서 이미지를 받아오는 전체 흐름입니다.

Linux 서버                          Windows 서버
────────────────────────────────    ──────────────────────────────────
1. job.json 생성
2. SCP -> iojob.json 전송  ───────> iojob.json 수신
3. SSH로 worker.ps1 실행   ───────> worker.ps1 실행
                                        comfy_workflow.json 읽기
                                        job.json 읽기
                                        프롬프트 노드 교체
                                        POST /prompt -> ComfyUI
                                        GET /history 폴링
                                        GET /view -> 이미지 다운로드
                                        output
esult_날짜시간.jpg 저장
                                        io
esult.json 작성
4. SCP <- result.json 회수 <───────  result.json 완료
5. SCP <- 이미지 파일 회수 <───────  output
esult_...jpg 전송

전제 조건

이 단계를 진행하기 전에 아래가 준비되어 있어야 합니다.

  • Windows 서버에 OpenSSH Server가 설치 및 실행 중입니다.
  • Linux에서 SSH 키로 Windows에 접속할 수 있습니다 (/root/.ssh/id_ed25519_cardnews).
  • D:\016_CardNew 폴더 구조가 만들어져 있습니다.
  • D:\016_CardNewiocomfy_workflow.json이 있습니다.
  • ComfyUI가 E:AI에 설치되어 있습니다.

0단계: ComfyUI 시작 확인

작업 전에 Windows에서 ComfyUI가 실행 중인지 확인합니다. Linux에서 SSH로 확인할 수 있습니다.

ssh -i /root/.ssh/id_ed25519_cardnews reedoc@<WINDOWS_IP> \n  'powershell -NoProfile -Command "Invoke-RestMethod -Method Get -Uri http://127.0.0.1:8188/system_stats | ConvertTo-Json -Depth 3"'

응답으로 GPU 정보가 오면 ComfyUI가 실행 중입니다.

{
  "system": {
    "os": "Windows",
    "python_version": "3.12.x",
    "embedded_python": true
  },
  "devices": [
    {
      "name": "NVIDIA GeForce RTX ...",
      "type": "cuda",
      "vram_total": 8589934592,
      "vram_free": 7000000000
    }
  ]
}

ComfyUI가 꺼져 있으면 먼저 restart-comfy.ps1을 실행합니다.

ssh -i /root/.ssh/id_ed25519_cardnews reedoc@<WINDOWS_IP> \n  'powershell -NoProfile -ExecutionPolicy Bypass -File "D:\016_CardNewio
estart-comfy.ps1"'

이 명령은 ComfyUI를 재시작하고, 20초 기다린 후 system_stats를 조회해서 결과를 반환합니다. 정상 응답이 오면 이미지 생성 요청을 보낼 수 있습니다.

1단계: job.json 생성

Linux에서 작업 요청 파일을 만듭니다.

cat > /tmp/job.json << 'JSON'
{
  "job_id": "test_001",
  "topic": "card_test",
  "image_prompt": "cozy korean chibi girl, cat-ear hoodie, warm pastel light, cinematic",
  "negative_prompt": "blurry, watermark, text"
}
JSON

파일이 제대로 만들어졌는지 확인합니다.

cat /tmp/job.json

JSON 내용이 그대로 출력되면 정상입니다. 프롬프트를 바꾸려면 image_prompt 값을 수정합니다. job_id는 고유값이어야 합니다. 같은 job_id를 여러 번 쓰면 결과를 추적할 때 혼동됩니다.

2단계: SCP로 Windows에 전송

job.json을 Windows 서버의 D:\016_CardNewio 폴더로 보냅니다.

scp -i /root/.ssh/id_ed25519_cardnews \n  /tmp/job.json \n  reedoc@<WINDOWS_IP>:"D:/016_CardNew/io/job.json"

<WINDOWS_IP>를 실제 IP 주소로 바꿉니다. Windows 경로를 SCP로 지정할 때는 큰따옴표 안에 슬래시(/)를 씁니다. 백슬래시를 쓰면 Linux 쉘이 이스케이프 문자로 해석합니다.

전송 완료 시 출력 예시입니다.

job.json                  100%  181    15.2KB/s   00:00

파일 크기(181 bytes)와 전송 속도가 나오면 성공입니다.

3단계: SSH로 worker.ps1 실행

SSH로 Windows에 접속해서 worker.ps1을 실행합니다.

ssh -i /root/.ssh/id_ed25519_cardnews reedoc@<WINDOWS_IP> \n  'powershell -NoProfile -ExecutionPolicy Bypass -File "D:\016_CardNewscriptsworker.ps1"'

이 명령은 worker.ps1이 완전히 끝날 때까지 기다립니다. 이미지 생성이 10~30초 걸리므로 그 시간 동안 터미널이 멈춘 것처럼 보입니다. 정상입니다.

정상 실행 시 터미널에 찍히는 출력입니다.

[INFO] promptId=626d4d7c-6955-4577-a2b6-80d4cd80c172
[OK] saved: D:\016_CardNewoutput
esult_20260322_105758.jpg

[INFO] promptId=... 줄이 나오면 ComfyUI가 이미지 생성을 시작한 것입니다. [OK] saved: ... 줄이 나오면 이미지가 저장되고 result.json이 작성된 것입니다.

4단계: result.json 회수

worker.ps1이 쓴 result.json을 Linux로 가져옵니다.

scp -i /root/.ssh/id_ed25519_cardnews \n  reedoc@<WINDOWS_IP>:"D:/016_CardNew/io/result.json" \n  /tmp/result.json

cat /tmp/result.json

result.json 내용 예시입니다.

{
  "status": "ok",
  "prompt_id": "626d4d7c-6955-4577-a2b6-80d4cd80c172",
  "output_image": "D:\016_CardNew\output\result_20260322_105758.jpg"
}

"status": "ok"를 확인합니다. "error"가 나오면 이미지 생성이 실패한 것입니다. "message" 필드에 실패 원인이 담겨 있습니다. "wait"가 나오면 job.json 파일이 전송되지 않은 것입니다.

output_image 경로에서 파일명만 뽑습니다.

OUTPUT_FILE=$(python3 -c "
import json
d = json.load(open('/tmp/result.json', encoding='utf-8'))
print(d['output_image'].replace('\\\\', '/').split('/')[-1])
")
echo $OUTPUT_FILE
# 출력: result_20260322_105758.jpg

5단계: 이미지 회수

result.json에서 파악한 파일명의 이미지를 Linux로 가져옵니다.

scp -i /root/.ssh/id_ed25519_cardnews \n  reedoc@<WINDOWS_IP>:"D:/016_CardNew/output/${OUTPUT_FILE}" \n  /tmp/${OUTPUT_FILE}

ls -lh /tmp/${OUTPUT_FILE}

파일 크기가 수백 KB에서 수 MB이면 정상적인 이미지입니다. 0바이트라면 전송 중 문제가 생긴 것입니다.

이미지를 원하는 위치에 저장합니다.

cp /tmp/${OUTPUT_FILE} /home/user/generated-images/test_001.jpg

전체를 하나의 쉘 스크립트로 묶기

매번 명령을 하나씩 치는 것은 불편합니다. 쉘 스크립트로 묶으면 한 번 실행으로 전체 흐름이 돌아갑니다.

#!/bin/bash
# send-and-fetch.sh -- ComfyUI 이미지 생성 파이프라인

set -e

WINDOWS_IP="<WINDOWS_IP>"
SSH_KEY="/root/.ssh/id_ed25519_cardnews"
WIN_USER="reedoc"
JOB_FILE="/tmp/job.json"
IMAGE_DIR="/tmp/generated"

mkdir -p "${IMAGE_DIR}"

# 1. job.json 전송
echo "[1/4] job.json 전송 중..."
scp -i "${SSH_KEY}" "${JOB_FILE}" "${WIN_USER}@${WINDOWS_IP}:D:/016_CardNew/io/job.json"

# 2. worker.ps1 실행
echo "[2/4] worker.ps1 실행 중..."
ssh -i "${SSH_KEY}" "${WIN_USER}@${WINDOWS_IP}" \n  'powershell -NoProfile -ExecutionPolicy Bypass -File "D:\016_CardNewscriptsworker.ps1"'

# 3. result.json 회수
echo "[3/4] result.json 회수 중..."
scp -i "${SSH_KEY}" "${WIN_USER}@${WINDOWS_IP}:D:/016_CardNew/io/result.json" /tmp/result.json

STATUS=$(python3 -c "import json; print(json.load(open('/tmp/result.json', encoding='utf-8'))['status'])")
if [ "${STATUS}" != "ok" ]; then
  echo "[ERROR] worker 실패: ${STATUS}"
  cat /tmp/result.json
  exit 1
fi

OUTPUT_FILE=$(python3 -c "
import json
d = json.load(open('/tmp/result.json', encoding='utf-8'))
print(d['output_image'].replace('\\\\\\\\', '/').split('/')[-1])
")

# 4. 이미지 회수
echo "[4/4] 이미지 회수 중: ${OUTPUT_FILE}"
scp -i "${SSH_KEY}" "${WIN_USER}@${WINDOWS_IP}:D:/016_CardNew/output/${OUTPUT_FILE}" \n  "${IMAGE_DIR}/${OUTPUT_FILE}"

echo "[완료] ${IMAGE_DIR}/${OUTPUT_FILE}"

저장 후 실행 권한을 주고 실행합니다.

chmod +x send-and-fetch.sh
./send-and-fetch.sh

트러블슈팅

ComfyUI가 응답하지 않을 때

POST /prompt에서 Connection refused가 나오면 ComfyUI가 꺼진 것입니다. restart-comfy.ps1을 먼저 실행합니다.

ssh -i /root/.ssh/id_ed25519_cardnews reedoc@<WINDOWS_IP> \n  'powershell -NoProfile -ExecutionPolicy Bypass -File "D:\016_CardNewio
estart-comfy.ps1"'

result.json에 timeout 에러가 있을 때

worker.ps1이 300번(600초) 폴링했지만 결과가 없었다는 뜻입니다. ComfyUI가 이미지 생성을 시작했지만 완료하지 못한 경우입니다. 원인은 보통 두 가지입니다.

첫 번째, GPU VRAM이 부족합니다. 다른 프로그램이 VRAM을 점유하고 있으면 ComfyUI가 모델을 올리지 못합니다. Windows에서 작업 관리자로 GPU 메모리 사용량을 확인합니다.

두 번째, 모델 파일이 없거나 손상되었습니다. ComfyUI GUI에서 직접 워크플로우를 실행해서 오류 메시지를 확인합니다.

SCP 경로 오류

Windows 경로를 SCP로 지정할 때 큰따옴표와 슬래시 방향에 주의합니다.

올바른 형식: reedoc@<IP>:"D:/016_CardNew/io/job.json"

잘못된 형식: reedoc@<IP>:D:\016_CardNewiojob.json (따옴표 없음, 백슬래시)

SSH 키 권한 오류

WARNING: UNPROTECTED PRIVATE KEY FILE!

이 메시지가 나오면 SSH 키 파일 권한이 너무 넓게 열려 있습니다.

chmod 600 /root/.ssh/id_ed25519_cardnews

result.json에 "status": "wait"가 나올 때

job.json이 Windows에 전송되지 않았거나, 경로가 잘못된 것입니다. SCP 명령을 다시 확인합니다. Windows 서버에서 직접 D:\016_CardNewio 폴더를 확인해서 job.json이 있는지 봅니다.

파이프라인 완성

이 네 단계의 가이드로 구성한 것을 정리합니다.

1단계: ComfyUI 설치 위치(E:AI), API 엔드포인트, 워크플로우 API Format 내보내기를 이해했습니다.

2단계: D:\016_CardNew 폴더 구조를 만들고 job.json, result.json, comfy_workflow.json의 실제 내용을 확인했습니다.

3단계: worker.ps1 전체 코드를 블록별로 분석했습니다. 에러 처리, 프롬프트 주입, 재시도 로직, 폴링, 이미지 다운로드까지 전부 다뤘습니다.

4단계: Linux에서 SSH와 SCP로 전체 파이프라인을 엔드투엔드로 실행했습니다. 쉘 스크립트로 묶어서 한 번에 실행할 수 있게 만들었습니다.

이제 Linux에서 image_prompt만 바꿔서 job.json을 만들면, Windows ComfyUI가 이미지를 생성하고, 결과 이미지가 Linux로 돌아오는 완전한 파이프라인이 동작합니다.

리도 프로필

리도 인사이트

기술을 현장 언어로 다시 풀어 쓰는 사람

3D 설계, 광통신 인프라 장비 개발, 글로벌 현장 교육을 19년 넘게 다뤄왔고, 요즘은 AI 자동화, 꿈꾸는 카메라, 실무 채널 운영을 연결해 복잡한 일을 더 쉽게 만드는 방법을 기록하고 있습니다.

다음 대화

읽고 끝내지 말고, 실제 문제로 이어가도 좋습니다.

자동화, 설계, 교육, 콘텐츠 중 무엇이든 지금 필요한 문제부터 같이 정리해볼 수 있습니다.

편하게 문의하기