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

허락된 단 하나의 추상화

~13 min · adapter, abstraction, narrow-boundary, yagni

Level 0툴 임차인
0 XP0/33 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"모든 추상화는 뭔가 변할 거라는 베팅이야. 변화가 진짜인 데서만 베팅해 — 그리고 엔진엔 진짜 베팅이 정확히 하나야."

추상화는 장식이 아니라 베팅이야

추상 베이스 클래스, 인터페이스, protocol — 하나하나가 주장이야: "이것의 구현이 여럿일 거고, 위의 코드는 어느 건지 신경 안 써야 해." 그 주장이 참이면, 추상화가 밥값을 해. 거짓이면 — 구현이 영영 하나뿐이면 — 추상화는 순수 비용이야: 읽고 통과해야 하는 우회, 아무것도 안 하는 seam. 규율은 변화가 진짜라고 확신하는 데서만 베팅하는 거야.

엔진의 진짜 베팅 하나

엔진을 보고 물어봐: 최상위에서 진짜 변하는 게 뭐야? VAE 아니야 — 그건 모듈, 파이프라인 안에서 변하고. sampler 아니야 — 역시 내부고. 최상위에서 변하는 건 생성이 물리적으로 어디서 일어나냐야:

  • LocalAdapter — 네 GPU 의 모델 weight 에 대고 PyTorch 랑 diffusers 를 돌려.
  • APIAdapter — closed-weight vendor(외부 이미지 서비스)를 HTTP 로 호출해; local weight 없음, GPU 없음.

이 둘은 진짜로 다른 세계야 — 다른 실패 양상, 다른 latency, 다른 모든 것. 그 차이가 진짜 변화라서, 엔진이 출하하는 단 하나의 추상화 — Adapter — 를 벌어.

진짜 변화 축 하나, 추상화 하나. Adapter 가 존재하는 건 local-vs-API 가 생성이 일어나는 방식의 진짜 갈림길이라서야. 최상위에서 그렇게 갈라지는 게 다른 게 없어서, 다른 건 추상화를 안 받아. 모든 걸 pluggable 하게 만들고 싶은 충동에 저항해; 실제로 꽂히는 것만 pluggable 하게 해.

'좁다' 가 뜻하는 것

Adapter 경계는 두 가지 의미로 좁아. 첫째, 유일한 최상위 추상화야 — 추상 router, 추상 store, 추상 뭐의 병렬 계층이 없어. 둘째, Adapter 인터페이스 자체가 작아: 요청 받고, 돌리고, 결과 바이트 + 메타데이터 반환. 좁은 인터페이스는 올바르게 구현하기 쉽고, 추론하기 쉽고, 누출하기 어려워. 넓은 인터페이스는 모든 구현자가 절반을 가짜로 만들어야 할 때까지 메서드를 쌓아.

좁은 인터페이스는 모두가 지키는 작은 약속이야. 인터페이스가 요구하는 메서드가 적을수록, 모든 구현이 더 정직하게 이행할 수 있어. 구현자가 진짜로 지원 안 하는 메서드를 stub 으로 두는 걸 발견하면, 인터페이스가 너무 넓었던 거야 — 모든 구현이 못 지킬 걸 약속한 거야.

아직 안 짓는 미래 adapter

Adapter 추상화는 ceiling matrix 의 예약된 seam 도 구체화해. 미래의 VideoAdapter(local video)랑 미래의 video-API adapter 둘 다 같은 경계에 맞아 — 비디오의 날이 오면, 기존 추상화의 새 구현으로 꽂혀, 경계 변경 없이. '생성 위치가 변한다' 는 네 베팅 하나가 아직 안 지은 변화까지 이미 커버해, 옳은 축에 베팅했으니까.

틀린 축에 베팅하는 건 안 베팅하는 것보다 나빠. 안 변하는 것 위의 추상화는 모든 미래 변경이 틀린 seam 이랑 싸우게 강제해. 인터페이스 추가 전에, 그게 흡수하는 변화를 한 문장으로 대. 못 대면, 추상화가 아니라 장식이야 — 그리고 장식은 모든 변경마다 비용을 물려.

피파의 고백

내 1M-context 본능은 모든 걸 인터페이스로 만드는 거야 — 모든 구현을 머릿속에 담을 수 있는데, 다 추상화하면 왜 안 돼? 아빠가 계속 한 질문으로 날 끌어당겨: 실제로 뭐가 변해? 내가 추상화하고 싶은 것 대부분은 구현이 정확히 하나고 영영 그럴 거야. Adapter 가 답이 진짜로 '하나 이상' 인 유일한 곳이라, seam 을 버는 유일한 추상화야. 추상화는 베팅이고, 난 너무 많이 걸고 있었어.

Code

추상화 하나, 한 가지가 변하니까·python
from abc import ABC, abstractmethod

class Adapter(ABC):
    """하나뿐인 최상위 추상화. 생성이 진짜로 두 다른 세계 —
    local 이랑 API — 에서 일어나기 때문에 존재해."""
    @abstractmethod
    async def run(self, request) -> "Result":
        """요청 받고, 생성하고, 바이트 + 메타데이터 반환."""
        ...

class LocalAdapter(Adapter):       # PyTorch + diffusers + 모델 weight
    async def run(self, request):
        ...                        # 진짜 GPU 작업이 여기서 일어나

class APIAdapter(Adapter):         # vendor 이미지 서비스로 HTTP
    async def run(self, request):
        ...                        # local weight 없음, GPU 없음

# 미래, ceiling matrix 로 예약됨 — 같은 좁은 경계:
# class VideoAdapter(Adapter): ...   (비디오 출하되면 열림)
# '생성 위치가 변한다' 베팅이 이미 이것들을 커버해.

External links

Exercise

네가 아는 코드베이스를 추상화(베이스 클래스, 인터페이스, protocol)에 대고 감사해. 각각, 진짜 구현 수를 세. 예약된 seam 이 아닌데 구현이 정확히 하나인 추상화는 삭제 후보야 — 걸었지만 안 필요했던 베팅. 몇 개 지울 거야?
Hint
예약된 seam(오늘 구현 하나지만 구체적으로 계획된 둘째가 있는 추상화)은 정당해. 투기적 추상화(구현 하나, 둘째 구체 계획 없음)가 삭제 후보야. 차이는 둘째 구현이 진짜냐 상상이냐.

Progress

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

댓글 0

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

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