Storybook Failed to fetch dynamically imported module 해결 (Vite)

··설명 약 12분·작성: 해비·블로그 소개

Storybook에서 Failed to fetch dynamically imported module 오류가 나면 무엇을 확인하나요?

Storybook의 동적 모듈 가져오기 오류는 요청한 파일을 브라우저가 읽지 못했다는 결과입니다. Network에서 실패 URL과 404·500을 확인한 뒤 import 경로, 파일명 대소문자, Vite 변환 오류를 좁혀 보세요.

적용 조건·범위: Windows에서는 경로 대소문자 문제가 로컬에서 드러나지 않다가 Linux CI나 다른 환경에서 실패할 수 있습니다.

본문 근거: storybook.js.org/docs · storybook.js.org/docs/get-started/frameworks/nextjs-vite · storybook.js.org/docs/writing-tests/integrations/vitest-addon

독립 실습: story import 복구

export default {
  stories: ['../src/**/*.stories.js'],
  framework: '@storybook/html-vite',
};
packages:
  - "."
allowBuilds:
  esbuild@0.28.2: true
export default function TaskCard({ title = '개발환경 확인' } = {}) {
  const article = document.createElement('article');
  const heading = document.createElement('h2');
  heading.textContent = title;
  article.append(heading);
  return article;
}
import TaskCard from './components/TaskCard.js';

export default { title: 'TaskFlow/TaskCard', render: (args) => TaskCard(args) };
export const Default = { args: { title: '개발환경 확인' } };

기대 결과: 빌드가 성공하고 Storybook의 TaskCard story가 표시되는지 확인합니다. 잘못된 import 재현은 아래 변형 과제로 수행하고 기존 원문 JSX 예시는 React 경로 설명용 부분 코드로 구분합니다.

직접 실행: 환경 준비와 전체 파일

기존 앱 밖의 새 연습 폴더에 아래 파일을 그대로 저장합니다. 표시한 경로는 이 연습 폴더 기준입니다. 하단 완료 ZIP을 사용할 경우 labs/storybook-vite/ 폴더만 별도로 열어도 됩니다. 이전 TaskFlow 앱 파일은 필요하지 않습니다.

.storybook/main.js 전체 코드

package.json 전체 코드

{
  "name": "taskflow-storybook-lab",
  "private": true,
  "type": "module",
  "packageManager": "pnpm@11.19.0",
  "scripts": {
    "dev": "storybook dev -p 6006 --host 127.0.0.1 --no-open",
    "storybook": "storybook dev -p 6006 --host 127.0.0.1 --no-open",
    "build": "storybook build"
  },
  "devDependencies": {
    "vite": "8.3.0",
    "storybook": "10.6.0",
    "@storybook/html-vite": "10.6.0"
  }
}

pnpm-workspace.yaml 전체 코드

README.md 전체 코드

# Storybook lab

이 폴더에서 `pnpm install --frozen-lockfile`, `pnpm dev`, `pnpm build`를 실행합니다.

TaskCard.stories.js의 import를 ./missing/TaskCard.js로 변경하면 변환 오류를 재현할 수 있습니다. 개발 서버와 Network의 첫 실패 요청을 확인하고 ./components/TaskCard.js로 복구합니다. 이 실습은 HTML/JavaScript이며 JSX/React parser를 추가하지 않습니다.

src/components/TaskCard.js 전체 코드

src/TaskCard.stories.js 전체 코드

pnpm install
pnpm build
pnpm storybook

변형 과제: TaskCard.stories.js의 import를 존재하지 않는 파일 이름으로 바꾸어 빌드 첫 오류를 기록합니다. 원래 경로로 복구한 후 빌드와 브라우저 요청 상태를 각각 확인합니다.

오류 메시지부터 이해하기

브라우저에서 다음과 비슷한 메시지를 볼 수 있습니다.

Failed to fetch dynamically imported module

이 메시지만으로 원인을 하나로 확정할 수는 없습니다.

브라우저가 요청한 URL을 먼저 확인해야 합니다.

1. Network 탭에서 실패 요청 확인

DevTools의 Network 탭을 열고 Storybook을 새로고침합니다.

실패한 요청의 상태를 확인합니다.

