안녕하세요, 로건입니다 👋
긴 시리즈도 이제 마지막 편입니다. 여기까지 오신 분들 정말 감사해요.
1년 전 처음 RN 프로젝트에 Storybook을 셋업하던 그 오후를 기억해요. 그때 동료가 던졌던 질문 — "그거 어차피 HTML로 렌더하는 거잖아요?" — 에 한 줄로 답하지 못했던 그 자리에서 시작된 시간이었어요. 지금은 그 한 줄을 가지고 있습니다.
이 마지막 글에서는 1년 운영하고 손에 남은 안전망의 전체 모양을, 그리고 아직 못 채운 칸들과 다시 도입한다면 다르게 할 결정 세 가지를 정직하게 정리해볼게요.
안전망의 최종 모양
먼저 우리 팀의 테스트 레이어 분담을 한 번에 보여드릴게요.
┌─────────────────────────────────────────────────────┐
│ Layer 5: Device QA / Detox │
│ - gesture, IME, perf, 네이티브 모듈 │
│ - 비싸지만 본질, 디바이스에서만 잡힘 │
│ - 빈도: release 전 / sprint 끝 │
├─────────────────────────────────────────────────────┤
│ Layer 4: Chromatic 시각 회귀 │
│ - 픽셀 단위 diff, PR마다 자동 │
│ - TurboSnap으로 영향받은 스토리만 캡처 │
│ - 빈도: PR마다 자동, ~3분 │
├─────────────────────────────────────────────────────┤
│ Layer 3: Storybook play 함수 │
│ - JS 레이어 로직 (props/state/handler) │
│ - Tier 1, 2 컴포넌트 (60개 정도) │
│ - 빈도: PR마다 자동, ~1분 │
├─────────────────────────────────────────────────────┤
│ Layer 2: Storybook 시각 카탈로그 │
│ - argTypes 콘트롤, Designs 탭에 figma 연결 │
│ - 디자이너·QA·개발자 합의 도구 │
│ - 빈도: 항상 (사이드바) │
├─────────────────────────────────────────────────────┤
│ Layer 1: jest unit │
│ - 순수 함수, 유틸리티 │
│ - 빈도: PR마다 자동, ~10초 │
└─────────────────────────────────────────────────────┘
위로 갈수록 비싸지고, 본질에 가까워져요. 아래로 갈수록 싸고, 자주 돕니다. Storybook은 Layer 2~4를 차지하는 그물입니다. 모든 칸을 채우는 것이 목표가 아니라, 각 칸의 주인이 누구인지 분명히 하는 것이 안전망 운영의 본질이에요.
play 함수의 Tier 분류 — 모든 곳에 달지 않는다
이게 1년 운영하면서 가장 늦게 안정화된 부분이에요. 처음엔 모든 컴포넌트에 play 함수를 달려고 했는데, 작성 비용이 도입 자체를 좌초시킬 뻔했거든요. Tier로 나눈 다음에 합리적이 됐어요.
| Tier | 정의 | play 적용 | 예시 |
|---|---|---|---|
| Tier 1 | 핵심 사용자 경로 | ✅ 필수 | Button, FormField, BottomSheet |
| Tier 2 | 자주 회귀 발생 영역 | ✅ 권장 | ToggleSwitch, Tabs, Stepper |
| Tier 3 | 보조 UI, 표시 전용 | ❌ 안 함 | Badge, Divider, Spinner |
| Showcase | 갤러리 grid | ❌ 안 함 (마찰) | AllTones, AllSizes |
Tier 1 + 2 합쳐서 60개 정도 컴포넌트에만 play를 달았어요. 모든 컴포넌트에 달았다면 작성 시간도 유지보수 부담도 무거웠을 겁니다. 안전망의 그물눈을 조밀하게가 아니라 적절하게 짜는 것이 핵심이었어요.
1년간 만들어진 산출물
숫자로 정리하면 이래요.
| 항목 | 수치 |
|---|---|
| 컴포넌트 스토리 | 200+ |
| play 인터랙션 테스트 | 60+ |
| Figma 자동 변환 스토리 | 80+ |
| 일괄 삭제한 페이지 스토리 (3편) | -106 |
| Chromatic baseline | 200+ 스냅샷 |
| 월 평균 PR 자동 검수 | ~80건 |
| Chromatic이 잡아낸 실제 회귀 | ~15건 |
마지막 줄이 가장 중요해요. 1년 동안 Chromatic이 잡아낸 실제 회귀가 15건이었습니다. 그 15건이 PR 머지 전에 잡히지 않았다면 어떻게 됐을지 상상해보세요. 디바이스 QA로 갔다가 운 좋게 발견되거나, prod 배포 후 사용자가 발견했을 거예요. 그 한 건당의 비용을 생각하면, 1년 운영 비용은 진작에 회수됐습니다.
아직 못 채운 칸들
이게 가장 정직하게 적어두고 싶은 부분이에요. 시도했는데 못 했거나, 의도적으로 미뤄둔 영역들이요.
| 영역 | 상태 | 이유 |
|---|---|---|
addon-a11y 자동 audit | ⏳ 미시작 | 우선순위 낮음. 디바이스 QA에서 함께 검수 중. |
test-runner CI 통합 (Tier 2까지) | 🔄 일부만 | Tier 1만 자동, Tier 2는 수동 트리거. |
| Living Style Guide (MDX 문서) | ⏳ 미시작 | argTypes 콘트롤로 충분하다는 판단. |
| 디자인 토큰 시각화 페이지 | 🔄 부분만 | Visual Builder로 부분 대체. |
| Detox e2e와의 dual 라벨링 | ⏳ 미시작 | 같은 시나리오를 양쪽에 두면 mock 무한 회귀 위험. |
| iOS vs Android 별도 베이스라인 | ⏳ 미시작 | 우리 케이스에서는 차이가 작아 무료 플랜 비용 우선 |
빈 칸을 모두 채우는 게 목표가 아니라, 각 칸이 누구의 책임인지 명시하는 것이 안전망 운영의 본질이라고 1편부터 6편까지 반복해서 말씀드렸어요. 이 표가 그 메시지의 가장 정직한 증거입니다.
다시 도입한다면 다르게 할 결정 세 가지
이게 마지막 정리예요. 1년을 다시 시작한다면 어떻게 다르게 할까라는 질문에 솔직하게 답해볼게요.
결정 1 — 페이지 스토리는 처음부터 시작하지 않는다
3편에서 한 번에 지운 그 106개 페이지 스토리. 다시 시작한다면 그 시간 전체를 절약하고 컴포넌트 스토리에 집중하겠어요. 처음엔 "1:1 매칭이 가능하지 않을까?" 하는 환상이 있었는데, mock 무한 회귀의 함정이 너무 명백했어요. 어떤 영역은 처음부터 디바이스 QA에 맡기는 게 답이라는 걸 가장 빨리 인정하는 게 1년차의 최선이었을 거예요.
결정 2 — Chromatic은 1주차에 Pilot으로 켠다
6편에서 단계적으로 풀었던 Pilot 단계를 2개월 뒤에야 시작했어요. 다시 시작한다면 첫 PR 머지하기 전에 Pilot을 켜겠어요. 빠르면 빠를수록 false positive 패턴을 빨리 발견하고, 도입 자체의 ROI를 한 자릿수 PR 만에 증명할 수 있어요. 그게 팀의 신뢰를 끌어올리는 가장 빠른 방법이에요.
결정 3 — 스토리 작성 표준을 공유 문서로 만든다
2편에서 정리한 한 줄 규칙들 — argTypes 전수 노출, 대표 스토리만 play, StyleSheet.create만, shim은 고치지 말기 등 — 이게 사실 내 머릿속에만 있었어요. 신규 합류한 분이 똑같은 실수를 다시 하시더라고요. 다시 시작한다면 첫 컴포넌트 스토리를 짤 때 이 규칙들을 사내 위키에 박아두는 것부터 하겠어요. 도구가 자동으로 강제할 수 있는 규칙은 ESLint 룰로, 사람만 결정할 수 있는 규칙은 PR 리뷰 체크리스트로요.
그리고 한 줄
1년이라는 시간이 정말 빨리 갔어요. 처음엔 "Storybook 도입"이라는 한 줄짜리 OKR이었는데, 끝나고 보니 팀이 디자인을 검수하는 방식, PR이 머지되기 전에 거치는 단계, 디자이너와 개발자가 의사소통하는 도구가 다 같이 바뀌어 있더라고요.
만약 여러분이 비슷한 갈림길에 서 계신다면, 마지막으로 한 줄 드리고 싶어요.
도구가 아니라 정책이 안전망을 만듭니다.
Storybook을 깔고, Chromatic을 붙이고, play 함수를 짜는 건 일주일이면 됩니다. 그런데 어떤 회귀를 잡을지, 어떤 회귀를 안 잡을지, 합격 받은 스토리를 어떻게 보호할지, false positive를 어떻게 줄일지 — 이런 정책들이 정착하는 데 1년이 걸렸어요. 그 정책들이 모여서 지금의 그물이 됐습니다.
만약 여러분도 RN 프로젝트에 Storybook 도입을 고민 중이시라면, 도구 자체보다 정책 한 묶음을 같이 설계하시는 걸 추천드려요. 시리즈에서 풀었던 한 줄 규칙들이 그 시작점이 될 수 있을 거예요. 그리고 안 짤 영역을 처음부터 정직하게 비워두세요. 그게 일주일 뒤에 후회를 가장 적게 남기는 결정이더라고요.
긴 시리즈 읽어주셔서 다시 한 번 감사합니다. 안전망이라는 단어가 처음보다 조금 더 손에 잡히는 모양으로 다가왔으면 좋겠어요. 다음에 또 어디선가, 다른 글로 인사드릴게요.