Skip to content

디자인 프리뷰 독립 저장소 — 수작업 7단계에서 명령 하나로, Production 을 보던 프리뷰를 staging 강제로 (2026-09-15)

  • 기간: 2026-09-15 13:57 ~ 20:35 KST (세션 2개, 오너 지시 "브랜치는 main 동기화 지점에서, 병렬 세션은 각자 포트 1개, DB 는 staging")
  • 랜딩: Barbelic-preview PR #3(Phase 1, e2c4497) · #4(Phase 2, bf282de) · #5(Phase 3, 2dcb546) · #6(Phase 4 README, a09f6cf) · 문서 Barbelic-docs PR #122(cd96131). 앱 저장소 변경·마이그레이션·배포 없음
  • 설계서: Barbelic-preview #2 본문("예상 효과·개선사항" 절 포함)
  • 정본: 절차 디자인 세션 프리뷰 · 앱과의 약속 = 도구 저장소 README "앱과의 약속" 표 · 전역 지침 §29(세션 셋업)
  • 도구: dekerd/Barbelic-preview(로컬 D:\LiftGuild-2026\Claude\barbelic-preview, bin/preview.mjs), 상태 %LOCALAPPDATA%\barbelic-preview(레포 밖)
  • 게이트: 도구 저장소 npm run check(node --test 36건, 외부 의존성 0). 앱 CI·pgTAP·e2e 는 만지지 않음
  • 버그리포트: 없음
  • 계약: 없음(앱 소스 변경 없음. 도구가 기대는 앱 파일·변수 목록은 README 표)

Phase 현황

Phase내용상태
Phase 11포트 실행기(Vite 미들웨어 모드)·staging 강제·틀 페이지✅ PR #3 (e2c4497)
Phase 2등록부·워크트리·포트 풀: up <이슈번호>/ls/down/rm/prune/logs/doctor✅ PR #4 (bf282de)
Phase 3기기 틀 완성: 프리셋 4종·안전 영역 띠✅ PR #5 (2dcb546)
Phase 4절차·문서 전환: 문서 저장소·전역 지침 §29·메모리✅ PR #6 (a09f6cf) · docs #122 (cd96131)

1. 배경