404
→ 경로나 파일 존재 여부 확인

500
→ Vite transform 또는 서버 내부 오류 확인

ERR_CONNECTION...
→ 개발 서버 연결 상태 확인

Console 메시지의 마지막 줄보다 Network의 실제 요청 URL이 더 직접적인 단서가 될 수 있습니다.

2. import 경로 확인

예:

import TaskCard from '../components/TaskCard';

파일이 이동됐는데 story import만 남아 있을 수 있습니다.

src/components/TaskCard.jsx
→ src/features/tasks/TaskCard.jsx

story 파일의 상대 경로가 실제 구조와 맞는지 확인합니다.

3. 대소문자 확인

Windows에서는 경로 대소문자 문제가 로컬에서 드러나지 않다가 Linux CI나 다른 환경에서 실패할 수 있습니다.

실제 파일
TaskCard.jsx

잘못된 import
./taskcard.jsx

Git에서 파일 이름만 대소문자로 바꾼 경우 변경이 제대로 기록됐는지도 확인합니다.

4. story 파일 이동·삭제 확인

Storybook의 stories 패턴이 실제 파일과 맞는지 확인합니다.

.storybook/main.js 또는 main.ts 예시:

export default {
  stories: [
    '../src/**/*.stories.@(js|jsx|ts|tsx)',
  ],
};

파일 경로를 바꿨다면 stories glob도 함께 확인합니다.

5. Vite 자체 오류 확인

Storybook이 Vite builder를 사용한다면 Vite 변환 오류가 동적 import 실패처럼 보일 수 있습니다.

터미널 로그에서 첫 오류를 확인합니다.

문법 오류
존재하지 않는 package import
브라우저에서 실행할 수 없는 Node 전용 module
alias 설정 불일치

Storybook 공식 문서도 브라우저 환경에서 실행할 수 없는 Node 전용 import를 story가 간접적으로 가져오면 Vite build가 깨질 수 있다고 설명합니다.

화면 컴포넌트와 서버 전용 로직을 분리하는 것이 해결책이 될 수 있습니다.

서버 전용 코드를 story에서 직접 import하지 않기

잘못된 구조 예:

page component
├─ DB/API 서버 전용 코드
└─ UI 렌더링

story
└─ page component 전체 import

개선 방향:

page
├─ 서버 데이터 준비
└─ 순수 UI component 호출

story
└─ 순수 UI component만 import

Storybook은 UI 컴포넌트를 독립적으로 확인하는 도구이므로 서버 런타임 전용 의존성을 직접 끌고 오지 않는 편이 명확합니다.

6. alias 설정 확인

Vite 앱에서는 동작하지만 Storybook에서 alias를 못 찾는 경우가 있습니다.

import TaskCard from '@/components/TaskCard';

앱의 Vite 설정과 Storybook builder 설정이 같은 alias를 알고 있는지 확인합니다.

필요하다면 Storybook의 Vite 확장 설정을 사용하지만, 앱 설정을 무작정 복사하지는 않습니다.

7. addon과 framework 설정 확인

Storybook 설정을 변경한 직후부터 오류가 시작됐다면 최근 변경부터 되돌려 봅니다.

framework 변경
builder 변경
addon 추가
viteFinal 수정
stories glob 변경

한 번에 여러 설정을 바꾸면 원인을 찾기 어려워집니다.

캐시 삭제는 언제 하는가

경로와 설정이 정상인데 이전 파일을 계속 요청하는 정황이 있을 때 캐시 정리를 고려합니다.

하지만 첫 단계로 캐시를 지우면 실제 import 오류를 숨길 수 있습니다.

경로 확인
→ 설정 확인
→ 터미널 첫 오류 확인
→ 필요할 때 캐시 정리

CI에서 같은 오류가 나올 때

Storybook의 테스트 통합 환경에서는 많은 동시 테스트로 리소스가 부족할 때 비슷한 동적 import 오류가 나타날 수 있습니다.

따라서 로컬 404 오류와 CI 대량 테스트 오류를 같은 원인으로 단정하지 않습니다.

CI에서만 발생한다면 실행 병렬성, isolation, shard 같은 테스트 환경 요소도 별도로 확인합니다.

