Published on

SDXL+ComfyUI VRAM OOM 해결 - 메모리 최적화

Authors

서로 다른 워크플로를 조금만 섞어도 SDXL은 VRAM을 빠르게 잡아먹습니다. 특히 ComfyUI는 노드 그래프 특성상 중간 텐서가 오래 살아남는 구조가 되기 쉬워, 같은 프롬프트를 A1111에서 돌릴 때는 괜찮던 GPU가 ComfyUI에서는 CUDA out of memory로 죽는 경우가 많습니다.

이 글은 “무작정 옵션을 끄는” 대신, OOM이 어디서 발생하는지를 기준으로 SDXL+ComfyUI 메모리 사용량을 체계적으로 줄이는 방법을 정리합니다. 목표는 다음 3가지입니다.

  • 같은 GPU에서 더 큰 해상도 또는 더 많은 스텝을 안정적으로 수행
  • OOM 발생 시 재현 가능한 체크리스트로 빠르게 원인 파악
  • 속도 저하를 최소화하면서 VRAM 상한을 관리

관련해서 문제를 “증상 기반으로 분해하고 체크리스트로 수습”하는 접근은 인프라 트러블슈팅과도 유사합니다. 예를 들어 타임아웃을 지점별로 쪼개 진단하는 글인 AWS ALB 502/504 급증? 타임아웃 7곳 점검처럼, OOM도 어디서 메모리가 폭증하는지 단계별로 쪼개보면 해결이 빨라집니다.

1) OOM이 터지는 대표 지점 5가지

SDXL 파이프라인을 VRAM 관점에서 크게 나누면 아래 구간에서 터집니다.

  1. UNet(디노이징) 어텐션: 해상도와 배치가 커질수록 가장 크게 증가
  2. VAE 인코드/디코드: 고해상도에서 순간 피크가 커짐
  3. ControlNet / IP-Adapter / LoRA 다중 적용: 모델 및 중간 피처 추가
  4. 업스케일/리파이너(Refiner): 두 번째 UNet 또는 업스케일러가 추가로 VRAM 사용
  5. 중간 결과 보관(Preview, Save, latent 캐시): ComfyUI 노드가 텐서를 붙잡고 있으면 누수처럼 보임

즉, “SDXL이라서 무조건 무겁다”가 아니라 해상도·배치·어텐션 구현·VAE 피크·부가 모델이 합쳐져 OOM이 납니다.

2) 먼저 현재 VRAM 사용량을 ‘측정 가능한 형태’로 만들기

최적화는 측정이 먼저입니다. 최소한 아래 2가지는 확보하세요.

  • 실행 중 nvidia-smi피크 VRAM 확인
  • OOM 직전 단계가 어떤 노드/구간인지 확인

nvidia-smi 실시간 모니터링

watch -n 0.5 nvidia-smi

또는 로그를 남기고 싶다면:

nvidia-smi --query-gpu=timestamp,utilization.gpu,memory.used,memory.total --format=csv -l 1

ComfyUI는 워크플로에 따라 메모리 피크가 “특정 노드 실행 순간”에 튀기 때문에, OOM이 터지는 순간의 피크를 잡아두면 다음 조치(해상도, 타일, 오프로딩)의 우선순위가 명확해집니다.

3) 가장 효과 큰 1순위: 해상도와 배치(특히 SDXL은 면적이 핵심)

SDXL은 텍스트 인코더도 있지만, OOM의 주범은 대개 UNet의 어텐션입니다. 어텐션 메모리는 대략적으로 토큰 수(=특징맵 공간 크기)에 비례하고, 이는 해상도의 “가로×세로” 면적에 강하게 연동됩니다.

권장 기본값(안정 우선)

  • 배치: batch_size=1 고정
  • 해상도: 1024 계열은 VRAM이 빡빡하면 896x1152, 832x1216 같은 “근접 비율”로 타협
  • 스텝: OOM과 직접 상관은 덜하지만, 미세하게 피크에 영향

ComfyUI에서는 Empty Latent Image 또는 Latent 생성 노드에서 크기를 만지는 경우가 많습니다. 1024x1024가 꼭 필요하지 않다면 먼저 면적을 10~15%만 줄여도 체감적으로 OOM이 사라집니다.

4) ComfyUI에서 바로 적용 가능한 VRAM 절감 스위치들

여기서부터는 “속도 vs VRAM” 트레이드오프를 옵션별로 정리합니다.

4-1) xFormers / SDP(Scaled Dot Product) 계열 어텐션 사용

어텐션 구현에 따라 VRAM이 크게 달라집니다. 환경에 따라 명칭이 다르지만, 핵심은 메모리 효율 어텐션을 켜는 것입니다.

  • 가능하면 xFormers 사용
  • PyTorch의 SDP(Flash / Mem Efficient) 경로가 활성화되도록 설정

설치 예시(환경에 맞게 조정):

pip install -U xformers

