두 번째 추출
첫 추출은 규칙을 증명하고, 두 번째 추출은 시스템을 증명해. workshop 둘이 중립 queue kernel 를 벌어들인 뒤에도 더 어려운 질문이 남아 있었어. kernel 을 실제 제품 하나로 만들어 주는 접착 코드, 그러니까 engine 몸통이나 CLI 동사, attachment 저장소 같은 것들이 어디로 가야 하는가 하는 문제야. 얼핏 제품 색깔이 진해서 첫 추출에서는 빠져나갔거든.
답은 편집이 아니라 census 로 왔어. 뭔가 옮기기 전에 프로그램은 먼저 셌어. attachment 저장소는 두 workshop 사이에서 바이트까지 똑같았어. engine 과 CLI 도 각자 앱 이름만 지우면 같았는데, 아무도 정당화 못 하는 drift 딱 세 개가 남아 있었지. slug 를 어느 층이 만들어 내는지, one-open 경합을 어느 쪽이 막는지, 착지가 어느 repo 를 수렴시키는지. 추출은 그 seam 을 가져가면서 drift 들을 그 자리에서 조정했어. 같은 텍스트는 단서일 뿐이고, 조정된 차이가 craft 야. 웹 UI 를 engine 포트에서 서빙하는 정책 하나는 스물여섯 개 engine 에서 세 가지 모양으로 손수 짜여 있었는데 — census 는 second-use 창을 진작 놓쳤다는 사실을 발견하는 방법이기도 해. 사본이 스물여섯 개면 두 번째 사본은 아주 옛날에 지나갔거든. 브라우저 origin 규칙 하나는 똑같은 복사본 열 개에, 두 검사 순서가 조용히 뒤집힌 사본 하나가 숨어 있었지. “이거 반복되는 것 같은데”가 여기서 측정값이 돼. 사본 몇 개, 모양 몇 가지, 어느 하나가 drift 했는지까지.
운반 수단은 workshop 자기 사다리였어. promotion 트랙이 가르치는 그 명시적 경로로 만들어진 named pipeline 하나가 추출 자체를 domain 으로 삼았지. plumbing 모양 하나를 공유 kit 으로 옮기고 사본 전부를 수렴시키는 일. 그 파이프라인으로 하루 오후에 일곱 건의 승격이 뛰었고, 전부 같은 기록 시스템의 평범한 row 로 큐잉·게이트·착지됐어. doctrine 은 자기 workshop 을 만나서도 살아남은 게 아니라, 자기 반복을 위한 도구까지 만들어낸 거야.
추출 뒤에 경계가 어디 사는지 봐. 각 consumer 는 “여기 편집하지 마”라고 찍힌 생성 사본을 vendor 하고, 손편집이 들어오면 drift test 가 test suite 를 떨궈. 수정은 upstream 에서 한 번만 일어나고 resync 로 퍼져. 주석 몇 줄짜리 경고는 마감 앞에서 지는데 빨간 테스트는 안 지거든. 구조로 지키는 경계가 문장으로 지키는 경계보다 오래 살아.
프로젝트가 아니라 상시 관행이야
몇 주 뒤 kit-ification 을 묶던 우산 태스크는 닫혔어. 추출이 끝나서가 아니라 영원히 안 끝나서야. sibling 들이 자라면서 새 seam 이 계속 나타나고, 각각은 같은 루프로 들어와. census, 승격, resync. 그 뒤 git 로그를 채우는 resync 커밋들은 노이즈가 아니야. seam 이 upstream 변경을 한 번에 하나씩 받아들이는 모습이고, 건강한 수렴이란 바로 그 모양이야. 그 스트림을 읽는 법을 익혀둬. 새 동작을 싣는 커밋이 시그널이고, 사본을 수렴시키는 커밋은 관리야. 둘을 헷갈리면 살아있는 시스템이 시끄러워 보여.