labs/storybook-vite 구성

TaskFlow 메인 앱에서 Storybook을 필수 도구로 만들지 않습니다.

labs/
└─ storybook-vite/
   ├─ .storybook/
   └─ src/

이 lab에서 일부러 잘못된 import를 만들고 Network 요청을 확인한 뒤 정상 경로로 복구합니다. 아래 완성 예제는 @storybook/html-vite와 순수 JavaScript를 사용합니다. 앞의 JSX 경로는 React 프로젝트를 설명하는 예시이며, 이 lab에 JSX 설정을 추가할 필요는 없습니다.

오류 해결 순서

1. 브라우저 Network의 첫 실패 요청
2. HTTP 상태와 요청 URL
3. import 경로
4. 파일 이름 대소문자
5. story glob
6. 터미널 Vite 오류
7. Node 전용 import 여부
8. alias
9. Storybook framework/addon 설정
10. 필요한 경우 캐시
11. CI 전용 문제라면 리소스/병렬성 분리 확인

학습 완료 체크리스트

  • dynamic import 오류를 하나의 원인으로 단정하지 않습니다.
  • Network 탭에서 실패 요청을 찾을 수 있습니다.
  • import 경로와 대소문자를 확인할 수 있습니다.
  • Storybook stories glob을 확인할 수 있습니다.
  • Node 전용 코드와 UI 컴포넌트를 분리할 수 있습니다.
  • alias와 Storybook Vite 설정을 구분할 수 있습니다.
  • 캐시 삭제를 첫 해결책으로 사용하지 않습니다.

선택 실습: 같은 프로젝트로 연습하기

TaskFlow는 작업을 관리하는 예제 앱입니다. 이 선택 실습에서는 앱을 실행·개발하는 환경과 설정을 준비합니다.

아래는 이번 회차 완료 시점의 전체 소스입니다. 파일 경로는 압축을 푼 체크포인트 폴더를 기준으로 합니다.

선택: 연재 프로젝트와 전체 자료

연재 프로젝트를 이어 만드는 분을 위한 자료입니다. 이 글의 개념과 예제만 찾으셨다면 필요한 파일과 실행 방법만 펼쳐보세요.

TaskFlow 프로젝트 적용

시작 체크포인트: 이전 글의 적용·완료 확인과 이전 회차 시작 ZIP을 기준으로 아래 변경 파일을 수정합니다. 메인 앱은 루트에서 실행하고, labs는 해당 폴더의 package.json과 잠금 파일을 기준으로 따로 실행합니다.

이전 완료본과 달라진 파일: docs/development-environment.md, README.md, labs/storybook-vite/.storybook/main.js, labs/storybook-vite/package.json, labs/storybook-vite/pnpm-workspace.yaml, labs/storybook-vite/README.md, labs/storybook-vite/src/components/TaskCard.js, labs/storybook-vite/src/TaskCard.stories.js. 전체 코드에서 같은 경로를 찾아 기존 내용을 대조합니다. ZIP의 자동 생성 lockfile도 해당 패키지 폴더와 함께 유지합니다.

다음 정도를 알고 시작합니다.

ES Module import
Vite 개발 서버
브라우저 DevTools Network
Storybook이 별도 개발 서버를 실행한다는 개념

이 글을 읽고 바로 확인할 것

독자 질문: Storybook의 동적 import 실패에서 깨진 요청과 파일 경로를 어떻게 찾나요?

얻을 결과: 브라우저 Network 실패 URL과 story의 import 경로·대소문자를 연결해 원인을 좁힐 수 있습니다.

직접 따라 할 순서

  1. Storybook을 실행해 오류를 다시 띄우고 Network에서 실패한 모듈 요청 URL을 기록합니다.
  2. story 파일의 import 경로·대소문자·alias 설정과 실제 파일을 비교합니다.
  3. 문제 경로를 수정하고 lab의 Storybook 빌드를 다시 실행합니다.

확인 결과 기준: 빌드 성공은 정적 모듈 복구 확인입니다. 브라우저 Network에서 오류가 사라졌는지는 별도 실행·확인이 필요합니다.

