디자인 프리뷰 독립 저장소 — 수작업 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 1 | 1포트 실행기(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.local → launch.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-guild는git fetch26초·"too many unreachable loose objects" 경고(워크트리 83개). 이 트랙 밖이라 손대지 않음. - 앱 PR #1649 가
.ts.bak3개를 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정리.