Storybook v10.2.1
Tailwind CSS v4.1.18
Vanilla JS
NPM v11.8.0
Node v22.14.0 s
프로젝트 초기화 및 최신 스택 설치
# 1. Vite 프로젝트 생성 (Vanilla HTML)
npm create vite@latest my-ui-library -- --template vanilla
cd my-ui-library
# 2. Storybook 설치 (HTML용 프레임워크 강제 지정)
npx storybook@latest init --type html
# 3. Tailwind CSS v4 설치 (Vite 플러그인 방식)
npm install tailwindcss @tailwindcss/vite
Vite 및 Storybook 설정 (v2026 최신)
Tailwind CSS v4는 별도의 tailwind.config.js 없이 Vite 플러그인을 통해 Zero-config로 작동
tailwindcss.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
"./.storybook/**/*.{js,ts,jsx,tsx}", // Storybook 설정 포함
],
theme: {
extend: {},
},
plugins: [],
}
#1. Vite 설정 (vite.config.js)
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [tailwindcss()],
});
#2. Global CSS 설정 (src/style.css)
@import "tailwindcss";
/* 프로젝트 전용 베이스 스타일이나 변수는 여기에 추가 */
:root {
--brand-color: #3b82f6;
}
#3. Storybook 프리뷰 설정 (.storybook/preview.js)
import '../src/style.css';
/** @type { import('@storybook/html').Preview } */
const preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
// 컴포넌트가 캔버스 중앙에 오도록 설정
layout: 'centered',
},
};
export default preview;
HTML 전용 컴포넌트 작성 (Atomic Design 방식)
React가 아니므로 DOM 요소를 생성하여 반환하는 함수 형태로 컴포넌트를 정의
예시: 공통 버튼 컴포넌트 (src/components/Button.js)
export const createButton = ({ label, primary = false, size = 'md', onClick }) => {
const btn = document.createElement('button');
btn.type = 'button';
btn.innerText = label;
// Tailwind v4 유틸리티 클래스 적용
const baseStyles = 'cursor-pointer rounded-full font-semibold transition-all focus:ring-2';
const sizeStyles = {
sm: 'px-3 py-1 text-sm',
md: 'px-5 py-2 text-base',
lg: 'px-7 py-3 text-lg',
};
const colorStyles = primary
? 'bg-blue-600 text-white hover:bg-blue-700'
: 'bg-gray-100 text-gray-900 border border-gray-300 hover:bg-gray-200';
btn.className = `${baseStyles} ${sizeStyles[size]} ${colorStyles}`;
if (onClick) btn.addEventListener('click', onClick);
return btn;
};
예시: 버튼 스토리 (src/components/Button.stories.js)
import { createButton } from './Button';
export default {
title: 'Components/Button',
tags: ['autodocs'],
render: (args) => createButton(args), // 렌더링 함수 지정
argTypes: {
label: { control: 'text' },
primary: { control: 'boolean' },
size: { control: { type: 'select' }, options: ['sm', 'md', 'lg'] },
onClick: { action: 'clicked' },
},
};
export const Primary = {
args: { primary: true, label: '확인', size: 'md' },
};
export const Outline = {
args: { label: '취소', size: 'md' },
};
Storybook UI 한국어 설정
한글 타이틀을 쓰고 컴포넌트를 만드는 데는 manager.js 설정이 필요없음 (스토리북은 utf-8)
테마를 사용한다면,
스토리북의 메뉴, 툴바 등 관리 화면을 한국어로 변경하려면 .storybook/manager.js 를 생성
// .storybook/manager.js
import { addons } from '@storybook/manager-api';
addons.setConfig({
enableShortcuts: false, // 단축키 충돌 방지 (선택)
showToolbar: true,
});
** Error: Build failed with 1 error:
│ .storybook/manager.js:2:23: ERROR: Could not resolve "@storybook/manager-api"
manager.js에서 필요한 패키지를 차지 못해 발생하는 의존성 미설치 에러
npm install -D @storybook/manager-api @storybook/theming
# --force 옵션을 사용하여 의존성 체크를 우회하고 강제 설치합니다.
npm install -D @storybook/manager-api @storybook/theming --force
# --legacy-peer-deps 옵션을 사용하여 npm이 호환 버전을 찾아서 기존 충돌 무시하도록 합니다
npm install -D @storybook/manager-api @storybook/theming --legacy-peer-deps
설치된 패키지 버전 확인
npm list --depth=0
node -v
npm -v
yarn -v
git --version
tsc -v
npm list @storybook/*
버튼 모양은 나오지만 스타일이 적용되지 않는다면
Vite와 Storybook이 Tailwind CSS를 빌드 프로세스에 포함하지 못해서임
CSS 파일에서 Tailwind 지시어 확인
src/style.css 에 @import "tailwindcss"; 있는지 확인
.storybook/preview.js 에서 CSS 임포트
스토리북 프리뷰 화면은 독립된 iframe이므로, 여기서 CSS를 명시적으로 불러와야 함
// .storybook/preview.js
import '../src/style.css'; 있는지 확인/경로 확인
Vite 설정 파일 확인 (vite.config.js)
스토리북은 Vite를 통해 빌드되므로, Vite 설정에 Tailwind 플러그인이 포함되어야 함
// vite.config.js
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [
tailwindcss(),
],
});
컴포넌트 클래스 확인
JS로 요소 생성할 때 class가 아닌 className 속성을 사용하고 있는지 확인
HTML 요소 객체는 className을 사용
코드 변경시 서버 재기동 없이 실시간으로 변경 사항 확인하기
HMR(실시간 반영/Hot Module Replacement) 활성화를 위한 설정 점검
별도 설정 없이 작동돼야 하지만 환경에 따라 vite.config.js에 감시 대상을 명시하면 훨씬 안정적임
// vite.config.js
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [tailwindcss()],
server: {
watch: {
// js 파일 내의 클래스 변화를 즉각 감지하도록 설정
usePolling: true,
},
},
});
.storybook/main.js 설정 확인
스토리북이 파일 변화를 감지하는 범위가 너무 좁으면 코드 수정 시 프리뷰가 갱신되지 않음
stories 경로를 넒게 잡았는지 확인
// .storybook/main.js
export default {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)", "../src/**/*.js"], // 컴포넌트 .js 파일도 감시 대상에 포함
addons: [
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"@storybook/addon-links",
],
framework: {
name: "@storybook/html-vite", // Vite 기반 확인
options: {},
},
};
실시간 작업 시 주의사항 (Tailwind 특성)
테일윈드는 소스 코드에서 문자열 그대로의 클래스명을 찾아내기 때문에 아래와 같이 코드를 짜면 실시간 반영이 안되기도 함
안 좋은 예 (동적 생성)
// Tailwind가 'bg-blue-500'이라는 전체 문자열을 찾지 못함
const color = 'blue';
element.className = `bg-${color}-500`;
좋은 예 (전체 클래스 명시)
// Tailwind가 빌드 타임에 클래스를 확실히 인지함
const colorClass = isPrimary ? 'bg-blue-500' : 'bg-gray-500';
element.className = colorClass;
브라우저 캐시 강제 새로고침
코드를 변경했는데 화면이 그대로면 스토리북 프리뷰 창 안을 클릭 후 Ctrl + F5 (강제 새로고침)
캐시 삭제 및 재시작
# Windows 기준 캐시 폴더 삭제
rmdir /s /q node_modules\.cache
npm run storybook
VSCode에서 Tailwind CSS 자동 완성(IntelliSense) 사용하기
필수 확장 프로그램 설치 : VSCode Extensions 에서 Tailwind CSS IntelliSense (제작사: Tailwind Labs) 설치
주요 기능은, 자동 완성, 린팅 Linting(클래스 오타, 스타일 충돌 감지 경고), 미리보기 Hover Preview(class에 마우스오버시 css 속성 보여줌)
설정 팁(HTML/JS 필수) : VSCode settings.json 에 아래 설정 추가
{
"editor.bracketPairColorization.enabled": true,
"editor.guide.bracketPairs": "active",
// --- Tailwind CSS 설정 시작 ---
"tailwindCSS.includeLanguages": {
"javascript": "javascript",
"html": "html"
},
"editor.quickSuggestions": {
"strings": true, // 문자열 안에서도 자동완성 허용
"other": true,
"comments": false
},
"tailwindCSS.emmetCompletions": true,
"editor.inlineSuggest.enabled": true
// --- Tailwind CSS 설정 끝 ---
}
** 명령 팔레트 이용 : Ctrl + Shift + P > settings json 입력 > 목록에서 Preferences: Open User Settings (JSON) 선택
** 메뉴 아이콘 이용 : 좌측 하단 톱니바퀴 > Settings > 오른쪽 구석에 있는 파일 아이콘(Open Settings (JSON)) 클릭
Tailwind CSS 클래스 자동 정렬(Prettier Plugin Tailwind CSS)
px-5 py-2 rounded-full 등 순서가 뒤죽박죽일 때 자동 정렬해 줌
권장순서는 레아아웃 - 사이즈 - 색상 순 ( https://github.com/tailwindlabs/prettier-plugin-tailwindcss )
npm install -D prettier-plugin-tailwindcss
Tailwind CSS 클래스 정리 및 공식 문서 링크
클래스 명칭이 익숙하지 않을 때 참고할 곳은 공식 문서와 치트 시트
- Tailwind CSS Official Documentation: 가장 정확하며 검색 기능이 뛰어남 (예: 상단 검색창에 rounded 입력 시 관련 클래스 즉시 출력) ( https://tailwindcss.com/docs/installation/using-vite )
- Tailwind CSS Cheat Sheet (정리 사이트): 모든 클래스를 한 페이지에 카테고리별로 모아두어 Ctrl+F로 찾기 편리함 ( https://nerdcave.com/tailwind-cheat-sheet )
접근성 진단 도구 (addon-a11y) 설치 및 설정 방법
애드온 설치
npm install -D @storybook/addon-a11y --legacy-peer-deps
스토리북 설정 등록
// .storybook/main.js
/** @type { import('@storybook/html-vite').StorybookConfig } */
const config = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"@storybook/addon-links",
"@storybook/addon-a11y", // 👈 여기 추가
],
framework: {
name: "@storybook/html-vite",
options: {},
},
};
export default config;
접근성 진단 확인 방법
스토리북 하단 패널에 Accessibility 탭 생성됨
1. Violations (위반) : 즉시 수정해야 하는 접근성 결함
2. Passes (통과) : 접근성 지침 준수 항목들
3. Incomplete (미완성) : 도구가 자동으로 판다할 수 없어 수동 확인 필요한 항목
고대배 및 색상 대비 대응 코드 가이드
색상 대비 Contast Ratio 문제 해결을 위해 컴포넌트 내부에 Tailwind의 고대비 유틸리티를 활용하는 방법
Button.js 개선
export const createButton = ({ label, primary = false }) => {
const btn = document.createElement('button');
btn.innerText = label;
// [접근성 포인트]
// 1. 최소 대비 4.5:1을 준수하는 색상 조합 (blue-600은 흰색 배경에서 4.5:1 이상)
// 2. 고대비 모드(@media forced-colors) 대응 테두리 추가
const baseClasses = 'px-5 py-2 rounded-lg font-bold transition-all focus-visible:ring-4 focus-visible:ring-blue-300 outline-none';
const modeClasses = primary
? 'bg-blue-700 text-white border-2 border-blue-800' // 명확한 구분선
: 'bg-white text-gray-900 border-2 border-gray-900'; // 고대비 텍스트
btn.className = `${baseClasses} ${modeClasses}`;
// 3. 스크린 리더를 위한 보조 설명 (필요시)
btn.setAttribute('aria-label', primary ? `${label} (주요 작업)` : label);
return btn;
};
** 스토리보드 a11y 패널을 켜두면 텍스트/배경 대비, 폼 레이블 누락, 이미디 대체 텍스트, 중복 ID 를 자동 감지함
'기술 > Angular React Vue' 카테고리의 다른 글
| Storybook v10 & TailwindCSS v4 설정 오류 해결 (0) | 2026.02.05 |
|---|---|
| TailwindCSS 에 대해 알아보기 (0) | 2026.01.31 |
| Storybook 스토리북 환경 설정 (0) | 2026.01.30 |
| Vue.js vs React 4주 커리큘럼 비교 버전 (1) | 2025.03.21 |
| React 실전 마스터 4주 과정 (0) | 2025.03.20 |
댓글