프론트엔드

Next.js 프로젝트에서 Storybook 도입해보기

김민나 2026. 1. 29. 22:34

프론트엔드 개발을 하다 보면 컴포넌트 단위로 UI를 나누어 개발하는 일이 많아진다.

특히, Next.js를 사용하면서 페이지 단위가 아닌, 재사용 가능한 UI 컴포넌트의 중요성을 깨닫게 되었다.

 

컴포넌트가 늘어나면 늘어날수록 다음과 같은 고민이 생긴다.

 

  • 이미 만들어진 컴포넌트가 있는지 한눈에 파악하기 어렵다
  • props에 따라 컴포넌트가 어떻게 변하는지 확인하려면 직접 페이지를 띄워야 한다
  • UI 테스트를 하려면 매번 특정 페이지와 상태를 만들어야 한다

 

이런 문제점들을 해결하기 위해 iDear 프로젝트에서 Storybook을 도입해 보기로 했다.

 


 

Storybook이란?

스토리북은 비즈니스 로직이나 페이지 맥락에서 분리된 상태로 UI 컴포넌트를 개발하고 테스트할 수 있도록 도와주는 도구다.

컴포넌트를 독립된 환경에서 렌더링할 수 있기 때문에 페이지를 띄우지 않고도 UI를 바로 확인할 수 있고, 코드 없이도 컴포넌트의 동작과 상태를 빠르게 파악할 수 있다.

 

Next.js처럼 페이지 중심의 프레임워크에서도 Storybook은 컴포넌트 중심 개발 환경을 만들 수 있다는 큰 장점을 가진다. 


프로젝트에 도입하게 된 이유

이번 프로젝트에서는 공통 버튼, 모달 등 여러 페이지에서 재사용되는 컴포넌트가 매우 많았다.

스토리북을 도입하지 않았다면, 컴포넌트를 확인하기 위해서 해당 컴포넌트를 사용하는 페이지까지 이동해야 했고,

특정 상태(에러, 로딩, 비활성화 상태) 등을 보려면 임시 코드나 조건 분기를 계속 추가해야 하는 문제점이 있었다.

 

Storybook을 도입한 이후 달라진 개발 방식

CDD(Component Driven Development) 적용

페이지를 먼저 만드는 대신, 가장 작은 UI 단위부터 독립적으로 설계하는 방식을 말한다.

페이지에 종속된 props가 아닌, 이 컴포넌트가 정말 독립적으로 쓰일 수 있을지를 고민할 수 있게 되었다.

 

컴포넌트 상태를 한눈에 확인할 수 있다

Storybook의 args를 활용하면 하나의 컴포넌트로 다양한 상태를 쉽게 표현할 수 있다.

 

  • 기본 상태
  • 비활성화 상태
  • 에러 상태
  • 로딩 상태

 

이 모든 상태를 페이지 이동 없이 한 화면에서 확인할 수 있다는 점이 큰 생산성 차이를 만들었다.

 


Storybook을 가이드 문서로 활용하기 

Storybook은 단순히 컴포넌트를 보여주는 도구를 넘어 문서화 도구로도 활용할 수 있다.

iDear 프로젝트에서는 Introduction.mdx 파일을 만들어 팀원들과 공유할 가이드를 작성해 두었다.

 

  • 프로젝트에서 Storybook을 사용하는 목적
  • 컴포넌트 작성 시 규칙
  • props 네이밍 컨벤션

 

등을 문서로 정리해 두어 새로 합류한 팀원도 빠르게 프로젝트 구조를 이해할 수 있도록 했다.

 


 

프로젝트 테마 스토리북에 설정하기 

Storybook에서도 프로젝트의 디자인 시스템과 동일한 분위기를 유지하고 싶었고, storybook/theming을 사용해 프로젝트 전용 테마를 설정했다. (공식 문서를 참고해서 작성했다.)

https://storybook.js.org/docs/configure/user-interface/theming

import {create} from 'storybook/theming';

export default create({
  base: 'light',

  brandTitle: 'iDear DESIGN SYSTEM',
  brandUrl: 'https://www.i-dear.kr',
  brandTarget: '_self',
  //
  colorPrimary: '#ffcccc',
  colorSecondary: '#ffcccc',

  // UI
  appBg: '#ffffff',
  appContentBg: '#ffffff',
  appPreviewBg: '#ffffff',
  appBorderColor: '#ffcccc',
  appBorderRadius: 4,

  // Toolbar default and active colors

  barSelectedColor: '#ffcccc',
  barHoverColor: '#ffcccc',
  barBg: '#ffffff',

  // Form colors
  inputBg: '#ffffff',
  inputBorder: '#10162F',
  inputTextColor: '#10162F',
  inputBorderRadius: 2,
});

 

그리고 manager.ts 에서 해당 테마를 적용한다. 

import {addons} from 'storybook/manager-api';
import theme from './theme';

addons.setConfig({
  theme: theme,
});

 

 

 


스토리 작성하기 

import GlobalButton from '@/components/buttons/GlobalButton';
import {Meta, StoryObj} from '@storybook/nextjs';