편집 검증 범위: 이번 보강에서 위 명령과 화면은 다시 실행하지 않았습니다(미확인). 본문 아래의 기존 실행 검증표는 이전 작업에서 기록한 결과이며, 독자는 자신의 환경에서 위 기준으로 확인해 주세요.

다음 학습: VS Code Copilot 디버깅: Agent Debug Log와 Chat Debug

이전 체크포인트

dev-env-step-08-tailwind-editor-fix

이번 변경

메인 TaskFlow 앱은 변경하지 않습니다.

labs/storybook-vite 추가
동적 import 오류 재현
Network 기반 진단
경로·대소문자·설정 복구

검증

Storybook lab에서 개발 서버를 실행합니다.

pnpm dev

또는 해당 lab에 정의된 Storybook script를 실행합니다.

pnpm storybook

복구 후 브라우저 Network에 실패한 module 요청이 남지 않는지 확인합니다.

완료 체크포인트

dev-env-step-09-storybook-vite-fix
전체 파일·코드 보기

실습 프로젝트 전체 코드

아래는 이번 회차 완료 시점의 전체 소스입니다. 파일 경로는 압축을 푼 체크포인트 폴더를 기준으로 합니다. 자동 생성되는 lockfile은 ZIP에 포함하며, node_modules·빌드 결과·실제 비밀값은 포함하지 않습니다. 메인 앱과 각 lab은 별도의 설치 범위를 유지합니다.

.gitignore

node_modules/
dist/
storybook-static/
.env.local
.env.*.local

apps/web/.env.example

VITE_API_URL=https://api.example.invalid
VITE_APP_NAME=TaskFlow

apps/web/eslint.config.js

import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import globals from 'globals';

export default defineConfig([
  { ignores: ['dist/**'] },
  js.configs.recommended,
  {
    files: ['src/**/*.js'],
    languageOptions: { globals: globals.browser },
    rules: { 'no-console': 'warn' },
  },
]);

apps/web/index.html

<!doctype html>
<html lang="ko">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>TaskFlow 개발환경</title></head>
<body><main id="app"></main><script type="module" src="/src/main.js"></script></body>
</html>

apps/web/package.json

{
  "name": "@taskflow/web",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite --host 127.0.0.1",
    "build": "vite build",
    "lint": "eslint ."
  },
  "devDependencies": {
    "vite": "8.3.0",
    "eslint": "10.11.0",
    "@eslint/js": "10.0.1",
    "globals": "17.12.0"
  }
}

apps/web/src/config/env.js

const apiUrl = import.meta.env.VITE_API_URL;
const appName = import.meta.env.VITE_APP_NAME;

if (!apiUrl) {
  throw new Error('VITE_API_URL 환경 변수가 필요합니다.');
}

export const env = {
  apiUrl,
  appName: appName || 'TaskFlow',
};

apps/web/src/main.js

import './style.css';
import { env } from './config/env.js';

const app = document.querySelector('#app');
const title = document.createElement('h1');
title.textContent = env.appName;
const status = document.createElement('p');
status.textContent = '개발환경 스타터가 실행 중입니다.';
const api = document.createElement('p');
api.id = 'api-url';
api.textContent = `API URL: ${env.apiUrl}`;
app.append(title, status, api);

apps/web/src/style.css

