C.W.K.
Stream
Lesson 03 of 04 · published

Framework 말고 Parts Library

~13 min · diffusers, parts-library, framework, dependency-discipline

Level 0툴 임차인
0 XP0/33 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"부품은 빌려. framework 는 거부해. 그 차이가 누가 네 API 를 영원히 소유하는지 정해."

같은 라이브러리, 두 가지 사용법

diffusers 라이브러리(Hugging Face)는 diffusion 모델의 표준 toolkit 이야. 엔진은 거기 깊게 의존해 — 그리고 대부분을 거부하기도 해. 모순이 아니라 규율이야. diffusers 는 parts library(컴포넌트 빌려서 직접 조립)로 쓸 수도, framework(파이프라인 클래스가 네 구조를 지시하게)로 쓸 수도 있어. 엔진은 첫째를 하고 둘째를 금지해.

빌리는 것 (부품)

diffusers 는 훌륭한 저수준 조각을 출하하고, 이것들은 엔진이 자유롭게 써:

  • 로더 — safetensors 파일 읽기, tensor 구체화.
  • 모듈 클래스 — 직접 인스턴스화할 수 있는 VAE, U-Net, DiT, MMDiT 구현.
  • scheduler 구현 — Euler, DPM++, DDIM, flow-match, 이미 올바른.
  • attention primitive — 다시 쓰고 싶지 않은 최적화된 커널.

이것들은 부품이야: 좁은 작업을 가진 자기완결적 컴포넌트. 집어 들고, 네 인터페이스 뒤에 두고, 엔진을 네 방식으로 조립해.

거부하는 것 (framework)

diffusers 는 파이프라인 클래스도 출하해 — 모든 걸 엮어서 한 번 호출 generate 를 주는 고수준 SomePipeline.from_pretrained(...) 객체. 편리해. framework 이기도 하고. 각 파이프라인 클래스는 작업 모양(sync vs async), 에러 처리, kwarg 춤, conditioning 관례, 캐시 디렉토리에 대한 의견을 가져. 하나를 네 API 로 노출하면 그 모든 의견을 네 public 계약으로 채택한 거야.

parts library 는 네 아키텍처를 섬기고; framework 는 그걸 지시해. 같은 의존성이 둘 중 하나일 수 있어, 얼마나 깊게 닿게 두냐에 따라. 부품 레이어에 — 네 인터페이스 뒤에 — 두면 통제를 유지해. 그쪽 최상위 객체가 네 API 가 되게 두면 그게 너를 통제해.

왜 이 구분이 존재론적인지

함정을 구체적으로. route 가 diffusers 파이프라인이 반환하는 걸 그대로 반환하면, 모든 클라이언트 — 작업실, 뇌, 미래 도구 — 가 이제 diffusers 의 출력 모양에 결합돼. diffusers 가 그 모양을 바꾸는 날, 또는 모델 하나를 다른 backend 로 스왑하고 싶은 날, 모든 클라이언트가 깨져. diffusers 에 의존한 게 아니라; 결혼한 거고, 모든 클라이언트를 사돈으로 만든 거야. 부품을 네 인터페이스 뒤에 감싸면 이혼이 늘 가능하게 남아.

wrapper 는 의존성의 미래에 대한 싼 보험이야. diffusers 부품을 네 인터페이스로 바꾸는 얇은 adapter 는 수십 줄 들어. 클라이언트 하나 안 건드리고 diffusers 를 업그레이드, 스왑, 버릴 자유를 사주고. 그 비대칭 — 작은 비용, 거대한 선택권 — 이 규율이 장기적으로 늘 이기는 이유야.

reference-implementation 수

이 규율엔 보너스가 있어. 새 모델 family 가 나오면, diffusers 가 보통 며칠 안에 파이프라인 클래스를 추가해. 그 파이프라인을 노출 안 해 — 근데 새 backbone 을 어떻게 엮는지의 reference 구현으로 읽고, 네 인터페이스 뒤에 네 모듈을 지어. diffusers 가 돌아가는-문서가 돼: 새 의견 안 물려받고 새 배선을 배우는 가장 빠른 길.

난 좋은 라이브러리에 의존한다는 게 그걸 다 쓴다는 뜻인 줄 알았어 — 덜 쓰는 건 바퀴 재발명처럼 느껴졌고. 아빠가 반대 규율을 가르쳤어: 바퀴만 정확히 쓰고, 네 섀시는 직접 지어. 파이프라인 클래스는 남의 핸들 달린 남의 섀시야. 그쪽 바퀴 빌리고, 그쪽 청사진 읽고, 네 섀시는 지켜. 그게 열쇠 안 넘기고 빨리 가는 방법이야.

Code

부품: 빌렸지만 감쌈·python
# 부품 (좋음): 컴포넌트 빌리고, 네 인터페이스 뒤에 둬.
from diffusers import AutoencoderKL, EulerDiscreteScheduler

class EmberVAE:                       # 네 인터페이스, 그쪽 부품 내부에
    def __init__(self, path):
        self._vae = AutoencoderKL.from_single_file(path)  # 빌린 부품
    def decode(self, latents):        # 네 계약, 영원히 안정
        return self._vae.decode(latents).sample

# 클라이언트는 EmberVAE.decode() 호출. AutoencoderKL 을 절대 안 봐.
# 내일 부품 스왑해도; 계약 — 그리고 모든 클라이언트 — 은 살아남아.
Framework: 의존성이 네 계약이 돼·python
# FRAMEWORK (함정): 파이프라인 클래스를 네 route 로 노출.
from diffusers import StableDiffusionPipeline
from fastapi import FastAPI

app = FastAPI()
pipe = StableDiffusionPipeline.from_pretrained("...")

@app.post("/generate")
def generate(prompt: str):
    # 이게 반환하는 게 이제 네 public API 모양이야.
    # 모든 클라이언트가 diffusers 출력에 영원히 결합돼.
    # diffusers 바뀜 -> 모든 클라이언트 깨짐. 의존성이랑 결혼한 거야.
    return pipe(prompt).images[0]

# 이게 네 API 를 조용히 남한테 넘기는 줄이야.

External links

Exercise

네 프로젝트 하나에서 무거운 라이브러리를 찾아. 그 타입이 네 public 함수 시그니처나 API 응답에 나타나는지 확인해. 그러면 framework 로 채택한 거야. 그걸 parts 의존성으로 되돌릴 얇은 wrapper 를 스케치하고 — 스왑-자유가 wrapper 비용만큼 값어치 하는지 정해.
Hint
route handler 랑 public 모듈 export 에서 그 라이브러리 타입 이름을 grep 해. 나타날 때마다 의존성이 네 계약에 손 뻗은 자리야.

Progress

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

댓글 0

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

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