주의: xFormers는 CUDA/PyTorch 버전 궁합이 중요합니다. 설치 후 ComfyUI 콘솔 로그에서 xFormers 사용 여부를 확인하세요.

4-2) VAE를 타일 디코드로 바꿔 피크를 낮추기

고해상도에서 OOM이 “마지막 디코드 순간”에 터진다면, UNet이 아니라 VAE 디코드 피크일 가능성이 큽니다. 이때는 VAE 타일 디코드가 가장 즉효입니다.

  • 타일 크기 작을수록 VRAM 감소, 속도는 저하
  • 오버랩을 약간 주면 타일 경계 아티팩트가 줄어듦

ComfyUI에서 VAE 타일 관련 노드를 사용하거나, 확장 노드(커스텀 노드)로 Tiled VAE Decode를 구성합니다.

권장 시작점:

  • tile: 256 또는 384
  • overlap: 32

5) SDXL Refiner를 쓸 때 OOM이 나는 패턴과 해결

SDXL Refiner는 사실상 “두 번째 모델을 추가로 돌리는 것”이라, 베이스만 겨우 돌아가던 환경에서 Refiner까지 붙이면 OOM이 나는 게 정상입니다.

해결 우선순위는 아래처럼 잡으면 됩니다.

  1. Refiner 비율(스텝 분배)을 줄이기
  2. Refiner를 아예 끄고, 대신 업스케일+디테일러로 대체
  3. Refiner 실행 구간에서만 오프로딩(아래 섹션) 적극 사용

ComfyUI에서는 베이스/리파이너를 분기한 뒤, 리파이너 쪽만 해상도를 낮추거나(혹은 스텝을 줄이거나) 리파이너를 생략한 워크플로로 빠르게 비교해보세요.

6) 모델/가중치 구성 최적화: ControlNet, IP-Adapter, LoRA의 비용

6-1) ControlNet을 여러 개 붙이면 VRAM이 선형으로 증가

ControlNet은 “조건”이 늘어날수록 추가 피처와 연산이 들어갑니다. 2~3개를 동시에 쓰면 갑자기 OOM이 나는 경우가 많습니다.

  • 정말 필요한 ControlNet만 남기기
  • 해상도 높은 Control 이미지는 다운스케일 후 입력
  • 강도(strength)만이 아니라 “개수”가 메모리에 치명적

6-2) LoRA 다중 적용도 누적 비용이 있다

LoRA 자체는 비교적 가볍지만, 여러 개를 겹치면 레이어별 연산이 늘고 캐시가 증가할 수 있습니다. 특히 SDXL에서 LoRA+IP-Adapter+ControlNet을 한 번에 묶으면 피크가 커집니다.

권장: LoRA를 1~2개로 줄이고, 나머지는 프롬프트/네거티브/샘플러로 튜닝해 먼저 안정화한 뒤 추가합니다.

7) “오프로딩(Offload)”로 VRAM 상한을 강제하기

VRAM이 부족한 GPU(예: 8GB, 10GB)에서 SDXL을 돌릴 때 가장 현실적인 해법이 오프로딩입니다.

  • 모델 일부를 CPU RAM으로 내리고 필요할 때만 GPU로 올림
  • VRAM은 줄지만 속도는 느려짐

ComfyUI는 실행 옵션/노드/백엔드 세팅에 따라 오프로딩 방식이 다릅니다. 일반적으로 다음 키워드로 설정을 찾을 수 있습니다.

  • --lowvram
  • --medvram
  • --cpu
  • --force-fp16

실행 예시(환경에 맞게 하나씩만 적용하며 비교):

python main.py --medvram
python main.py --lowvram

팁: 오프로딩은 “무조건 켜기”보다, Refiner나 VAE 디코드에서만 피크가 터지는지 먼저 확인한 뒤 적용하면 속도 손실을 줄일 수 있습니다.

8) 정밀도(Precision)와 메모리: FP16, BF16, FP8의 현실적인 선택

  • FP16: 가장 흔한 절충안. VRAM 절감 효과 큼
  • BF16: 일부 GPU에서 안정적이지만 VRAM 이점은 FP16과 비슷
  • FP8: 환경이 받쳐주면 VRAM/속도에 이점이 있지만, 세팅 난이도와 호환성 이슈가 있음

ComfyUI/백엔드에서 FP16 경로를 쓰도록 설정하면, 같은 해상도에서도 OOM이 사라지는 경우가 많습니다.

주의: 일부 VAE/노드 조합에서 FP16이 밴딩이나 색 문제를 만들 수 있습니다. 이때는 “UNet은 FP16, VAE는 FP32” 같은 혼합 전략을 고려합니다(가능한 워크플로에서).

9) ComfyUI에서 ‘중간 텐서가 안 내려가는’ 것처럼 보일 때

ComfyUI는 그래프 실행 후에도 미리보기/저장/분기 구조 때문에 텐서가 참조되어 VRAM이 즉시 반환되지 않는 것처럼 보일 수 있습니다.