body { margin: 0; color: #202020; background: #f6f6f6; font: 16px/1.6 system-ui, sans-serif; }
main { max-width: 720px; margin: 64px auto; padding: 24px; }
h1 { font-size: 30px; font-weight: 500; }
p { overflow-wrap: anywhere; }

docs/development-environment.md

# TaskFlow 개발환경

이 스타터는 개발환경 진단을 위한 최소 Vite/vanilla JavaScript 앱입니다. 할 일 관리 기능이나 API 서버는 포함하지 않습니다.

Node.js 24.19.0, pnpm 11.19.0으로 검증했습니다. 루트는 pnpm만 사용하며 apps/*만 workspace입니다. labs의 npm/Yarn/pnpm 실습은 독립 프로젝트입니다.

## 2회차

메인 앱은 pnpm을 유지합니다. labs/yarn-modern은 독립 Yarn 실습입니다.

## 3회차

apps/web/.env.example을 apps/web/.env.local로 복사합니다. .invalid 주소는 표시만 하며 실제 API 호출은 하지 않습니다. 공개 샘플값만 제공하고 로컬 파일은 ZIP에서 제외합니다.

## 4회차

Vite 루트는 apps/web입니다. env.js가 필수 VITE_API_URL을 검사하고 화면에 공개 URL을 표시합니다.

## 5회차

ESLint 설정과 의존성은 apps/web에 있습니다. 루트 pnpm lint가 앱의 eslint .을 호출합니다.

## 6회차

npm ERESOLVE 실습은 labs/npm-eresolve에서 실행합니다. 최종본은 react와 react-dom 19.3.0 호환 조합입니다.

## 7회차

설치 오류는 경로 → Node/pnpm 버전 → workspace → package.json → lockfile 순으로 확인합니다. 새 폴더에서 pnpm install --frozen-lockfile로 재현합니다.

## 8회차

Tailwind lab은 독립 pnpm 프로젝트입니다. PostCSS 빌드와 VS Code 언어 모드/확장 상태를 구분합니다. VS Code GUI 경고는 이번 자동 검증 범위에 포함하지 않았습니다.

## 9회차

Storybook lab은 HTML/Vite 기반 최소 UI입니다. 잘못된 import 경로를 진단합니다. Linux 대소문자/CI 자원 문제는 이 Windows 실행으로 검증하지 않았습니다.

package.json

{
  "name": "taskflow",
  "private": true,
  "packageManager": "pnpm@11.19.0",
  "engines": {
    "node": ">=24"
  },
  "scripts": {
    "dev": "pnpm --filter @taskflow/web dev",
    "build": "pnpm --filter @taskflow/web build",
    "lint": "pnpm --filter @taskflow/web lint"
  }
}

pnpm-workspace.yaml

packages:
  - "apps/*"

README.md

# TaskFlow 개발환경 09 완료 체크포인트

Node.js 24.19.0 / pnpm 11.19.0 검증 기준입니다. pnpm을 별도로 설치한 환경에서 실행하세요. ZIP에는 node_modules, dist, 로컬 환경 변수, 실제 비밀값이 없습니다.

1. 이 폴더에서 `pnpm install --frozen-lockfile`
2. PowerShell: `Copy-Item apps/web/.env.example apps/web/.env.local` 또는 macOS/Linux: `cp apps/web/.env.example apps/web/.env.local`
3. `pnpm dev` 후 http://127.0.0.1:5173 확인
4. `pnpm build`
5. `pnpm lint`

apps/web가 Vite 루트입니다. 환경 변수도 이 폴더에 둡니다. 표시용 API 주소에 실제 요청을 보내지 않습니다. labs는 메인 workspace에서 제외되어 각 폴더에서 별도 설치합니다.

원문 단계별 전체 파일과 실행 검증 범위는 docs/development-environment.md를 확인하세요.

labs/yarn-modern/.yarnrc.yml

nodeLinker: node-modules

labs/yarn-modern/package.json

{
  "name": "taskflow-yarn-lab",
  "private": true,
  "type": "module",
  "packageManager": "yarn@4.18.0",
  "scripts": {
    "dev": "node src/main.js",
    "lint": "node --check src/main.js"
  }
}

labs/yarn-modern/src/main.js

console.log('TaskFlow Yarn 독립 실습');

labs/npm-eresolve/package.json

{
  "name": "taskflow-npm-eresolve",
  "private": true,
  "type": "module",
  "packageManager": "npm@11.16.0",
  "scripts": {
    "test": "node verify.mjs"
  },
  "dependencies": {
    "react": "19.3.0",
    "react-dom": "19.3.0"
  }
}

labs/npm-eresolve/README.md

# npm ERESOLVE 실습

이 폴더에서만 npm을 사용합니다.

오류 재현: `npm install react@18.3.1 react-dom@19.3.0 --save-exact`

복구: `npm install react@19.3.0 react-dom@19.3.0 --save-exact`

검증: `npm ls react react-dom`, `npm test`

react-dom 19.3.0의 peerDependencies는 react ^19.3.0입니다. 최종 package.json은 복구된 상태입니다.

labs/npm-eresolve/verify.mjs

import { createElement } from 'react';
import { renderToString } from 'react-dom/server';
import assert from 'node:assert/strict';
const html = renderToString(createElement('p', null, 'TaskFlow'));
assert.equal(html, '<p>TaskFlow</p>');
console.log('React 서버 렌더링 통과');

labs/tailwind-at-rule/.vscode/extensions.json

{
  "recommendations": [
    "bradlc.vscode-tailwindcss"
  ]
}

labs/tailwind-at-rule/.vscode/settings.json

{
  "files.associations": {
    "*.css": "tailwindcss"
  }
}

labs/tailwind-at-rule/index.html

<!doctype html>
<html lang="ko"><head><meta charset="UTF-8"><title>Tailwind lab</title><link rel="stylesheet" href="/src/style.css"></head><body><h1 class="text-brand text-2xl">TaskFlow Tailwind</h1></body></html>

labs/tailwind-at-rule/package.json

{
  "name": "taskflow-tailwind-lab",
  "private": true,
  "type": "module",
  "packageManager": "pnpm@11.19.0",
  "scripts": {
    "dev": "vite --host 127.0.0.1",
    "build": "vite build"
  },
  "devDependencies": {
    "vite": "8.3.0",
    "tailwindcss": "4.3.3",
    "@tailwindcss/postcss": "4.3.3",
    "postcss": "8.5.28"
  }
}

labs/tailwind-at-rule/pnpm-workspace.yaml

packages:
  - "."

labs/tailwind-at-rule/postcss.config.js

export default {
  plugins: { '@tailwindcss/postcss': {} },
};

labs/tailwind-at-rule/README.md

# Tailwind lab

이 폴더에서 `pnpm install --frozen-lockfile`, `pnpm dev`, `pnpm build`를 실행합니다.

빌드 오류 재현은 postcss.config.js의 plugin을 tailwindcss로 바꿔 확인하고, @tailwindcss/postcss로 복구합니다. VS Code에는 Tailwind CSS IntelliSense를 설치하고 이 폴더를 열어 언어 모드를 확인합니다. 전역 CSS 검사는 끄지 않습니다.

labs/tailwind-at-rule/src/style.css

@import "tailwindcss";

@theme {
  --color-brand: #111111;
}

labs/storybook-vite/.storybook/main.js

export default {
  stories: ['../src/**/*.stories.js'],
  framework: '@storybook/html-vite',
};