const meta: Meta<typeof GlobalButton> = {
  title: 'Components/Buttons/Global Button',
  component: GlobalButton,
  tags: ['autodocs'],
  argTypes: {
    text: {control: 'text', description: '버튼에 표시될 텍스트'},
    onClick: {action: 'clicked', description: '버튼 클릭 시 실행될 함수'},
  },
  parameters: {
    docs: {
      description: {
        component: `사이트 전반에서 쓰이는 글로벌 버튼 컴포넌트입니다. 버튼이 클릭되었을 때 실행할 함수와 text를 props로 받아서 렌더링합니다.`,
      },
    },
  },
};

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
  args: {
    text: '아이디어 등록하기',
  },
};

 

  • argTypes
    → props 설명과 컨트롤 UI를 함께 제공
  • actions
    → 클릭 이벤트를 실제 함수 없이도 확인 가능
  • docs.description
    → 컴포넌트의 역할을 문서처럼 설명

 

 

이렇게 컴포넌트 구현과 함께 스토리를 함께 작성하면 이 컴포넌트가 무엇을 하는지 바로 이해할 수 있게 된다. 

 


Chromatic으로 Storybook 배포하기 

Storybook을 로컬에서만 사용하는 데 그치지 않고,팀원들과 언제든 공유할 수 있는 형태로 배포하고 싶다는 니즈가 생겼다.

  • 디자이너 / 기획자와 UI를 빠르게 공유하자!
  • 이 버튼 상태 맞나요? 같은 커뮤니케이션 비용을 줄이자!

알아보니 Storybook과 가장 궁합이 좋은 배포 도구가 바로 Chromatic이었다.

 

Chromatic이란?

Chromatic은 Storybook 공식 팀에서 만든 서비스로, Storybook을 자동으로 빌드하고 웹에 배포해 주는 도구다.

Chromatic을 사용하면 별도의 서버 설정 없이 스토리북을 배포할 수 있고, 배포된 URL 하나로 모든 컴포넌트를 공유할 수도 있으며, PR 단위로 UI 변경 사항을 시각적으로 비교할 수 있다. 

이번 프로젝트에서는 우선 공유 가능한 Storybook 배포 목적에 집중해서 사용했다.

 

 

GitHub Actions로 Chromatic 자동 배포하기

PR이 올라올 때마다 스토리북을 자동으로 배포하고, 갱신된 스토리북 링크를 깃허브 PR 내에서 확인하기 위해 Github Actions + Chromatic을 연동했다.

 

다음 흐름으로 진행된다. 

 

PR 또는 특정 브랜치에 push 가 발생했을 경우,

1. Github Actions 실행

2. Storybook 빌드

3. Chormatic 자동 배포

4. 배포된 Storybook URL을 PR 코멘트로 남김 

 

아래는 실제 프로젝트에서 사용 중인 Github Actions 설정이다. 

name: 'Deploy Storybook to Chromatic'

permissions:
  contents: read
  pull-requests: write

on:
  push:
    branches:
      - main
      - develop

  pull_request:
    branches:
      - main
      - develop

env:
  CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}

jobs:
  chromatic-deploy:
    runs-on: ubuntu-latest
    outputs:
      storybook_url: ${{ steps.chromatic.outputs.storybook-url }}
      current_time: ${{ steps.current-time.outputs.formattedTime }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Install dependencies
        run: npm install

      - name: Build Storybook
        run: npm run build-storybook

      - name: Publish to Chromatic
        id: chromatic
        uses: chromaui/action@v1
        with:
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
          autoAcceptChanges: true
          exitZeroOnChanges: true

      - name: Get current time
        id: current-time
        uses: josStorer/get-current-time@v2
        with:
          format: 'YYYY년 MM월 DD일 HH시 mm분 ss초'
          utcOffset: '+09:00'

      - name: Comment pull request
        if: github.event_name == 'pull_request'
        uses: thollander/actions-comment-pull-request@v1
        with:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          message: |
            💄 Storybook preview url: ${{ steps.chromatic.outputs.storybookUrl }}
            🕖 Update time: ${{ steps.current-time.outputs.formattedTime }}

 

 

위와 같이 PR이 생성되면 코멘트로 프리뷰 url, 업데이트 시간을 함께 달아 준다!

마치며 

Storybook을 도입하기 전에는 컴포넌트는 페이지를 만들다 보면 자연스럽게 생기는 것에 가까웠는데, Storybook과 Chromatic을 함께 사용하다 보니 컴포넌트는 먼저 정의하고, 공유하고, 검증하는 대상이 되었다.

 

특히 Next.js처럼 페이지 중심으로 개발이 흘러가기 쉬운 환경에서 UI를 독립적으로 고민하게 만들고, 재사용성과 설계를 한 번 더 생각할 수 있게 된다. 

 

처음에는 컴포넌트를 구현할 때마다 스토리를 작성하는 일이 번거롭게 느껴질 수 있지만, 코드의 유지보수성과 재사용성을 위해 프로젝트에 스토리북을 도입해 보는 것을 추천한다!