본문 바로가기
C.W.K.
Stream
Lesson 03 of 05 · published

두 자식이 어긋날 때: SiblingKit 이야기

~11 min · sibling-kit, drift-check, vendored-copies, shared-ownership

Level 0식은 화로
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"공유 배관은 kit 에서 편집하고 동기화를 돌려. vendored 사본을 제자리에서 절대 건드리지 마. 그러면 drift check 가 빌드를 실패시켜."

같은 날, 세 사본

이 트랙에 가장 날카로운 레슨을 준 war story 가 여기 있어. Vesta 와 형제 Forge 가 둘 다 같은 날, 나란히 일하는 두 다른 Pippa 인스턴스한테서 Waystone 에서 씨앗 뿌려졌어. 각자 같은 공유 배관을 충실히 이어갔지. cwkPippa client 레이어, publish client, veil, ULID 발급, settings slice, outbox 와 ask-thread 팩토리, 몇 개의 공유 UI atom. 그 순간, 공유 레이어가 세 벌로 존재했어. Waystone 것, Vesta 것, Forge 것. 첫날부터 이미 어긋나면서. 두 인스턴스가 각자 살짝 다르게 맞췄으니까. 겉치레 어긋남보다 나빴어. 그 갈림 속에 진짜 크로스앱 버그가 숨어 있었거든. Settings 에서 한 브레인을 고르면 Ask Pippa 가 깨지는 brain-namespace 불일치가, 한 사본엔 있고 다른 것엔 없이.

그게 가족이 자랄 때 복사로 나누기가 어떤 모습인지야. 부모에서 씨앗 뿌려진 모든 형제가 공유 레이어를 복제하고, 모든 복제가 자기 스케줄로 어긋나. 오늘 세 사본, 다음 달 다섯, 각자 살짝 다르고, 각자 같은 버그가 따로 살거나 고쳐질 수 있는 곳. 놔두면 공유 배관이 가족 전체에서 가장 안 맞는 부분이 돼. '공유' 가 뜻해야 할 것의 정반대지.

주인이 여럿인 공유 코드는 설계가 아니라 우연으로 공유돼. 두 앱이 같은 레이어의 자기 사본을 쥐는 순간, '공유' 는 네가 하는 이야기지 시스템이 강제하는 사실이 아냐. 진짜 공유엔 주인이 딱 하나, 그리고 모든 소비자를 거기로 모으는 장치가 필요해. 그게 없으면 복제 더하기 따로 진화가 어긋남을 보장해. 그리고 공유 레이어의 어긋남이 크로스앱 버그가 번식하는 곳이야.

한 주인, vendored 사본, drift check

고침은 cwkSiblingKit 이었어. Waystone 형태 가족이 나누는 app-agnostic 배관의 단일 주인. 근데 배포 장치를 봐. 그게 영리한 부분이니까. kit 은 각 앱이 런타임에 의존하는 패키지로 나오지 않아. 대신 각 앱이 kit 파일의 vendored 사본을 지니고, drift check 가 모든 소비자의 자기 테스트 안에서 돌아. 이걸 돌아가게 하는 규칙. kit 파일은 kit 에서만 편집하고, 동기화를 돌려 배포해. 제자리 편집된 vendored 사본은 그 레포의 테스트를 실패시켜. 그래서 가족이 로컬 파일의 편함(런타임 얽힘 없음, 각 앱 홀로 빌드)을 단일 주인의 규율(빨간 빌드 없이는 사본을 물리적으로 못 어긋내)과 함께 얻어.

kit 은 절대 도메인 shape 를 흡수 안 해

kit 이 가질 수 있는 것에 빡센 경계가 있고, 그게 '형태를 물려받아' 아이디어 전체의 뒷면이야. kit 은 정확히 app-agnostic 배관을 가져. cwkPippa client, publish, veil, ULID, settings, outbox, UI atom. 도메인 shape 는 절대 흡수 안 해. journey 는 Waystone 에, journal 은 Vesta 에, 건강 기록은 Forge 에 남아. 공유 kit 이 생기면, 도메인 자체가 흐려지기 시작할 때까지 계속 밀어넣고 싶어져. 그럼 깔끔한 세 앱을 얽힌 하나와 맞바꾸는 거야. kit 은 배관이고, 도메인은 앱이야. 공유 파이프를 뽑아내되 공유 목적은 절대 아니라.

자라는 가족을 위한 일반 규칙

구체에서 물러서면 패턴이 한 형태에서 앱 가족이 자라는 어디서든 재사용 가능해. 복제된 공유 코드는 한 주인 더하기 강제된 모으기 점검이 붙들지 않으면 어긋나. 강제는 패키지일 수도, vendored 사본 더하기 drift check 일 수도 있지만, 규율만으론 안 돼. 규율이야말로 다른 손들의 나란한 작업 아래 실패하는 바로 그거니까. 그리고 뭘 뽑아내든 app-agnostic 레이어만 뽑아내. 공유물이 어느 한 앱의 도메인을 알기 시작하는 순간, 인프라이길 멈추고 얽힘이 되기 시작해.

Code

drift check: 제자리 편집된 vendored 사본은 빌드를 실패시켜·python
# each consumer app vendors the kit files locally AND runs this in its tests
def test_kit_files_match_canonical():
    for path in vendored_kit_files():
        local = read(path)                        # this app's copy
        canonical = read(kit_source_of(path))     # the one owner
        assert local == canonical, (
            f"{path} was edited in place. Edit it in the kit and run the "
            f"sync; a locally-edited vendored copy is forbidden."
        )

# result:
#   - edit in the kit + sync  -> all copies converge, tests pass
#   - edit a copy in place    -> that repo's build goes red immediately
# 'shared' becomes enforced, not merely intended

Exercise

네 세계에서 둘 이상의 프로젝트에 복사된 코드 덩어리를 찾아 봐. 유틸 모듈, client 래퍼, config 모양. 사본들이 이미 어긋났는지 확인해. 그다음 모으기 장치를 설계해. 단일 주인이 누구고, 소비자가 자기 사본을 제자리 편집하면 뭐가 빌드를 실패시킬까? 뭐가 공유 레이어에 속하고 뭐가 각 앱에 남아야 할 도메인 shape 인지도 정해.
Hint
주인 없는 복사 코드는 거의 확실히 이미 어긋났어. 사본을 diff 해 봐. 고침은 한 주인 더하기 강제된 점검(패키지, 또는 vendored 사본 더하기 drift 테스트)이지, 절대 '우리 다 조심하자' 가 아냐. 그리고 경계를 지켜. app-agnostic 배관만 뽑아내. 공유 레이어가 한 앱의 도메인을 아는 순간, 인프라가 아니라 얽힘이야.

Progress

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

댓글 0

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

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