labs/storybook-vite/package.json

{
  "name": "taskflow-storybook-lab",
  "private": true,
  "type": "module",
  "packageManager": "pnpm@11.19.0",
  "scripts": {
    "dev": "storybook dev -p 6006 --host 127.0.0.1 --no-open",
    "storybook": "storybook dev -p 6006 --host 127.0.0.1 --no-open",
    "build": "storybook build"
  },
  "devDependencies": {
    "vite": "8.3.0",
    "storybook": "10.6.0",
    "@storybook/html-vite": "10.6.0"
  }
}

labs/storybook-vite/pnpm-workspace.yaml

packages:
  - "."
allowBuilds:
  esbuild@0.28.2: true

labs/storybook-vite/README.md

# Storybook lab

이 폴더에서 `pnpm install --frozen-lockfile`, `pnpm dev`, `pnpm build`를 실행합니다.

TaskCard.stories.js의 import를 ./missing/TaskCard.js로 변경하면 변환 오류를 재현할 수 있습니다. 개발 서버와 Network의 첫 실패 요청을 확인하고 ./components/TaskCard.js로 복구합니다. 이 실습은 HTML/JavaScript이며 JSX/React parser를 추가하지 않습니다.

labs/storybook-vite/src/components/TaskCard.js

export default function TaskCard({ title = '개발환경 확인' } = {}) {
  const article = document.createElement('article');
  const heading = document.createElement('h2');
  heading.textContent = title;
  article.append(heading);
  return article;
}

labs/storybook-vite/src/TaskCard.stories.js

import TaskCard from './components/TaskCard.js';

export default { title: 'TaskFlow/TaskCard', render: (args) => TaskCard(args) };
export const Default = { args: { title: '개발환경 확인' } };

실행 검증 결과