체크리스트:

  • Preview/Save 노드가 여러 갈래로 붙어 있지 않은지
  • 같은 latent를 여러 분기에서 잡고 있지 않은지
  • 필요 없는 디버그용 노드를 제거했는지

또한 PyTorch는 캐시를 잡고 있어 nvidia-smi 상으로 VRAM이 바로 줄지 않을 수 있습니다. 이건 누수와 다릅니다. 중요한 건 반복 실행 시 VRAM이 계속 증가하는지입니다.

반복 실행마다 증가한다면, 워크플로에서 이미지/latent를 리스트로 축적하거나(배치 저장), 커스텀 노드가 참조를 유지하는 케이스를 의심해야 합니다.

10) OOM을 “재현 가능하게” 줄이는 단계별 처방전

아래 순서대로 적용하면 대부분의 환경에서 원인을 좁힐 수 있습니다.

Step 1. 가장 가벼운 베이스라인 만들기

  • SDXL Base만 사용
  • ControlNet/IP-Adapter/Refiner/업스케일 모두 제거
  • 해상도 832x1216 또는 896x1152, 배치 1

여기서도 OOM이면, 어텐션/정밀도/오프로딩 문제일 확률이 큽니다.

Step 2. 어텐션 최적화 적용

  • xFormers 또는 메모리 효율 SDP 경로 확인
  • 가능하면 FP16

Step 3. VAE 디코드 피크 잡기

  • OOM이 디코드 구간이면 타일 디코드 적용

Step 4. 기능을 하나씩 추가하며 피크 확인

  • ControlNet 1개 추가 → 피크 확인
  • IP-Adapter 추가 → 피크 확인
  • Refiner 추가 → 피크 확인

이 방식은 장애 분석에서 “변경점을 하나씩만 넣고 재현”하는 것과 같습니다. 운영에서 원인 격리를 할 때도 동일한 원칙을 쓰는데, 예를 들어 복합 원인으로 보이는 403을 정책/KMS/엔드포인트로 분해해 점검하는 AWS S3 AccessDenied 403 - 정책·KMS·VPCE 점검 같은 접근이 여기에도 그대로 통합니다.

11) 실전 예시: SDXL 고해상도에서 OOM이 날 때 워크플로 조정

상황: 12GB VRAM에서 1024x1024, ControlNet 2개, Refiner까지 사용하다가 마지막에 OOM.

권장 조정안:

  1. Refiner 제거 후 베이스만 성공시키기
  2. ControlNet을 1개로 줄여 피크 확인
  3. 해상도를 896x1152로 변경
  4. 디코드에서 터지면 VAE 타일 디코드 tile=256, overlap=32
  5. 그래도 부족하면 --medvram 또는 --lowvram

이 조합은 “품질을 크게 잃지 않으면서 피크를 낮추는” 쪽으로 설계되어 있습니다. 특히 해상도를 약간만 조정하고 VAE 타일을 적용하는 것만으로도, 체감 품질 손실 없이 OOM이 사라지는 경우가 많습니다.

12) 자주 묻는 질문(FAQ)

Q1. 스텝을 줄이면 VRAM이 줄어드나요?

스텝은 주로 시간에 영향을 주고, VRAM 피크에는 영향이 제한적입니다. 다만 일부 워크플로에서 중간 결과를 저장하거나(프리뷰) 샘플러 구현 차이로 피크가 달라질 수는 있습니다. VRAM은 해상도/배치/어텐션/VAE/부가모델이 핵심입니다.

Q2. “VRAM이 남아 있는데도” OOM이 나는 이유는?

PyTorch의 메모리 할당은 단순히 “남은 VRAM”이 아니라 **연속된 큰 블록 할당 실패(단편화)**로 OOM이 날 수 있습니다. 워크플로를 단순화하고 피크를 낮추면 해결되는 경우가 많습니다.

Q3. ComfyUI가 A1111보다 더 잘 터지는 느낌인데요?

노드 그래프 특성상 중간 텐서가 더 오래 살아남거나, 분기/프리뷰/저장이 VRAM 피크를 키울 수 있습니다. 워크플로를 최소화한 베이스라인을 만든 뒤, 노드를 하나씩 추가하며 피크를 확인하는 방식이 가장 빠릅니다.

마무리: “해상도·어텐션·VAE 피크”만 잡아도 절반은 끝

SDXL+ComfyUI OOM은 대부분 아래 3개 축에서 정리됩니다.

  • 해상도(면적)와 배치
  • 메모리 효율 어텐션(xFormers/SDP)과 정밀도(FP16)
  • VAE 디코드 피크(타일 디코드)

여기에 ControlNet/IP-Adapter/Refiner를 “한 번에” 붙이지 말고, 베이스라인에서 하나씩 추가해 피크를 확인하면 재현 가능한 방식으로 안정화할 수 있습니다. 다음 단계로는, 본인 GPU VRAM(8/12/16/24GB)에 맞춘 권장 프리셋을 만들어 워크플로 템플릿으로 고정해두면 매번 OOM을 다시 겪지 않게 됩니다.