아랄라랄라
R 스토리
아랄라랄라
전체 방문자
오늘
어제
  • All (208)
    • Web (153)
      • Markup | WEB (9)
      • Styles (45)
      • javascript (32)
      • jquery (28)
      • vue (16)
      • react (18)
      • more (5)
    • IT (32)
      • CS (3)
      • git hub (5)
      • UI | UX (18)
      • more (6)
    • ETC (23)
      • 이슈노트 (13)
      • 스터디 (10)
      • 아랄라 ☞☜ (0)
      • JOB🛠 (0)

인기 글

반응형
hELLO · Designed By 정상우.
아랄라랄라

R 스토리

Web/react

[Storybook] Next.js 관리자 페이지에 Storybook을 붙이면서 알게 된 핵심 개념 정리

2026. 6. 18. 13:49

 

 

Next.js로 관리자 페이지를 만들면서 Storybook을 함께 적용해보고 있다.
처음에는 단순히 “컴포넌트를 따로 볼 수 있는 도구” 정도로만 이해했는데,

직접 Alert, Dropdown, Modal 같은 컴포넌트의 Story를 만들다 보니 몇 가지 꼭 알아야 할 개념이 있었다.

이번 글에서는 Storybook을 처음 적용하면서 이해한 핵심 내용을 정리해보려고 한다.

 

 

 

 

 


 

 

 

Storybook은 페이지보다 컴포넌트를 보기 위한 도구다

Storybook은 관리자 페이지 전체를 실행하는 도구라기보다, 버튼이나 모달 같은 개별 UI 컴포넌트를 따로 꺼내서 확인하는 도구에 가깝다.

예를 들어 관리자 페이지에는 이런 컴포넌트들이 반복해서 사용된다.

Button
Badge
Alert
Modal
Dropdown
Input
Table
Pagination

 

이런 컴포넌트를 실제 페이지에 붙이기 전에 Storybook에서 먼저 확인할 수 있다.

<Button>저장</Button>
<Alert
  variant="success"
  title="완료"
  message="정상 처리되었습니다."
/>
<Modal isOpen={true} onClose={() => {}}>
  모달 내용
</Modal>

 

즉, Storybook은 “이 컴포넌트가 어떤 props를 받았을 때 어떻게 보이는지” 확인하는 공간이라고 볼 수 있다.

 

 

 

 

 


 

 

Story를 만들기 전에 props를 먼저 확인해야 한다

Storybook 파일을 만들 때 가장 먼저 확인해야 하는 것은 컴포넌트의 Props다.

예를 들어 Alert 컴포넌트가 아래와 같은 props를 받는다고 가정해보자.

interface AlertProps {
  variant: "success" | "error" | "warning" | "info";
  title: string;
  message: string;
  showLink?: boolean;
  linkHref?: string;
  linkText?: string;
}

 

여기서 중요한 것은 ? 표시다.

showLink?: boolean;

 

?가 붙어 있으면 선택값이고, 붙어 있지 않으면 필수값이다.

위 코드에서 필수 props는 아래 3개다.

variant
title
message

 

그래서 Storybook에서도 이 값들은 기본적으로 넣어줘야 한다.

args: {
  variant: "success",
  title: "처리가 완료되었습니다.",
  message: "요청한 작업이 정상적으로 완료되었습니다.",
}

 

반대로 선택 props는 필요한 Story에서만 넣으면 된다.

export const WithLink: Story = {
  args: {
    variant: "info",
    title: "추가 안내가 있습니다.",
    message: "자세한 내용은 링크를 통해 확인할 수 있습니다.",
    showLink: true,
    linkHref: "/",
    linkText: "자세히 보기",
  },
};

 

정리하면 Story를 만들 때 흐름은 다음과 같다.

컴포넌트 Props 확인
→ 필수 props 확인
→ 기본 args에 필수 props 넣기
→ 선택 props는 필요한 케이스에서만 사용

 

 

 

 

 

 


 

 

 

 

args는 컴포넌트에 전달하는 props 값이다

Storybook을 만들다 보면 args라는 값을 자주 사용하게 된다.