검증 환경: Windows · Node.js 24.19.0 · pnpm 11.19.0 · Vite 8.3.0 · ESLint 10.11.0.

항목 확인 결과
메인 앱 pnpm install --frozen-lockfile 성공
메인 앱 pnpm build 성공
메인 앱 pnpm lint 성공
Storybook lab의 잘못된 import 예상 빌드 실패 재현
정상 import 복구 후 build · frozen 설치 성공
브라우저 Network의 오류·복구 화면 미검증 · 개발 서버에서 직접 확인 필요

메인 앱의 개발 서버 응답과 환경 변수 변환은 1·4·5·11회차에서 대표 확인했습니다. 선택 lab과 에디터 기능은 위에 표시한 범위만 검증했으며, 운영 배포 검증은 포함하지 않습니다.

다음 학습

다음 글에서는 코드나 Vite가 아니라 VS Code의 AI 에이전트 자체가 이상하게 동작할 때 Agent Debug Logs와 Chat Debug를 통해 원인을 추적합니다.

다음 글: VS Code Copilot 디버깅: Agent Debug Log와 Chat Debug

공식 문서

체크포인트 다운로드

dev-env-step-09-storybook-vite-fix 완료 ZIP 다운로드

이전 회차 시작 체크포인트 ZIP

글 소개·학습 준비·전체 목차
Storybook 오류 해결을 표현한 컴포넌트와 돋보기, 곰 표지

개발환경 · 9 / 11 · 오류 해결 · Storybook과 Vite 동적 import

Storybook 화면에서 Failed to fetch dynamically imported module 오류가 보이면 “Storybook 캐시가 꼬였다”라고 바로 결론 내리기 쉽습니다.

하지만 이 메시지는 브라우저가 동적으로 요청한 모듈을 가져오지 못했다는 결과입니다. 원인은 잘못된 import 경로, 파일 이름 대소문자, 이동·삭제된 story, Vite 변환 실패, 설정 오류, CI 리소스 문제 등 여러 가지일 수 있습니다.

이번 글에서는 첫 실패 요청부터 범위를 줄이는 순서를 정리합니다.

이번 글에서 배우는 내용

  • dynamic import 오류가 의미하는 것
  • 브라우저 Network 탭 확인
  • import 경로와 파일 대소문자 확인
  • story 파일 이동·삭제 확인
  • Vite transform 오류 확인
  • Storybook main 설정 확인
  • 캐시 삭제를 마지막에 두는 이유
  • CI에서 같은 오류 문구가 나올 때 별도 원인을 고려해야 하는 이유

선수 지식

ES Module import·Vite 서버·브라우저 Network 탭을 알고 시작합니다. 아래 lab은 @storybook/html-vite 기반이며 React 앱이 필요하지 않습니다.

Node.js·pnpm 설치와 공통 실행 기준은 pnpm 환경 준비에서 확인합니다.

목차

  1. 오류 메시지부터 이해하기
  2. 1. Network 탭에서 실패 요청 확인
  3. 2. import 경로 확인
  4. 3. 대소문자 확인
  5. 4. story 파일 이동·삭제 확인
  6. 5. Vite 자체 오류 확인
  7. 서버 전용 코드를 story에서 직접 import하지 않기
  8. 6. alias 설정 확인
  9. 7. addon과 framework 설정 확인
  10. 캐시 삭제는 언제 하는가
  11. CI에서 같은 오류가 나올 때
  12. labs/storybook-vite 구성
  13. 오류 해결 순서
  14. 학습 완료 체크리스트
  15. 독립 실습: story import 복구
  16. TaskFlow 프로젝트 적용
  17. 이 글을 읽고 바로 확인할 것
  18. 실습 프로젝트 전체 코드
  19. 실행 검증 결과
  20. 다음 학습
  21. 공식 문서

이 글이 도움이 되었나요?

조회 중

읽음 기록

읽음 — / 전체 11개 · 필수 6개

이 글을 쓴 해비

웹사이트를 제작·운영하고, 개인 서비스와 자동화·AI 도구를 만듭니다. 직접 만들며 배운 내용과 문제 해결 과정을 BlogFlow에 기록합니다.

새 글 받아보기

RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.

RSS 피드 구독하기

댓글 남기기