결정-0018: 컴포넌트 워크벤치는 Storybook(angular-vite)으로 한다
상태
승인됨
맥락
디자인 시스템 컴포넌트를 앱 화면 없이 격리해서 보고 검토할 곳이 필요했습니다. 라이트와 다크 양쪽을 지원하기로 했으므로 두 모드를 함께 볼 수 있는지가 특히 중요했습니다. 한 모드만 보면 다른 쪽이 깨진 것을 늦게 발견하기 때문입니다.
당시 전제는 Angular 22와 Vite 기반 빌더, zoneless 구성, TypeScript 6, Tailwind 4, Vitest 4, 그리고 SSR 사용입니다.
워크벤치 설정은 이 저장소를 받는 쪽이 물려받아 유지해야 하는 부채입니다. 클론 직후 Docker 없이 빌드된다는 기준을 세울 때와 같은 종류의 고민이었습니다.
검토한 대안
Storybook (@storybook/angular-vite) — 채택
| 구분 | 내용 |
|---|---|
| 장점 | 사실상 표준이며 애드온 생태계가 있습니다. 접근성 검사와 뷰포트, 상호작용 테스트가 그것입니다. 스토리 포맷이 널리 알려져 있어 이 아키텍처를 채용하는 쪽이 이해하기 쉽고 링크로 공유할 수 있습니다 |
| 단점 | preview 상태이며 문서가 API와 기본값이 바뀔 수 있다고 밝힙니다. 서드파티 Angular 변환 플러그인에 의존하고 Vite 버전이 둘로 갈립니다 |
Storybook (webpack)
stable 이지만 레거시 빌더를 peer 로 요구합니다. 현재 빌더와 다르므로 빌드 툴체인이 둘이 됩니다. 기각합니다.
자체 워크벤치 라우트와 Vitest
컴포넌트 갤러리를 라우트로 두고 자동 검증은 이미 있는 Vitest 가 맡습니다. 의존성이 0이고 버전 위험이 0입니다. 잃는 것은 격리 렌더링과 애드온이며, 접근성 자동 검사를 재현하려면 결국 직접 만들게 됩니다. Storybook 이 동작함을 확인했으므로 채택하지 않았습니다.
정적 빌드 후 서빙
HMR 이 없어 값 하나 바꿀 때마다 전체 재빌드를 수동으로 돌려야 합니다. 디자인 시스템 작업은 바꾸고 눈으로 확인하는 반복이라 이 비용이 큽니다. 기각합니다.
검증한 것
Storybook 을 고르기 전에 실제로 도는지 확인했습니다. 문서만으로는 이 조합에서의 동작을 알 수 없었기 때문입니다.
시그널로 갱신되는 컴포넌트를 워크벤치에 올려 브라우저에서 클릭했습니다. 정적 컴포넌트는 변경 감지가 깨져 있어도 렌더링되므로 검증이 되지 않습니다.
| 확인 항목 | 결과 |
|---|---|
| dev 서버와 정적 빌드 양쪽의 DOM 갱신 | 클릭 수만큼 갱신되었습니다 |
window.Zone |
undefined 입니다. zone.js 없이 동작합니다. peer 로 선언되어 있지만 실제로 설치되지 않으며 앱의 zoneless 구성을 워크벤치가 깨지 않습니다 |
이것이 가장 걱정했던 지점이었습니다. 워크벤치만 zone.js 를 되살리면 한쪽에서만 재현되는 변경 감지 버그가 생깁니다. 그 위험은 실재하지 않았습니다.
결정
@storybook/angular-vite를 씁니다. 애플리케이션 빌더와 같은 Vite 계열이고 Vitest 애드온으로 상호작용 테스트를 붙일 수 있습니다..storybook/tsconfig.json을 반드시 둡니다.preview.ts에 애플리케이션 프로바이더를 추가하지 않습니다. 워크벤치가 앱과 다른 변경 감지 설정을 쓰면 한쪽에서만 재현되는 버그가 생깁니다. 전역 스타일만 앱과 공유합니다.- 모든 컴포넌트 스토리는 라이트와 다크를 나란히 띄웁니다. 테마 속성을 하위 트리에 걸 수 있게 만들어 둔 덕에 한 화면에 둘을 넣을 수 있습니다.
- 포맷 검사가
.storybook도 검사합니다. 설정 파일이 포맷 게이트 밖에 있으면 반드시 어긋납니다.
주의
.storybook/tsconfig.json 이 없으면 원인을 찾기 어려운 방식으로 멈춥니다
프리셋이 Angular 변환 플러그인에 이 경로를 넘깁니다. 없으면 TypeScript 타입과 @Component 데코레이터가 변환되지 않은 채 브라우저로 나가 프리뷰가 SyntaxError 로 멈춥니다. 그 에러는 화면에 표시되지 않고 스토리 준비 중 상태로 보입니다.
재검토 조건
@storybook/angular-vite가 stable 에서 벗어나 깨지는 경우 자체 워크벤치와 Vitest 조합으로 전환합니다. 스토리는 컴포넌트를 참조하는 얇은 파일이므로 전환 비용이 스토리 재작성에 한정됩니다.- Angular 메이저 업그레이드에서 Storybook 이 따라오지 못하는 경우도 같습니다. 업그레이드를 Storybook 에 묶어 미루지 않습니다.
- 디자이너와 협업하거나 팀이 커지는 경우 애드온의 값이 올라갑니다. 본 결정이 그 방향에 유리합니다.
결과
- 컴포넌트를 앱 화면 없이 격리해서 보고 두 모드를 동시에 비교할 수 있습니다.
- HMR 이 있어 값을 바꾸고 바로 확인하는 반복이 빠릅니다.
- zoneless 구성이 워크벤치 때문에 흐트러지지 않습니다.
- 감수하는 것
- preview 상태 도구를 기본값으로 둡니다. 이 아키텍처를 채용하는 쪽이 물려받는 부채입니다.
- Vite 버전이 트리에 둘 존재합니다. 현재 문제를 일으키지 않지만 플러그인 동작이 갈릴 여지가 있습니다.
- 서드파티 Angular 변환 플러그인에 간접 의존합니다.