본문 바로가기
기술/Angular React Vue

FE UI Component Framework 환경설정

by 해피스트 2026. 1. 30.

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 클래스 정리 및 공식 문서 링크

클래스 명칭이 익숙하지 않을 때 참고할 곳은 공식 문서와 치트 시트 

 

접근성 진단 도구 (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 를 자동 감지함

반응형

댓글