본문 바로가기
C.W.K.
Stream
Lesson 01 of 04 · published

Monolith 이 천장에 부딪히다

~13 min · monolith, transformer-models, architecture, a1111

Level 0툴 빌려 쓰는 사람
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"자기 모양을 코드에 박아 넣은 파이프라인은 이미 아는 모양만 만들어 낼 수 있어."

안 될 때까지는 잘 되던 툴

몇 년 동안, 자기 머신에서 open-weight 이미지 모델을 돌리는 제일 편한 방법은 monolithic 웹 UI 였어. 그중 제일 많이 쓰이는 건 생성 전체를 처리 함수 하나에 다 엮어 놨고. 모델 고르고 프롬프트 치고 generate 누르면 긴 파이프라인이 처음부터 끝까지 한 번에 돌아. 진짜 잘 만든 소프트웨어야. 그리고 transformer 시대가 그대로 걸어 들어간 구조적 천장이 하나 있어.

'monolithic 파이프라인' 이 실제로 뜻하는 것

옛날 파이프라인은 함수 하나에 전제 세 개를 구워 넣었어. backbone 은 U-Net, text encoder 는 CLIP, sampler 는 정해진 몇 개(Euler, DPM++, DDIM) 중 하나. SD1.5 랑 SDXL 시대에는 이 전제가 모든 모델한테 참이었어. 그러니까 박아 넣는 게 공짜로 속도를 벌어 줬지. 모양이 하나뿐이니까 파이프라인이 그 모양을 알고 있어도 됐던 거야.

박아 넣은 전제는 틀리기 전까지는 공짜야. 들어오는 게 다 같은 모양이면 그 모양을 전제하는 건 순수한 이득이야. 계산서는 그 전제를 어기는 입력이 처음 들어오는 날 날아와. 그리고 그날 오는 계산서는 작지 않고.

transformer 시대가 전제를 다 어겼어

그러다 transformer 기반 이미지 모델이 왔어. SD3, FLUX, PixArt, Hunyuan-DiT, AuraFlow. 그리고 전제 셋을 한꺼번에 깼지.

  • backbone 이 더 이상 U-Net 이 아니야. DiTMMDiT, 그러니까 diffusion transformer 야.
  • text encoder 도 CLIP 하나가 아니야. FLUX 는 CLIP 에 T5-XXL encoder 를 붙여. conditioning 모양 자체가 달라져.
  • sampler 도 옛날 것들이 아니고. flow-matching 모델은 flow-match scheduler 를 원해.

U-Net 이랑 CLIP 이랑 Euler 를 박아 놓은 파이프라인에는 이 셋 중 뭘 넣을 자리도 없어. fork 떠서 모델 하나쯤 패치할 수는 있어. 그런데 다음 계열이 나오면 그 패치가 또 깨져. monolith 는 변종은 받아들여도 새로운 종류는 못 받아들여.

monolith 는 자기 전제 안에서만 휘어. 전제 밖으로는 안 휘고. 새 요구사항이 박아 넣은 전제를 어기는 순간, 치러야 하는 건 기능 추가가 아니라 재작성이야. 그게 천장이야.

fork 로는 안 되는 이유

커뮤니티 fork 들이 transformer 모델을 monolithic UI 에 패치해 넣기는 해. 돌아가기도 하고. 단, 누군가 패치해 준 그 모델에 한해서야. 그리고 그 패치 하나하나는 여전히 옛날 모양을 전제한 파이프라인에 볼트로 조여 붙인 예외 처리야. 아키텍처가 패치랑 싸우는 거지. 모델 계열 다섯 개쯤 지나면 예외 처리 다섯 개랑 아무도 통째로는 이해 못 하는 파이프라인이 남아. 증상만 패치하는 건 천장을 안 올려 줘. 비계로 가려 놓을 뿐이야.

교훈은 이미지 모델보다 커

이게 forcing function 의 일반적인 모양이야. 툴이 자기 세계 전체에 참이던 전제를 코드에 새겨 넣는다. 그러다 세계가 바뀐다. 그 전제가 천장이 된다. 이때 정직한 대응은 더 세게 패치하는 게 아니야. 아예 박아 넣은 모양이 없는 아키텍처는 어떤 모양일지 물어보는 거지. 다음 트랙이 바로 그 얘기야.

난 "패치할 수 있음" 이 "괜찮음" 이랑 같은 말인 줄 알았어. 아빠는 계속 그 패치들 자체를 가리켰어. 하나하나가 아키텍처가 새로운 걸 반기지 않는다는 증거였거든. 뭘 붙이려고 할 때마다 싸워야 하는 파이프라인은 너한테 뭔가를 말하고 있는 거야. 난 그 싸움을 그냥 귀찮은 일이 아니라 신호로 읽는 법을 배웠어.

Code

전제 셋이 한꺼번에 무너지는 자리·python
# monolithic 모양 (예시용): 함수 하나에 전제 셋.
def generate(prompt, model, sampler_name, steps, cfg):
    unet  = model.unet           # 전제 1: backbone 은 늘 U-Net
    clip  = model.cond_stage     # 전제 2: text encoder 는 늘 CLIP
    cond  = clip.encode(prompt)
    sampler = SAMPLERS[sampler_name]  # 전제 3: sampler 는 정해진 것들 중 하나
    latents = sampler.sample(unet, cond, steps, cfg)
    return model.vae.decode(latents)

# 여기에 FLUX 모델이 들어오면:
#   backbone 이 U-Net 이 아니라 DiT   -> model.unet 은 없는 attribute
#   text encoder 가 CLIP + T5-XXL     -> clip.encode() 로는 T5 conditioning 을 못 실어
#   flow-match scheduler 를 원함       -> SAMPLERS[name] 에 해당 항목이 없음
# 전제가 한꺼번에 다 무너져. 패치를 끼워 넣을 깨끗한 자리가 없어.

External links

Exercise

네 코드에서 어떤 입력의 '모든 경우' 를 다 처리하는 파이프라인이나 함수를 찾아봐. 그게 입력 모양에 대해 하는 전제를 전부 적어. 이제 각각을 어기는 새 입력을 하나씩 상상해 봐. 어떤 전제가 작은 수정이 아니라 재작성을 부르는지 보이지? 그게 네 천장이야.
Hint
if type == ... 로 이어지는 체인, model.unet 처럼 박아 넣은 attribute 접근, 고정된 lookup 테이블 같은 걸 찾아봐. 하나하나가 다 모양에 대한 전제야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.