args: {
  variant: "success",
  title: "성공",
  message: "정상 처리되었습니다.",
}

 

처음에는 낯설 수 있지만, 어렵게 생각할 필요는 없다.
args는 컴포넌트에 넣어주는 props 값이라고 보면 된다.

위 코드는 실제로 아래처럼 컴포넌트를 사용하는 것과 비슷하다.

<Alert
  variant="success"
  title="성공"
  message="정상 처리되었습니다."
/>

 

Storybook 화면에서는 이 args 값을 Controls 패널에서 직접 바꿔볼 수도 있다.
즉, Storybook은 props 값을 바꿔가며 컴포넌트가 어떻게 변하는지 확인할 수 있게 해준다.

 

 

 

 


 

 

 

단순한 컴포넌트는 args만으로 충분하다

버튼, 배지, 알림처럼 props 값만 바꾸면 화면이 달라지는 컴포넌트는 보통 args만으로 충분하다.

예를 들어 Alert 컴포넌트의 Story는 이런 식으로 만들 수 있다.

import type { Meta, StoryObj } from "@storybook/react";
import Alert from "./Alert";

const meta = {
  title: "UI/Alert",
  component: Alert,
  tags: ["autodocs"],
  args: {
    variant: "success",
    title: "처리가 완료되었습니다.",
    message: "요청한 작업이 정상적으로 완료되었습니다.",
  },
} satisfies Meta<typeof Alert>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Success: Story = {
  args: {
    variant: "success",
    title: "처리가 완료되었습니다.",
    message: "요청한 작업이 정상적으로 완료되었습니다.",
  },
};

export const Error: Story = {
  args: {
    variant: "error",
    title: "처리 중 오류가 발생했습니다.",
    message: "입력값을 확인한 뒤 다시 시도해주세요.",
  },
};

 

이런 컴포넌트는 별도의 상태 관리가 필요하지 않기 때문에 Story 코드도 비교적 단순하다.

 

 

 

 


 

 

상태가 필요한 컴포넌트는 render를 사용한다

모든 컴포넌트가 args만으로 충분한 것은 아니다.
Modal이나 Dropdown처럼 열림/닫힘 상태가 필요한 컴포넌트는 별도의 상태 관리가 필요하다.

예를 들어 모달은 보통 아래와 같은 상태가 필요하다.

const [isOpen, setIsOpen] = useState(false);

 

이런 경우에는 render를 사용해서 Story 안에서 직접 예시 화면을 구성한다.

function DefaultModalExample() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button onClick={() => setIsOpen(true)}>
        모달 열기
      </button>

      <Modal
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
      >
        모달 내용
      </Modal>
    </>
  );
}

export const Default: Story = {
  render: () => <DefaultModalExample />,
};

 

정리하면 기준은 간단하다.

props 값만 바꾸면 되는 컴포넌트 → args 사용
클릭, 열림/닫힘, 선택값, 입력값 상태가 필요한 컴포넌트 → render 사용

 

예를 들어 다음과 같이 나눌 수 있다.

Button → args
Badge → args
Alert → args
StatusBadge → args

Modal → render
Dropdown → render
DatePicker → render
SearchFilter → render
Table → render 가능성 높음

 

 

 

 

 


 

 

 

필수 props가 있는 컴포넌트는 meta의 args를 잘 넣어야 한다

Modal이나 Dropdown을 Storybook에 올리면서 타입 오류를 만날 수 있다.
대표적으로 이런 오류다.

args 속성이 없습니다

 

이 오류는 컴포넌트에 필수 props가 있는데 Story에서 기본 args를 제공하지 않았을 때 발생할 수 있다.

예를 들어 Modal이 아래 props를 필수로 받는다고 해보자.

interface ModalProps {
  isOpen: boolean;
  onClose: () => void;
  children: React.ReactNode;
}

 

그러면 Story의 meta에도 기본 args를 넣어주는 것이 좋다.

const meta = {
  title: "UI/Modal",
  component: Modal,
  args: {
    isOpen: true,
    onClose: () => {},
    children: <div>모달 내용</div>,
  },
} satisfies Meta<typeof Modal>;

