Next.js 15에서 storybook 세팅 및 tailwind 연동 방법 (pnpm)

2025-02-02
Next.jsStorybookTailwind

Table of Contents

설치

  • Package Manager: pnpm 9.15.4
  • node.js: v20.18.0
pnpm create next-app
✔ What is your project named? … my-app
✔ Would you like to use TypeScript? … No / ✔Yes
✔ Would you like to use ESLint? … No / ✔Yes
✔ Would you like to use Tailwind CSS? … No / ✔Yes
✔ Would you like your code inside a `src/` directory? … ✔No / Yes
✔ Would you like to use App Router? (recommended) … No / ✔Yes
✔ Would you like to use Turbopack for `next dev`? … ✔No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … ✔No / Yes
  • 기호에 맞게 옵션을 찍어줍니다.
pnpm dlx storybook@latest init
  • pnpm dlx는 원격 패키지를 임시로 설치하고 실행하는 명령어입니다. 이를 사용하여 Storybook을 초기화할 수 있습니다.

설치가 완료 되고, localhost:6006으로 접속하시면

페이지가 펼쳐지면 성공입니다.

파일 구조 및 역할

.storybook/main.ts

import type { StorybookConfig } from "@storybook/nextjs";

const config: StorybookConfig = {
	// 스토리 파일 경로 지정
	stories: [
		"../stories/**/*.mdx",
		"../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)",
	],
	// Storybook 기능 확장
	addons: [
		"@storybook/addon-onboarding",
		"@storybook/addon-essentials",
		"@chromatic-com/storybook",
		"@storybook/addon-interactions",
	],
	//  Next.js 전용 Storybook 사용
	framework: {
		name: "@storybook/nextjs",
		options: {},
	},
	// 정적 파일 지원
	staticDirs: ["../public"],
};

export default config;
  • stories: 스토리 파일 경로 지정
  • addons: Storybook 기능 확장
  • framework: Next.js 전용 Storybook 사용
  • staticDirs: 정적 파일 지원
  • Next.js 프로젝트에서 Storybook을 설정하는 기본적인 구성.

.storybook/preview.ts

import type { Preview } from "@storybook/react";

const preview: Preview = {
	// Storybook의 기본 동작을 조정하는 속성.
	parameters: {
		// Controls 패널에서 자동으로 속성을 감지하는 기능을 설정.
		controls: {
			//- `background`, `color` 속성 → 색상 선택기로 자동 매핑.
			//- `Date`로 끝나는 속성 → 날짜 선택기로 자동 매핑.
			matchers: {
				color: /(background|color)$/i,
				date: /Date$/i,
			},
		},
	},
};
export default preview;
  • background, color 속성 → 색상 선택기로 자동 매핑.
  • Date로 끝나는 속성 → 날짜 선택기로 자동 매핑.
  • Storybook에서 Controls 패널을 최적화.

stories 폴더 안에는 많은 예제들이 다운받아져 있습니다. 패턴이 보이시나요? tsx파일과 stories.ts 파일, css 파일로 구성되어 있습니다.


Button.tsx

import React from 'react';

import './button.css';

export interface ButtonProps {
/** Is this the principal call to action on the page? */
	primary?: boolean;
/** What background color to use */
	backgroundColor?: string;
/** How large should the button be? */
	size?: 'small' | 'medium' | 'large';
/** Button contents */
	label: string;
/** Optional click handler */
	onClick?: () => void;
}

/** Primary UI component for user interaction */
export const Button = ({
	primary = false,
	size = 'medium',
	backgroundColor,
	label,
	...props
}: ButtonProps) => {
	const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
	return (
		<button
		type="button"
		className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
	{...props}>
		{label}
	<style jsx>{`
		button {
		background-color: ${backgroundColor};
		}
	`}</style>
	</button>
	);
};
  • 일반적인 Button 컴포넌트입니다.

Button.stories.ts

import type { Meta, StoryObj } from '@storybook/react';

import { fn } from '@storybook/test';

import { Button } from './Button';


// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta = {
	title: 'Example/Button',
	component: Button,
	parameters: {
	// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
		layout: 'centered',
	},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
	tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/api/argtypes
	argTypes: {
		backgroundColor: { control: 'color' },
	},
// Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
	args: { onClick: fn() },
} satisfies Meta<typeof Button>;

export default meta;

type Story = StoryObj<typeof meta>;

// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
	args: {
		primary: true,
		label: 'Button',
	},
};

export const Secondary: Story = {
	args: {
		label: 'Button',
	},
};

export const Large: Story = {
	args: {
		size: 'large',
		label: 'Button',
	},
};

export const Small: Story = {
	args: {
		size: 'small',
		label: 'Button',
	},
};
  • 스토리 파일입니다. 구성을 살펴보겠습니다.
const meta = {
	//Storybook에서 분류.
	title: 'Example/Button',
	// 컴포넌트를 설정
	component: Button,
	// 컴포넌트를 화면 중앙에 배치.
	parameters: {
		layout: 'centered',
	},
	// 자동 문서화 활성화
	tags: ['autodocs'],
	// 색상 선택기로 변경 가능
	argTypes: {
		backgroundColor: { control: 'color' },
	},
	// Actions 패널에서 클릭 이벤트 확인 가능.
	args: { onClick: fn() },
} satisfies Meta<typeof Button>;

export default meta;
  • title"Example/Button"으로 Storybook에서 분류.
  • componentButton 컴포넌트를 설정.
  • parameters.layout = 'centered' → 컴포넌트를 화면 중앙에 배치.
  • tags = ['autodocs'] → 자동 문서화 활성화.
  • argTypes.backgroundColor → 색상 선택기로 변경 가능.
  • args.onClick = fn() → Actions 패널에서 클릭 이벤트 확인 가능.
  • satisfies Meta<typeof Button> → 타입 안전성 확보.
  • 만들어졌습니다. Example 안에 Button 컴포넌트가 보이고, tags = ['autodocs'] 로 자동 문서화가 된 모습과 parameters.layout = 'centered'로 화면 중앙에 컴포넌트가 배치 된 모습입니다.
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
	args: {
		primary: true,
		label: 'Button',
	},
};

export const Secondary: Story = {
	args: {
		label: 'Button',
	},
};

export const Large: Story = {
	args: {
		size: 'large',
	label: 'Button',
	},
};

export const Small: Story = {
	args: {
		size: 'small',
		label: 'Button',
	},
};
  • 상태값을 미리 설정하여 볼 수 있습니다.
  • 이렇게 다른 기본값으로 설정한 컴포넌트를 볼 수 있습니다.

Tailwind CSS 적용

globals.css

@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  --background: #ffffff;
  --foreground: #171717;
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #0a0a0a;
    --foreground: #ededed;
  }
}

body {
  color: var(--foreground);
  background: var(--background);
  font-family: Arial, Helvetica, sans-serif;
}

.storybook/preview.ts

import type { Preview } from "@storybook/react";

// tailwind css 적용
import "../app/globals.css";

const preview: Preview = {
	// Storybook의 기본 동작을 조정하는 속성.
	parameters: {
		// Controls 패널에서 자동으로 속성을 감지하는 기능을 설정.
		controls: {
			//- `background`, `color` 속성 → 색상 선택기로 자동 매핑.
			//- `Date`로 끝나는 속성 → 날짜 선택기로 자동 매핑.
			matchers: {
				color: /(background|color)$/i,
				date: /Date$/i,
			},
		},
	},
};
export default preview;
  • preview.ts 파일에 tailwindcss를 적용한 globals.css파일을 import 해줍니다.