디자인 세션은 앱 화면을 브라우저에서 보면서 스타일을 고친다. 2026-09-15 디자인 세션 4개(앱 #1633·#1634·#1637·#1639)를 전역 지침 §29 의 수작업 7단계(이슈 → 브랜치·워크트리 → npm ci.env.locallaunch.json+skip-worktree → 개발 서버 → 제목)로 셋업했다. 오너 지시(같은 날): 세션은 main 과 동기화된 지점에서 브랜치를 따고, 병렬 세션은 각자 포트 1개를 쓰며, DB 는 staging 에 연결한다.

2. 문제 제기

프리뷰 6개 중 4개가 Production DB 를 보고 있었다

19:12 KST 실측(각 서버의 __BARBELIC_DEPLOYMENT__ 선언): 5637·5737·5639·5640 이 Production 프로젝트(kobxeylancdimqhfkbnl). 원인은 세 워크트리에 .env.local 이 없어서 — 개발 서버는 대상이 없으면 local 로 뜨고 local 의 기본값이 Production 이다. 지시(staging)를 빠뜨려도 막는 것이 없었다.

포트 규칙이 세션마다 달랐다

5634 / 5737 / 5640 / 51633 — 5<N> 규칙은 4자리 이슈 번호에서 5자리 포트가 되고, 한 워크트리(wt1639)가 포트 2개를 점유했다.

앱 저장소를 세션마다 오염시켰다

.claude/launch.json 은 앱이 추적하는 파일이라 세션마다 고친 뒤 git update-index --skip-worktree 로 숨겨야 했다. 기기 틀은 세션 1 워크트리의 미커밋 파일에만 있었다.

병합된 워크트리가 방치됐다

앱 저장소 워크트리 82개 중 55개는 브랜치가 이미 병합됐는데 남아 있었다(각 node_modules 약 181MB).

3. 해결 방안

원칙 (오너 결정, 2026-09-15)

D1 "브랜치는 main 과 동기화된 지점에서, 프리뷰는 그 브랜치를 따라간다. 병렬 세션은 독립." D2 "끝난 브랜치는 release 에 병합." D3 "병렬 세션은 각자 포트 1개." D4 "DB 는 staging." D5(이슈 이관 지시) "이 트랙의 이슈는 프리뷰 저장소에 둔다." D6(질문 "릴리스에 머지하면 워크트리도 정리돼?") → 병합·clean·push 확인 뒤 자동 정리.

접근

대안판단
A. §29 절차를 더 자세히 적고 세션이 계속 수작업기각 — 세션 4개 중 2개가 빠뜨렸다. 지침으로는 못 막는다
B. 앱 저장소에 npm run design:preview 스크립트기각 — 도구를 고칠 때마다 앱 release 큐를 타고, "독립 repo·앱은 블랙박스"와 반대
C. Barbelic-preview 를 디자인 프리뷰 도구 저장소로 완성채택
C-1 중계 서버 + Vite 자식 프로세스(세션당 포트 2개)기각 — D3 위반
C-2 Vite 미들웨어 모드로 한 프로세스·한 포트채택 — 실험(앱 main, 포트 5399 하나)에서 틀·앱·모듈·SPA 폴백·HMR 웹소켓 모두 같은 포트 확인

4. 적용한 내용

Phase 1 — 1포트 실행기 (PR #3)

lib/server.mjs(Vite createServer({ middlewareMode }) + 이 저장소 frame//__preview/ 에 얹는 플러그인), lib/staging.mjs(staging 대상은 앱 deployment-targets.json, 공개 키는 배포된 staging 페이지에서 꺼내 캐시, .env.local 세 줄 병합, 첫 페이지 선언이 staging 이 아니면 서버를 내리고 실패), lib/app.mjs(앱과의 약속 검사). 초안의 로컬 샌드박스·시드·중계 서버는 삭제.

Phase 2 — 등록부·워크트리·포트 풀 (PR #4)

lib/registry.mjs(등록부 JSON, mkdir 원자성으로 잠금, 60초 넘은 잠금 인수, 포트 풀 5300~5319 배정), lib/worktree.mjs(fetch·기준 결정·워크트리 생성·병합/clean/push 판정·삭제·마이그레이션 드리프트), lib/process.mjs(분리 프로세스·READY 대기·트리 종료·로그 tail). up <N> 은 잠금 안에서 prune → 워크트리 → 포트 → 등록, 잠금 밖에서 npm ci → 분리 실행 → READY → 드리프트 경고. 테스트 12개(잠금 동시성, 임시 git 저장소로 조건 판정, 진짜 자식 프로세스).

Phase 3 — 기기 틀 (PR #5)

프리셋 4종(iPhone 17 Pro·iPhone SE·Galaxy S25·iPad mini), "안전 영역 표시" 띠(?safe=1), 상단 정보(치수·안전 영역·배율), window.__barbelicPreview 노출.

Phase 4 — 절차·문서 (PR #6, docs #122)

문서 저장소에 디자인 세션 프리뷰 신설, 저장소 경계 표에 행 추가, 전역 지침 §29 를 "up <N> 한 번"으로 개정, 메모리 갱신. 실행 중이던 세션은 손대지 않았다(새 세션부터).

주요 결정과 그 근거

  • 기본 기준 브랜치 = origin/main 을 포함한 가장 낮은 origin/release/vX.Y.Z(지금 v0.19.3). v0.20.0 도 main 을 포함하지만 "지금 나갈 차례"는 낮은 쪽이다. --base 로 바꿀 수 있다.
  • 브랜치 삭제는 git branch -D — git 의 -d 는 main(HEAD) 기준이라 release 에만 병합된 브랜치를 거부한다. 병합 여부는 도구가 목적 release 기준으로 먼저 확인한다.
  • ls·down·logs 는 fetch 하지 않는다(앱 체크아웃 fetch 26초). 병합 판정이 뒤처질 수는 있어도 앞서지는 않으므로 지우는 쪽으로 틀리지 않는다.
  • 손으로 만든 wt<N> 은 브랜치 이름만 맞으면 그대로 등록해 쓴다(오늘 세션들의 워크트리를 버리지 않기 위해).

작업 중 드러난 것

  • Vite 미들웨어 모드의 의존성 스캔이 index.html 을 현재 폴더 기준으로 찾는다 → 서버 프로세스의 작업 폴더를 앱 워크트리로 옮겨 해결.
  • 이 PC 의 git 이 2.24 라 git init -b·switch 등 새 옵션에 기대지 않았다.
  • Node 24 에서 spawn(… , { shell: true }) 에 인자를 주면 DEP0190 경고 → Windows 는 cmd.exe /c npm ci 로 호출.
  • 앱 기본 체크아웃 lift-guildgit fetch 26초·"too many unreachable loose objects" 경고(워크트리 83개). 이 트랙 밖이라 손대지 않음.
  • 앱 PR #1649 가 .ts.bak 3개를 release/v0.19.3 에 넣었다(이 트랙 밖, 앱 쪽 정리 필요).
  • 지금 release/v0.19.3 기준 프리뷰는 staging DB 에 없는 마이그레이션 10개를 경고한다(동의 v5·원본 보호 등). 도구는 알리기만 하고 해결은 승격.

5. 적용 결과

항목결과
프리뷰가 Production 을 보는 사고6개 중 4개 → 0 (staging 선언이 아니면 기동 거부; Production 선언 거부 단위 테스트)
셋업 수고수작업 7단계·파일 3개 편집 → up <N> 1개, 실측 29초(fetch 포함)
포트규칙 4가지·한 워크트리 2개 → 풀 5300~5319 에서 1개, 이슈당 고정, ls 한눈에
앱 저장소 오염launch.json skip-worktree 매 세션 → 0
기기 틀세션 1에만(미커밋) → 공통 프리셋 4종, 안전 영역 주입값 = 프리셋값 브라우저 계측 일치
병렬 독립이슈 2개 동시 up → 포트 2개, 한쪽 CSS 수정이 그쪽 포트에만 HMR 반영, 한쪽 down 에 다른 쪽 무영향
병합 뒤 정리없음 → 병합·clean·push 확인 뒤 자동(prune), 어긋나면 이유 표시(단위 테스트·실기동 rm 거부 확인)
미검증실제 디자인 세션이 이 도구로 셋업된 사례는 아직 없음(새 세션부터). 소셜 로그인 되돌아오기 주소는 21:00 사용자 등록 뒤 콜백 실측으로 허용 확인(실제 계정 로그인 완주는 자동 확인 대상 아님)

6. 이번 개선으로 향상된 것

디자인 세션이 DB 를 잘못 볼 수 없다

staging 이 아니면 서버가 뜨지 않는다. 지침을 빠뜨려도 결과가 같다.

세션 하나 = 명령 하나 = 포트 하나

셋업·목록·종료·정리가 한 도구 안에 있고, 오너는 ls 로 어느 세션이 어느 포트인지 본다.

구조적으로 남는 것

저장소 경계(프리뷰 도구는 앱 밖), 앱과의 약속 표(계약), 포트 풀, staging 강제 검사, 병합·clean·push 정리 규칙.

남은 것

  • 오너 손: Supabase staging Auth Redirect URLs 에 프리뷰 주소 등록 → 2026-09-15 21:00 등록 완료, 콜백 실측으로 확인(이슈 #2 댓글). 선택: 세션별 테스트 계정.
  • 후속(범위 밖): 이 저장소 #1 의 화면×기기 대조표, 앱 체크아웃 git prune, 앱 release 의 .ts.bak 정리.