이렇게 해두면 타입 오류를 줄일 수 있다.

 

 

 

 

 


 

 

 

Modal과 Dropdown은 Storybook에서 다르게 보일 수 있다

Storybook을 쓰면서 헷갈렸던 부분 중 하나는 Modal과 Dropdown이 실제 서비스 화면과 다르게 보일 수 있다는 점이다.

실제 서비스에서는 모달이 브라우저 전체 화면 위에 뜨지만, Storybook에서는 컴포넌트가 Storybook 미리보기 영역 안에서 실행된다.

그래서 다음과 같은 문제가 생길 수 있다.

모달이 좁은 영역 안에서 열린다
드롭다운이 잘린다
높이가 부족해서 스크롤이 생긴다

 

이건 반드시 컴포넌트 코드가 잘못된 것은 아니다.
Storybook의 실행 환경 특성 때문에 생기는 경우가 많다.

이럴 때는 Storybook 설정에서 레이아웃을 넓게 잡아주는 것이 좋다.

parameters: {
  layout: "fullscreen",
}

 

그리고 Story 내부에서도 충분한 높이를 확보한다.

<div className="min-h-screen p-10">
  ...
</div>

 

드롭다운은 이런 식으로 감싸줄 수 있다.

<div className="relative h-64 w-64">
  ...
</div>

 

모달은 이런 식으로 감싸줄 수 있다.

<div className="min-h-screen bg-gray-50 p-10">
  ...
</div>

 

즉, Modal이나 Dropdown은 Storybook에서 확인하기 위해 별도의 공간 설정이 필요할 수 있다.

 

 

 

 

 

 


 

 

 

 

Storybook 파일의 기본 구조

Storybook 파일은 보통 아래 구조를 따른다.

import type { Meta, StoryObj } from "@storybook/react";
import Component from "./Component";

const meta = {
  title: "UI/Component",
  component: Component,
  tags: ["autodocs"],
  args: {
    // 기본 props
  },
} satisfies Meta<typeof Component>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
  args: {
    // 이 Story에서 보여줄 props
  },
};

 

처음에는 이 구조만 익혀도 충분하다.

상태가 필요한 컴포넌트는 여기에 render를 추가하면 된다.

function Example() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <Component
      isOpen={isOpen}
      onClose={() => setIsOpen(false)}
    />
  );
}

export const Default: Story = {
  render: () => <Example />,
};

 

 

 

 

 

 

 


 

 

 

 

정리

Storybook을 처음 적용하면서 가장 중요하다고 느낀 점은 다음과 같다.

1. Storybook은 페이지보다 컴포넌트를 보기 위한 도구다.
2. Story를 만들기 전에 props를 먼저 확인해야 한다.
3. 필수 props는 args에 반드시 넣어야 한다.
4. args는 컴포넌트에 전달하는 props 값이다.
5. 단순 컴포넌트는 args만으로 충분하다.
6. 상태가 필요한 컴포넌트는 render와 useState를 사용한다.
7. Modal과 Dropdown은 Storybook 환경에서 잘릴 수 있으므로 layout과 높이 설정이 필요하다.

 

처음부터 페이지 전체를 Storybook에 올리려고 하면 복잡해진다.
따라서 버튼, 배지, 알림, 모달, 드롭다운처럼 작은 컴포넌트부터 하나씩 만들어보는 것이 좋다.

작은 컴포넌트부터 Story를 만들어두면, 이후 관리자 페이지를 개발할 때 UI를 더 빠르게 확인하고 재사용할 수 있다.

728x90
저작자표시 (새창열림)

'Web > react' 카테고리의 다른 글

[Next.js] Next.js App Router 경계 정리표  (0) 2026.05.18
[Next.js] Next.js + TypeScript + Tailwind CSS 관리자 페이지 만들기 2  (0) 2026.05.14
[Next.js] Server vs Client Component 완전 정리  (0) 2026.05.08
[Next.js] Next.js + TypeScript + Tailwind CSS 관리자 페이지 만들기 1  (1) 2026.05.08
[Next.js] 초보의 관리자 페이지 만들기 시작기  (0) 2026.04.28

티스토리툴바