~12 min · ceiling-matrix, interface-design, yagni, roadmap
Level 0툴 빌려 쓰는 사람
0 XP0/40 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"seam 은 지금 그려. 구현은 나중에 그 사이로 통과시키고. 인터페이스로 자리를 잡아 두는 게, 미리 다 짓지 않고도 열어 두는 방법이야."
언젠가 필요해질 것들의 지도
엔진을 직접 갖기로 하면 위험한 질문이 따라와. 얼마나 짓지? 상상되는 걸 다 지으면 출시도 못 해 보고 가라앉아. 오늘 필요한 것만 지으면 스스로를 가두고. ceiling matrix 는 그 질문에 답하는 도구야. 엔진한테 언젠가 필요할 수 있는 능력을 격자에 다 늘어놓고, 하나하나에 세 상태 중 하나를 붙이는 거지.
축은 둘
matrix 에는 축이 두 개 있어. 하나는 modality, 이미지냐 비디오냐. 다른 하나는 weight 가 어디 있냐, 네가 직접 돌리는 local open weight 냐 네트워크로 부르는 closed-weight API 냐. 그러면 칸이 넷 나와. local 이미지, local 비디오, API 이미지, API 비디오. 각 칸이 상태를 하나씩 받아.
세 상태는 이거야. 구현됨, 인터페이스로 잡아 둠, 범위 밖. 구현됨은 지금 돌아가는 거. 잡아 둠은 스키마에 seam 은 있는데 구현은 없는 거. 범위 밖은 이유를 적어 놓고 일부러 뺀 거. 모든 능력이 정확히 하나만 받아. 반쯤 만들다 만 기능으로 조용히 썩어 가는 '나중에 아마' 칸은 없어.
'인터페이스로 잡아 둠' 이 핵심 수야
제일 중요한 건 가운데 상태야. 이 matrix 를 그릴 때 local 이미지 생성은 구현돼 있었고 local 비디오는 아니었어. 그런데 요청 스키마에는 이미 video 라고 적을 수 있는 modality 자리가 있었어. seam 이 있었던 거지. 비디오 작업 흐름이 마침내 구현을 요구했을 때, 이미 쓰고 있던 호출자를 하나도 안 깨고 그 seam 사이로 지어 넣었어(날짜는 아래 v4 메모에 있어). 문은 일찍 그려 두고, 통과는 나중에 하는 거야.
seam 은 잡아 두고 구현은 미뤄. 첫날 스키마에 modality: image | video 를 넣는 건 거의 공짜인데 백째 날의 API 파손을 막아 줘. 첫날 비디오 파이프라인을 짓는 건 엄청 비싸고, 정작 필요해질 때쯤엔 틀린 설계일 수도 있고. 자리는 싸게 잡고, 짓기는 늦게 해.
이게 그냥 YAGNI 는 아닌 이유
"어차피 안 쓸 거야(YAGNI)" 는 투기적인 기능을 짓지 말라고 말해. 맞는 말이야. 그런데 곧이곧대로만 적용하면 그 기능들이 들어갈 자리도 남기지 말라는 말이 돼. 그러면 정말로 필요해지는 날 모든 클라이언트로 번지는 파손으로 값을 치르게 되지. ceiling matrix 는 그 사이를 지나가. 투기적인 기능은 안 짓고(YAGNI 는 지키고), 그 인터페이스 seam 만 잡아 둬(그래서 나중에 짓는 게 파손이 아니라 추가가 되고). 싼 seam 에 미뤄 둔 구현.
범위 밖에는 이유가 붙어야 해
세 번째 상태도 똑같이 엄격해. 어떤 능력은 일부러 빠져. 그리고 matrix 는 뺐다가 아니라 왜 뺐는지를 적어. training 도구는 엔진이 inference 전용이라서 범위 밖이야. face-swap 기능은 그것대로의 이유로 범위 밖이고. 이유를 적어 두면 나중의 너나 다른 기여자가 그 결정을 맨바닥부터 다시 다투지 않아. '범위 밖' 을 '까먹은 것' 으로 오해하지도 않고.
내 버릇은 둘 중 하나였어. 지금 다 짓거나(머릿속에 전체가 들어오니까), 아니면 전부 '나중' 으로 미루거나(빨리 내놔야 할 것 같아서). matrix 가 내가 계속 놓치던 세 번째 수를 가르쳐 줬어. 인터페이스는 잡아 두고, 구현은 건너뛰고, 이유는 적어 두기. 로드맵이랑 소원 목록의 차이가 이거야. 로드맵에는 seam 이 있고, 소원 목록에는 바람만 있어.
Code
모든 능력이 정확히 한 상태만 받아·text
| local (weight 직접 돌림) | API (서비스 호출)
--------------+---------------------------+--------------------------
이미지 | 구현됨 | 인터페이스로 잡아 둠
| (엔진의 코어) | (adapter 자리 준비됨)
--------------+---------------------------+--------------------------
비디오 | 인터페이스로 잡아 둠 | 인터페이스로 잡아 둠
| (modality 자리가 있음) | (위 둘이 나가면 열림)
범위 밖 (그냥 빼는 게 아니라 이유까지):
- training / fine-tuning -> 엔진은 inference 전용
- face swap -> 그것대로의 이유로 제외
(face *restore* 는 후처리로 범위 안에 남음)
싼 seam 하나가 비싼 파손을 막아·python
# seam 은 첫날부터 있고, 구현만 미뤄 뒀어.
from typing import Literal
from pydantic import BaseModel
class GenerateRequest(BaseModel):
prompt: str
model: str
# 잡아 둔 seam: 비디오 파이프라인이 아직 없어도
# 'video' 는 스키마가 받아 주는 정식 값이야. 나중에 비디오를 붙이는 게
# 추가가 되지 파손이 안 돼. 기존 이미지 호출자는 그대로 굴러가.
modality: Literal["image", "video"] = "image"
steps: int = 30
# 1일차: modality 는 늘 "image". seam 을 갖는 값은 0.
# 100일차: VideoAdapter 가 modality="video" 뒤에 붙어. API 는 안 깨짐.
로드맵이 있는 프로젝트를 골라 ceiling matrix 를 만들어 봐. 능력을 6개에서 10개쯤 늘어놓고 각각에 붙여. 구현됨, 인터페이스로 잡아 둠, 아니면 범위 밖(이유까지). '잡아 둠' 마다 그걸 잡아 주는 스키마 필드나 seam 을 적고, '범위 밖' 마다 이유를 한 문장으로 적어.
Hint
세 칸 어디에도 안 들어가는 능력이 있으면 아직 그것에 대해 결정을 안 한 거야. 그리고 결정 안 한 능력이 반쯤 만들다 만 군더더기로 썩는 바로 그거고.
Progress
Progress is local-only — sign in to sync across devices.