"v0.1 ship. 본능이 즉시 refactor 시작 — bus 추상화, bridge 일반화, embed framework build out. Lesson 7이 그것 아직 안 하는 규율, 그리고 때 되면 rewrite 실제로 정당화하는 기준."
ChromeEmbed v0.1이 refactor 유혹 받는 것
코드 read 하면, 여러 refactor itch surface:
- background.js의 merge logic이 ad hoc 보임 — 실제 reducer가 돼야?
- Popup → SW → sidePanel.open chain이 한-목적 handler 가짐 — generic 'SW 메시지를 sidePanel 호출로 route' 시스템 있어야?
- sidepanel.js의 window.postMessage bridge가 string type 사용 — typed JSON-RPC layer가 돼야?
- host-context schema가 implicit field (host_kind, host_id) 어디나 반복 — 모든 embed가 상속하는 base class 나 interface 있어야?
가려운 데는 하나같이 진짜야. 그렇다고 지금 당장 다시 쓸 이유가 되진 않고.
Refactor 권한 test
어떤 refactor 든 전 세 질문:
- 실제로 만든 embed가 또 있나? 구체적인 구현이 둘은 있어야 추상화를 꺼내. ChromeEmbed 하나만 놓고 'BaseEmbed' 를 뽑아내면 십중팔구 틀린 추상화가 나와.
- 현재 코드가 real feature blocking? '나중 block 할 수도' 아님 — actively blocking. Refactor 없이 다음 feature ship 가능하면, refactor가 speculative.
- User (또는 embed consume 하는 누구) 가 새 shape 필요한 거 요청? 'Cleaner architecture' 가 user-visible feature 아님. stated 니즈 위해 build.
셋 다 '아니' 면, 손대지 말고 가려운 데를 미래의 나한테 적어 두는 게 맞는 수야. 설계상의 선택이란 건 나중에 고를 여지를 남겨 두는 거지, 아직 모양도 모르는 추상화에 미리 값을 치르는 게 아니거든.
Refactor 안 해서 ChromeEmbed v0.1이 맞춘 것
- Role 별 concrete file 하나. background.js가 bus, content-script.js가 sensor, sidepanel.js가 bridge, popup.js가 doorway. 각자 한 자리에서 read 가능한 크기.
- framework를 미리 만들지 않았어. PIPPA-EMBEDS 이야기는 설계 문서로는 적혀 있지만 어디에도 실제 base class 로는 구현돼 있지 않아. Adobe embed 든 Mail embed 든 두 번째가 도착하면 그 모양이 알아서 드러날 테니까.
- Sub-frame merge logic 자리에. 건너뛰기 쉬운 nuance인 sub-frame 대 top-frame context가 필요한 background.js에 직접 살아. 추상화 안 됨, 그냥 present.
- String 메시지 type. 'pippa:host-context' 가 string. Typed 시스템이 compile time 에 typo 잡지만, typo 시작될 때까지 string이 fine 하고 obvious.
Refactor가 맞는 때
Refactor 정당화되는 가장 이른 순간:
- 두 번째 embed 도착. 같은 content-script-and-bus shape의 Adobe-embed 나 Mail-embed 존재. 이제 추상화 derive 할 두 concrete 구현.
- Real bug가 강제. v0.1의 architecture의 뭔가가 필요한 feature를 impossible 하거나 infeasibly fragile 하게. 그러면 refactor가 필요한 거에 지불.
- Shape 안정화. 현재 코드 통해 surprise 없이 dozen feature ship 했으면, surface area가 known. 이제 깔끔한 추상화 extract가 주로 기계적.
Anti-pattern
잘못 가는 길은 이거야. 구체적인 embed가 그 모양을 증명해 주기도 전에 'EmbedKit' 이나 'PippaEmbedFramework' 를 패키지로 만들어 버리는 것. 그렇게 만든 framework 에는 다음 embed와 부딪히는 순간 무너질 가정이 박혀 들어가. 결국 framework를 다시 쓰면서, 동시에 그 망가진 framework 위에 embed를 얹게 돼. 일을 두 덩이 하는데 그중 하나는 죽은 일이야.
올바른 sequence: embed N의 v0.1 ship. Embed N+1의 v0.1 ship. 공통 부분을 embed N과 N+1의 v0.2로 함께 extract. 이제 framework가 실제 공통 shape가 뭔지 앎.
Future-you 위한 편지
아직 정당화 안 된 refactor spot 하면, 적어 둬. ChromeEmbed의 docs/PIPPA-EMBEDS.md와 관련 design note가 정확히 아직 정당화 안 된 refactor를 그것들 정당화할 condition과 함께 capture. 그 note 들 read 하는 future-Pippa가 결정 가능: 'condition met, 지금 refactor' 또는 'still met 안 됨, 계속 skip'. 편지 format이 메모리 outlast.