'use strict';

var fs = require('fs');
var path = require('path');
var url = require('url');

var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var fs__default = /*#__PURE__*/_interopDefault(fs);
var path__default = /*#__PURE__*/_interopDefault(path);

// src/platform/prompts/markdown-assets.ts
var PACKAGE_JSON_FILE_NAME = "package.json";
function findPackageRoot(moduleFilePath) {
  let currentDirectoryPath = path__default.default.dirname(moduleFilePath);
  while (!fs__default.default.existsSync(path__default.default.join(currentDirectoryPath, PACKAGE_JSON_FILE_NAME))) {
    const parentDirectoryPath = path__default.default.dirname(currentDirectoryPath);
    if (parentDirectoryPath === currentDirectoryPath) {
      throw new Error(`markdown \uC790\uC0B0 package root\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. start=${moduleFilePath}`);
    }
    currentDirectoryPath = parentDirectoryPath;
  }
  return currentDirectoryPath;
}
function resolvePromptPackageFilePath(importMetaUrl, packageRelativeFilePath) {
  const moduleFilePath = url.fileURLToPath(importMetaUrl);
  const packageRoot = findPackageRoot(moduleFilePath);
  return path__default.default.normalize(path__default.default.resolve(packageRoot, packageRelativeFilePath));
}
function createPromptMarkdownFileAsset(importMetaUrl, packageRelativeFilePath) {
  return {
    filePath: resolvePromptPackageFilePath(importMetaUrl, packageRelativeFilePath),
    kind: "file-reference"
  };
}

// src/platform/assets/rules/fe/coding-convention.md
var coding_convention_default = '# \uCF54\uB529\uCEE8\uBCA4\uC158\n\n> `/gen-html`, `/gen-storybook`, `/review` \uC5D0\uC11C \uACF5\uD1B5\uC73C\uB85C \uC0AC\uC6A9\uD558\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC \uCF54\uB529 \uADDC\uCE59\uC774\uB2E4.\n\n## \uCC38\uC870 \uC870\uAC74\n\n- \uD504\uB860\uD2B8\uC5D4\uB4DC \uB9C8\uD06C\uC5C5, \uC811\uADFC\uC131, \uC778\uD130\uB799\uC158, \uC2A4\uD0C0\uC77C\uB9C1 \uADDC\uCE59\uC744 \uD655\uC778\uD574\uC57C \uD560 \uB54C \uC774 \uBB38\uC11C\uB97C \uC77D\uB294\uB2E4.\n- \uC0DD\uC131\uD558\uAC70\uB098 \uC218\uC815\uD558\uB294 \uCF54\uB4DC\uAC00 HTML/SCSS \uADDC\uCE59\uC744 \uC9C1\uC811 \uB530\uB77C\uC57C \uD560 \uB54C \uC774 \uBB38\uC11C\uB97C \uC77D\uB294\uB2E4.\n\n## \uC218\uD589 \uACC4\uC57D\n\n- \uD504\uB860\uD2B8\uC5D4\uB4DC \uCF54\uB4DC\uB97C \uC0DD\uC131\uD558\uAC70\uB098 \uC218\uC815\uD560 \uB54C\uB294 \uC774 \uBB38\uC11C\uC758 \uC2DC\uB9E8\uD2F1 \uB9C8\uD06C\uC5C5, \uC811\uADFC\uC131, \uC778\uD130\uB799\uC158, \uC2A4\uD0C0\uC77C\uB9C1 \uADDC\uCE59\uC744 \uC2E4\uC81C \uCF54\uB4DC\uC5D0 \uBC18\uC601\uD55C\uB2E4.\n- \uC608\uC2DC\uAC00 \uC788\uB294 \uD56D\uBAA9\uC740 \uAE08\uC9C0 \uC608\uC2DC\uB97C \uD53C\uD558\uACE0 \uD5C8\uC6A9 \uC608\uC2DC \uBC29\uD5A5\uC73C\uB85C \uAD6C\uD604\uD55C\uB2E4.\n\n## HTML \uCEE8\uBCA4\uC158\n\n- html doctype + html lang \uC0AC\uC6A9\n\n```html\n<!DOCTYPE html>\n<html lang="ko"></html>\n```\n\n- \uBAA8\uB4E0 \uD398\uC774\uC9C0\uC5D0 title \uC815\uC758\n\n```html\n<head>\n  <title>\uD0C0\uC774\uD2C0\uBA85</title>\n</head>\n```\n\n- header, nav, main, footer \uB4F1 \uC2DC\uBA58\uD2F1 \uC694\uC18C \uC0AC\uC6A9\n\n```html\n<!-- \u2705 -->\n<header>\n  <div>...</div>\n</header>\n```\n\n- `<button>`\uC740 `type="button"` \uBA85\uC2DC (form \uC548\uC5D0\uC11C \uC758\uB3C4\uCE58 \uC54A\uC740 submit \uBC29\uC9C0)\n\n```html\n<!-- \u2705 -->\n<button type="button">\uB2EB\uAE30</button>\n\n<!-- \u274C form \uC548\uC5D0\uC11C submit \uBC1C\uC0DD \uAC00\uB2A5 -->\n<button>\uB2EB\uAE30</button>\n```\n\n- \uD074\uB9AD\uB9CC \uD544\uC694\uD55C \uC694\uC18C\uC5D0 `<a>` \uC0AC\uC6A9 \uAE08\uC9C0 \u2014 `<button>` \uC0AC\uC6A9\n\n```html\n<!-- \u2705 -->\n<button type="button" onClick="{handleClick}">\uB354\uBCF4\uAE30</button>\n\n<!-- \u274C href \uC5C6\uB294 a \uD0DC\uADF8 -->\n<a onClick="{handleClick}">\uB354\uBCF4\uAE30</a>\n```\n\n- \uC694\uC18C \uC0AC\uC774\uC5D0 \uAC04\uACA9\uC744 br \uD0DC\uADF8\uB85C \uC0AC\uC6A9\uD558\uAE30 \uBCF4\uB2E8 div, p \uD0DC\uADF8\uC640 \uAC19\uC740 \uBE14\uB85D\uB808\uBCA8 \uD0DC\uADF8 \uC0AC\uC6A9\n\n```html\n<!-- \u274C -->\n\uC548\uB155\uD558\uC138\uC694.\n<br />\n<br />\n\uC548\uB155\uD558\uC138\uC694.\n\n<!-- \u2705  -->\n<p>\uC548\uB155\uD558\uC138\uC694.</p>\n<p>\uC548\uB155\uD558\uC138\uC694.</p>\n```\n\n- \uAC15\uC870\uC758 \uC758\uBBF8\uB294 b, i \uD0DC\uADF8 \uB300\uC2E0 strong, em \uD0DC\uADF8 \uC0AC\uC6A9(\uC2A4\uD06C\uB9B0 \uB9AC\uB354\uAE30\uC5D0\uC11C \uB354 \uAC15\uD558\uAC8C \uC77D\uC5B4\uC90C)\n\n```html\n<!-- \u274C \uC758\uBBF8 \uC5C6\uC74C -->\n<b>\uAD75\uC740 \uAE00\uC790</b>\n\n<!-- \u274C \uC758\uBBF8 \uC5C6\uC74C -->\n<i>\uC774\uD0E4\uB9AD \uAE00\uC790</i>\n\n<!-- \u2705 \uAC15\uC870\uC758 \uC758\uBBF8\uB97C \uAC16\uC74C(\uB193\uCE58\uBA74 \uC548 \uB418\uB294 \uC815\uBCF4, \uC8FC\uC758\uC0AC\uD56D \uB4F1 \uC911\uC694\uD55C \uC815\uBCF4) -->\n<strong>\uAD75\uC740 \uAE00\uC790</strong>\n\n<!-- \u2705 \uAC15\uC870\uC758 \uC758\uBBF8(\uBE44\uAD50/\uB300\uC870, \uB2AC\uC559\uC2A4 \uAC15\uC870) -->\n<em>\uC774\uD0E4\uB9AD \uAE00\uC790</em>\n```\n\n- \uBAA8\uB4E0 \uC778\uD130\uB799\uD2F0\uBE0C \uC694\uC18C\uB294 \uD0A4\uBCF4\uB4DC\uB85C \uC811\uADFC\uC774 \uB418\uC5B4\uC57C \uD55C\uB2E4.\n- \uBAA8\uB4E0 \uC774\uBBF8\uC9C0\uC5D0\uB294 alt \uC18D\uC131 \uC0AC\uC6A9, \uC7A5\uC2DD\uC6A9 \uC774\uBBF8\uC9C0\uB294 \uBE48 alt=\'\' \uC0AC\uC6A9\n\n## CSS \uCEE8\uBCA4\uC158\n\n- \uAE00\uB85C\uBC8C css\uAC00 \uC544\uB2C8\uBA74 module.scss\uB97C \uC0AC\uC6A9\uD55C\uB2E4.\n- \uC601\uC5C5\uC9C0\uC6D0 \uD504\uB860\uD2B8\uC5D4\uB4DC StyleLint\uC5D0\uC11C \uAD8C\uC7A5\uD558\uB294 rule set\uC744 \uC801\uC6A9\uD55C\uB2E4. (stylelint-config-dsp-frontend)\n\n```javascript\n// .stylelint.js\nmodule.exports = {\n  extends: [\'stylelint-config-dsp-frontend\']\n};\n```\n\n- \uAE30\uBCF8\uC801\uC73C\uB85C class \uBA85 \uC704\uC8FC\uB85C \uC2A4\uD0C0\uC77C\uB9C1\uD55C\uB2E4.\n\n```css\n/* \u2705 */\n.something {\n}\n\n/* \u26A0\uFE0F */\n#something {\n}\n\n/* \u26A0\uFE0F */\ndiv {\n}\n```\n\n- \uC758\uBBF8 \uC788\uACE0 \uC9C1\uAD00\uC801\uC778 \uC774\uB984\uC744 \uC0AC\uC6A9\uD55C\uB2E4.\n\n```css\n\u2705 .product-card {\n}\n\n\u274C .box {\n}\n\n\u274C .blue {\n}\n```\n\n- \uD074\uB798\uC2A4\uB294 \uAC04\uACB0\uD558\uAC8C, \uAE4A\uC740 \uB124\uC2A4\uD305 \uC2A4\uD0C0\uC77C\uC740 \uD53C\uD55C\uB2E4.\n\n```css\n\u2705 .product-card {\n}\n\n\u274C .div.container ul li a span {\n}\n```\n\n- variant\uAC00 \uD544\uC694\uD55C \uBD80\uBD84\uC740 -{variant or modifier}\uB97C \uBD99\uC5EC\uC11C \uC2A4\uD0C0\uC77C\uB9C1\uD55C\uB2E4.\n- \uACF5\uD1B5\uC5D0\uC11C\uB294 \uC5C4\uACA9\uD558\uAC8C. \uB098\uBA38\uC9C0\uB294 \uC790\uC720\uB86D\uAC8C \uC0AC\uC6A9\n\n```css\n.{\uCEF4\uD3EC\uB10C\uD2B8\uBA85}-{variant or modifier} {\n}\n\n/* \uC608 */\n.something-large {\n}\n.something-outline {\n}\n.something-warning {\n}\n```\n\n- \uD53C\uADF8\uB9C8 \uC0C1 \uBCC0\uC218\uB85C \uCC38\uC870\uB418\uACE0 \uC788\uB294 \uBD80\uBD84\uC740 design-system-context.scss\uB97C import \uD558\uC5EC \uC0AC\uC6A9\uD55C\uB2E4. (\uD558\uB4DC\uCF54\uB529 \uAE08\uC9C0)\n\n```scss\n@use \'@dsp-frontend/design-system-context\' as *;\n\n.something {\n  // \uC0C9\uC0C1\n  color: colors(surface-primary);\n\n  // shadow\n  box-shadow: shadow(medium);\n\n  // radius\n  border-radius: radius-basic(xlarge);\n\n  // \uC5EC\uBC31(padding \uD568\uC218\uB294 padding \uC18D\uC131\uC5D0 \uB300\uD55C \uAC12\uC774 \uC544\uB2D8)\n  padding: padding(medium);\n  margin: padding(medium);\n  gap: padding(medium);\n\n  // \uC5EC\uBC31(margin \uD568\uC218\uB294 margin \uC18D\uC131\uC5D0 \uB300\uD55C \uAC12\uC774 \uC544\uB2D8)\n  padding: margin(medium);\n  margin: margin(medium);\n  gap: margin(medium);\n\n  // \uD0C0\uC774\uD3EC\n  @include applay-typography(title1);\n}\n```\n\n- \uBC18\uC751\uD615 \uBBF8\uB514\uC5B4 \uCFFC\uB9AC\uB294 `@media`\uB97C \uC9C1\uC811 \uC791\uC131\uD558\uC9C0 \uC54A\uACE0, design-system\uC758 `media` \uBBF9\uC2A4\uC778\uC744 \uC0AC\uC6A9\uD55C\uB2E4.\n\n```scss\n@use \'@dsp-frontend/design-system-context\' as *;\n\n.something {\n  // mobile \uAE30\uBCF8 \uC2A4\uD0C0\uC77C\n  padding: 1rem;\n\n  // \u2705 tablet \uC774\uC0C1\n  @include media(tablet) {\n    padding: 2rem;\n  }\n\n  // \u2705 pc \uC774\uC0C1\n  @include media(pc) {\n    padding: 3rem;\n  }\n}\n\n// \u274C @media \uC9C1\uC811 \uC791\uC131\n.something {\n  @media (min-width: 768px) {\n    padding: 2rem;\n  }\n}\n```\n\n- SCSS nesting\uC740 **3\uB2E8\uACC4 \uC774\uB0B4**\uB85C \uC81C\uD55C\uD55C\uB2E4. (\uC120\uD0DD\uC790 \uBCF5\uC7A1\uB3C4/specificity \uC99D\uAC00 \uBC29\uC9C0)\n\n```scss\n// \u2705 2\uB2E8\uACC4\n.container {\n  .header {\n    color: colors(text-body_1);\n  }\n}\n\n// \u274C 4\uB2E8\uACC4 \uC774\uC0C1\n.container {\n  .header {\n    .title {\n      .icon {\n        color: colors(text-body_1);\n      }\n    }\n  }\n}\n```\n\n- className\uC740 \uBC18\uB4DC\uC2DC `classnames/bind` \uD328\uD134\uC73C\uB85C \uC801\uC6A9\uD55C\uB2E4. \uBB38\uC790\uC5F4 \uC9C1\uC811 \uC804\uB2EC \uAE08\uC9C0.\n- **\uC608\uC678**: \uC804\uC5ED \uC544\uD1A0\uBBF9 CSS \uD074\uB798\uC2A4(\uC608: `text-primary`, `text-secondary` \uB4F1 `global.css`/`atomic.css` \uC5D0 \uC815\uC758\uB41C \uC720\uD2F8 \uD074\uB798\uC2A4)\uB294 \uBB38\uC790\uC5F4 \uC9C1\uC811 \uC804\uB2EC \uD5C8\uC6A9.\n\n```typescript\nimport classNames from \'classnames/bind\';\nimport styles from \'./something.module.scss\';\n\nconst cx = classNames.bind(styles);\n\n// \u2705\n<div className={cx(\'root\', isActive && \'is-active\')} />\n\n// \u2705 \uC804\uC5ED \uC544\uD1A0\uBBF9 \uD074\uB798\uC2A4\uB294 \uBB38\uC790\uC5F4 \uC9C1\uC811 \uC804\uB2EC \uD5C8\uC6A9\n<span className="text-primary">\uAC15\uC870</span>\n\n// \u274C \uBAA8\uB4C8 \uC2A4\uD0C0\uC77C\uC744 \uBB38\uC790\uC5F4\uB85C \uC804\uB2EC\n<div className={styles.root} />\n<div className="root" />\n```\n\n- \uC778\uB77C\uC778 \uC2A4\uD0C0\uC77C\uC740 \uAC00\uAE09\uC801 \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uB294\uB2E4.\n\n```javascript\n<button style={{ color: \'red\' }}>...</button>\n```\n\n- !important \uC0AC\uC6A9\uC740 \uC758\uBBF8 \uADF8\uB300\uB85C \uC815\uB9D0 \uD544\uC694\uD55C \uACF3\uC774 \uC544\uB2C8\uBA74 \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uB294\uB2E4. (CSS\uC758 \uC21C\uC218\uD55C \uCCA0\uD559 \uBB34\uC2DC \uAC1C\uB150\uC774\uBBC0\uB85C)\n\n```css\n.something {\n  /* \u26A0\uFE0F \uBC18\uB4DC\uC2DC \uD544\uC694\uD55C \uC0C1\uD669\uC778\uAC00? \uD655\uC778\uD560 \uAC83. */\n  color: blue !important;\n}\n```\n\n- \uAE30\uBCF8 \uB2E8\uC704\uB294 rem, \uBB34\uC870\uAC74 \uACE0\uC815\uC774\uC5EC\uC57C\uD558\uB294 px\n\n```css\n.something {\n  /* \u2705 root font-size\uC5D0 \uB530\uB77C \uAC00\uBCC0 */\n  width: 2rem;\n\n  /* \u274C root font-size\uC5D0 \uB530\uB77C \uAC00\uBCC0 */\n  width: 32px;\n\n  /* \u2705 root font-size\uC640 \uBCC4\uAC1C\uB85C \uACE0\uC815 */\n  border-radius: 8px;\n}\n```\n\n- \uCD95\uC57D \uD45C\uD604 \uC6B0\uC120\uC73C\uB85C \uC2A4\uD0C0\uC77C\uB9C1\uD55C\uB2E4.\n\n```css\n\n.something {\n  // \u2705\n  margin: 0 20px;\n\n  // \u26A0\uFE0F \uC9C4\uC9DC \uD544\uC694\uD55C \uACBD\uC6B0\uC5D0\uB9CC\n  margin-right: 12px;\n\n  // \u274C \uC5EC\uB7EC\uAC1C \uC0AC\uC6A9\uD560 \uACBD\uC6B0 \uCD95\uC57D\uD615\uC73C\uB85C \u274C\n  margin-top: 0;\n  margin-right: 20px;\n}\n```\n\n- Mobile First\uB85C \uC2A4\uD0C0\uC77C\uB9C1\n\n```css\n\n@use \'@dsp-frontend/design-system-context\' as *;\n\n.something {\n  // \u2705 Mobile\n  color: tomato;\n\n  // \u2705 Tablet\n  @media(tablet) {\n    color: blue;\n  }\n\n  // \u2705 PC\n  @media(pc) {\n    color: yellow;\n  }\n}\n\n\n\n.something {\n  // \u274C PC\n  @media(pc) {\n    color: yellow;\n  }\n\n  // \u274C Tablet\n  @media(tablet) {\n    color: blue;\n  }\n\n  // \u274C Mobile\n  color: tomato;\n\n}\n\n```\n\n## Typescript \uCEE8\uBCA4\uC158\n\n- \uC601\uC5C5\uC9C0\uC6D0 \uD504\uB860\uD2B8\uC5D4\uB4DC ESLint\uC5D0\uC11C \uAD8C\uC7A5\uD558\uB294 rule set\uC744 \uC801\uC6A9\uD55C\uB2E4. (dsp-frontend-eslint-config-v8)\n\n```javascript\n// .eslintrc.js\nmodule.exports = {\n  extends: [\'dsp-frontend-eslint-config-v8\']\n};\n```\n\n- **[\uD544\uC218]** \uBAA8\uB4E0 \uD568\uC218\uC5D0\uB294 JSDoc\uC744 \uC791\uC131\uD55C\uB2E4. `@description`, `@param`(\uC788\uB294 \uACBD\uC6B0), `@returns`(\uC788\uB294 \uACBD\uC6B0) \uD3EC\uD568.\n\n```typescript\n// \u2705 \uD30C\uB77C\uBBF8\uD130\uC640 \uBC18\uD658\uAC12\uC774 \uC788\uB294 \uD568\uC218\n/**\n * @description \uC0AC\uC6A9\uC790 \uC774\uB984\uC744 \uD3EC\uB9F7\uD305\uD558\uC5EC \uBC18\uD658\uD55C\uB2E4.\n * @param firstName \uC774\uB984\n * @param lastName \uC131\n * @returns \uD3EC\uB9F7\uD305\uB41C \uC804\uCCB4 \uC774\uB984\n */\nconst formatUserName = (firstName: string, lastName: string): string => {\n  return `${lastName} ${firstName}`;\n}\n\n// \u2705 \uD30C\uB77C\uBBF8\uD130\uB9CC \uC788\uB294 \uD568\uC218 (@returns \uC0DD\uB7B5)\n/**\n * @description \uC0AC\uC6A9\uC790 \uC815\uBCF4\uB97C \uC11C\uBC84\uC5D0 \uC800\uC7A5\uD55C\uB2E4.\n * @param user \uC800\uC7A5\uD560 \uC0AC\uC6A9\uC790 \uC815\uBCF4\n */\nconst saveUser = async (user: UserInfo): Promise<void> => { ... }\n\n// \u2705 \uD30C\uB77C\uBBF8\uD130\uAC00 \uC5C6\uB294 \uD568\uC218 (@param \uC0DD\uB7B5)\n/**\n * @description \uD604\uC7AC \uB85C\uADF8\uC778\uD55C \uC0AC\uC6A9\uC790 \uC815\uBCF4\uB97C \uBC18\uD658\uD55C\uB2E4.\n * @returns \uB85C\uADF8\uC778\uD55C \uC0AC\uC6A9\uC790 \uC815\uBCF4. \uBBF8\uB85C\uADF8\uC778 \uC2DC null\n */\nconst getCurrentUser = (): UserInfo | null => { ... }\n```\n\n- `any` \uC0AC\uC6A9 \uAE08\uC9C0 \u2014 `unknown` + \uD0C0\uC785 \uAC00\uB4DC\uB85C \uB300\uCCB4\uD55C\uB2E4.\n\n```typescript\n// \u2705 unknown + \uD0C0\uC785 \uAC00\uB4DC\nconst parseResponse = (data: unknown): UserInfo => {\n  if (!isUserInfo(data)) throw new Error(\'Invalid data\');\n  return data;\n};\n\n// \u274C any\nconst parseResponse = (data: any): UserInfo => {\n  return data;\n};\n```\n\n- `React.FC<Props>` \uC0AC\uC6A9 \uAE08\uC9C0 \u2014 Props \uD0C0\uC785\uC744 \uC9C1\uC811 \uBA85\uC2DC\uD55C\uB2E4.\n\n```typescript\n// \u2705 \uC9C1\uC811 \uD0C0\uC785 \uBA85\uC2DC\nconst UserName = ({ name }: UserNameProps) => {\n  return <span>{name}</span>;\n};\n\n// \u274C FC \uC0AC\uC6A9\nconst UserName: React.FC<UserNameProps> = ({ name }) => {\n  return <span>{name}</span>;\n};\n```\n\n- optional chaining (`?.`) \uB0A8\uC6A9 \uC9C0\uC591 \u2014 \uC2E4\uC81C\uB85C null/undefined\uC77C \uC218 \uC5C6\uB294 \uACF3\uC5D0\uB294 \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uB294\uB2E4.\n\n```typescript\n// \u2705 \uD0C0\uC785\uC0C1 \uD56D\uC0C1 \uC874\uC7AC\uD558\uB294 \uAC12\nconst name = user.name;\n\n// \u274C \uBD88\uD544\uC694\uD55C optional chaining (user\uAC00 \uD56D\uC0C1 \uC874\uC7AC\uD558\uB294 \uACBD\uC6B0)\nconst name = user?.name;\n```\n\n- type assertion (`as`) \uC9C0\uC591 \u2014 \uD0C0\uC785 \uAC00\uB4DC\uB97C \uC6B0\uC120 \uC0AC\uC6A9\uD55C\uB2E4.\n\n```typescript\n// \u2705 \uD0C0\uC785 \uAC00\uB4DC\nif (isButtonElement(element)) {\n  element.disabled = true;\n}\n\n// \u274C as\uB85C \uAC15\uC81C \uCE90\uC2A4\uD305\n(element as HTMLButtonElement).disabled = true;\n```\n\n- \uC8FC\uC11D\uC740 TypeScript\uC640 \uAD00\uB828\uB41C \uAC83\uB4E4\uC740 /\\*\\* \\*/ \uB85C \uC791\uC131\uD55C\uB2E4. (\uC0C1\uC138\uD558\uBA74 \uC88B\uC74C)\n- \\*\\* \uD2B9\uD788 \uD0C0\uC785\uC758 \uACBD\uC6B0 \uD544\uB4DC\uAC00 \uB9CE\uC544\uC9C0\uB294 \uACBD\uC6B0 \uC8FC\uC11D\uC774 \uC5C6\uC73C\uBA74 \uB09C\uD574\uD574\uC9D0\n\n```typescript\n// \u2705 \uC8FC\uC11D\uC0AC\uC6A9\n/**\n * \uC0AC\uC6A9\uC790\uC815\uBCF4\n */\ninterface IUserInfo {\n  /** \uC0AC\uC6A9\uC790 \uC774\uB984 */\n  name: string;\n}\n\n// \u274C \uC8FC\uC11D \uBBF8\uC0AC\uC6A9\ninterface IUserInfo {\n  name: string;\n}\n\n/** http \uC0C1\uD0DC */\ntype HttpStatus = \'success\' | \'error\';\n```\n\n- export\n- \uAE30\uBCF8 named export \uC0AC\uC6A9 (\uC0AC\uC720: \uC790\uB3D9\uC644\uC131 / \uD2B8\uB9AC\uC138\uC774\uD0B9 \uCD5C\uC801\uD654 / \uBA85\uD655\uD55C \uAD6C\uC870)\n- Framework\uC5D0\uC11C export default \uAC15\uC81C\uD654\uD558\uB294 \uBD80\uBD84\uB9CC \uC0AC\uC6A9\n- \uC774\uC288\uAC00 \uBC1C\uC0DD\uC2DC "import/de-default-export" \uB9B0\uD2B8 \uB8F0\uC744 \uC801\uC6A9\uD560 \uC218 \uC788\uC74C\n\n```typescript\n// \u2705 \uD568\uC218\nexport getUserName = () => {...}\n\n// \u2705 \uCEF4\uD3EC\uB10C\uD2B8\nexport UserName = () => {...}\n\n// \u26A1\uFE0F Page \uCEF4\uD3EC\uB10C\uD2B8 (framework\uC5D0\uC11C \uAC15\uC81C\uD558\uB294 \uBD80\uBD84)\nexport default function Page(){...}\n```\n\n- import\n- import/order ESLint\uC758 \uAD8C\uC7A5\uC0AC\uD56D\uC5D0 \uB530\uB978\uB2E4.\n- \uB514\uC2A4\uD2B8\uB7ED\uCC98\uB9C1\n- \uD2B9\uBCC4\uD55C \uC870\uAC74\uC774 \uC5C6\uB294 \uACBD\uC6B0 \uAC1D\uCCB4\uC640 \uBC30\uC5F4\uC758 \uB514\uC2A4\uD2B8\uB7ED\uCC98\uB9C1\uC744 \uC0AC\uC6A9\uD55C\uB2E4.\n\n```javascript\nconst user = { name: \'\uAE40\uD55C\uD654\', age: 30 };\nconst numbers = [1, 2, 3, 4, 5];\n\n// \u2705\nconst { name, age } = user;\n\n// \u274C\nconst name = user.name;\nconst age = user.age;\n\n// \u2705\nconst [first, second] = numbers;\n\n// \u274C\nconst first = numbers[0];\nconst second = numbers[1];\n```\n\n## React Component \uCEE8\uBCA4\uC158\n\n### \uAE30\uBCF8 \uC6D0\uCE59\n\n- \uB2E8\uC77C \uCC45\uC784\uC744 \uC644\uC218\uD558\uB294 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB9CC\uB4E4 \uAC83 (\uD2B9\uD788, \uACF5\uD1B5 \uCEF4\uD3EC\uB10C\uD2B8)\n- YAGNI \uC6D0\uCE59 (\uC9C0\uAE08 \uD544\uC694\uD55C \uAC83\uB9CC \uAD6C\uD604) & \uC810\uC9C4\uC801 \uAC1C\uC120\n- \uCC45\uC784\uC774 \uC5EC\uB7EC \uAC1C\uBA74 \uCC45\uC784 \uAC1C\uC218\uB9CC\uD07C \uBD84\uB9AC\n- props\uAC00 \uAC70\uB300\uD574\uC9C0\uB294 \uAC83 \uC9C0\uC591\n- \uACF5\uD1B5 \uCEF4\uD3EC\uB10C\uD2B8\uAC00 \uC544\uB2CC \uAC83\uB4E4\uC740 \uD398\uC774\uC9C0 \uB2E8\uC704\uB85C \uAC1C\uBC1C (\uBC18\uBCF5 \uC0AC\uC6A9 \uC2DC \uACF5\uD1B5\uD654)\n- **God \uCEF4\uD3EC\uB10C\uD2B8/\uD568\uC218 \uC9C0\uC591** \u2014 \uD558\uB098\uC758 \uD30C\uC77C\uC5D0 \uBAA8\uB4E0 \uB85C\uC9C1\uC744 \uBAB0\uC544\uB123\uC9C0 \uC54A\uB294\uB2E4\n\n```tsx\n// \u2705 Compound \u2014 props\uAC00 \uCEE4\uC9C8 \uB54C \uBD84\uB9AC\n<Alert.Root>\n  <Alert.Indicator />\n  <Alert.Content>\n    <Alert.Title />\n    <Alert.Description />\n  </Alert.Content>\n</Alert.Root>\n\n// \u26A0\uFE0F \uBAA8\uB4E0 \uAC78 \uD558\uB098\uC5D0 \uB2F4\uC74C\n<Alert />\n```\n\n### \uD568\uC218 \uC120\uC5B8\n\n- \uCEF4\uD3EC\uB10C\uD2B8/\uD568\uC218 \uBAA8\uB450 \uD654\uC0B4\uD45C \uD568\uC218 \uAE30\uBCF8 (framework \uAC15\uC81C \uBD80\uBD84 \uC81C\uC678)\n- \uD568\uC218\uD615 \uCEF4\uD3EC\uB10C\uD2B8\uB9CC \uC0AC\uC6A9. \uD074\uB798\uC2A4\uD615\uC740 \uB0B4\uC7A5 \uCEF4\uD3EC\uB10C\uD2B8 \uC0C1\uC18D \uC6A9\uB3C4\uB85C\uB9CC.\n\n```tsx\n// \u2705 \uCEF4\uD3EC\uB10C\uD2B8\nconst UserName = () => { return <>...</> }\n\n// \u2705 \uC21C\uC218 \uD568\uC218\nconst getUserName = () => { ... }\n\n// \u2611\uFE0F Page \uCEF4\uD3EC\uB10C\uD2B8 (framework \uAC15\uC81C)\nexport default function Page() { ... }\n```\n\n### Props\n\n- \uD0C0\uC785\uC744 \uC815\uC758\uD558\uC5EC \uC0AC\uC6A9\uD55C\uB2E4. \uCEF4\uD3EC\uB10C\uD2B8\uBA85 + `Props` \uC811\uBBF8\uC0AC.\n- \uC678\uBD80 \uC0AC\uC6A9\uC774 \uD544\uC694\uD55C \uD0C0\uC785\uC740 \uBCC4\uB3C4\uC758 \uD30C\uC77C(`.types.ts`)\uC5D0\uC11C export \uD55C\uB2E4.\n\n```typescript\n/** \uC0AC\uC6A9\uC790 \uC774\uB984 \uCEF4\uD3EC\uB10C\uD2B8 Props */\ninterface UserNameProps {\n  /** \uC81C\uCD9C \uD578\uB4E4\uB7EC */\n  onUserNameSubmit: () => void;\n}\n\nconst UserName = ({ onUserNameSubmit }: UserNameProps) => { return <>...</> }\n```\n\n### \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC \uB124\uC774\uBC0D\n\n- Props\uB85C \uC804\uB2EC: `on*` \uC811\uB450\uC0AC\n- \uCEF4\uD3EC\uB10C\uD2B8 \uB0B4\uBD80: `handle*` \uC811\uB450\uC0AC\n\n```tsx\n// \u2705 \uB0B4\uBD80 \uD578\uB4E4\uB7EC\nconst handleModalClose = () => { ... };\nconst handleUserNameClick = () => { ... };\n\n// \u2705 Props\uB85C \uC804\uB2EC\n<UserName\n  onUserNameClick={handleUserNameClick}\n  onModalClose={handleModalClose}\n/>\n```\n\n### Container / View \uBD84\uB9AC\n\n- `xxx.tsx` (container) \u2014 \uC0C1\uD0DC, \uB85C\uC9C1, \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\n- `xxx.view.tsx` (view) \u2014 \uB9C8\uD06C\uC5C5, className, props \uB80C\uB354\uB9C1\uB9CC\n\n### \uC870\uAC74\uBD80 \uB80C\uB354\uB9C1\n\n```tsx\n// \u2705 \uB2E8\uC21C \uD45C\uC2DC/\uBBF8\uD45C\uC2DC \u2014 && \uC0AC\uC6A9\n{\n  isVisible && <Tooltip />;\n}\n\n// \u2705 \uB450 \uAC00\uC9C0 \uBD84\uAE30 \u2014 \uC0BC\uD56D \uC0AC\uC6A9\n{\n  isLoggedIn ? <UserMenu /> : <LoginButton />;\n}\n\n// \u274C && \uC5D0\uC11C falsy \uAC12(0, \'\') \uC8FC\uC758 \u2014 boolean\uC73C\uB85C \uBCC0\uD658\n{\n  items.length > 0 && <ItemList />;\n} // \u2705\n{\n  items.length && <ItemList />;\n} // \u274C 0\uC774 \uB80C\uB354\uB9C1\uB428\n```\n\n### key prop\n\n- \uB9AC\uC2A4\uD2B8 \uB80C\uB354\uB9C1 \uC2DC `index`\uB97C key\uB85C \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uB294\uB2E4. \uACE0\uC720\uD55C \uC2DD\uBCC4\uC790\uB97C \uC0AC\uC6A9\uD55C\uB2E4.\n\n```tsx\n// \u2705 \uACE0\uC720 id \uC0AC\uC6A9\n{\n  users.map((user) => <UserCard key={user.id} user={user} />);\n}\n\n// \u274C index \uC0AC\uC6A9\n{\n  users.map((user, index) => <UserCard key={index} user={user} />);\n}\n```\n\n### page \uCEF4\uD3EC\uB10C\uD2B8\n\n- Page \uD30C\uC77C \uC790\uCCB4\uAC00 \uBCF5\uC7A1\uD574\uC9C0\uB294 \uAC83\uC744 \uC9C0\uC591\n\n```tsx\nimport { ContractsPageContainer } from \'@/page-container/contracts/contracts-page-container\';\n\nexport default function Page() {\n  return <ContractsPageContainer />;\n}\n```\n\n### \uBA54\uBAA8\uC774\uC81C\uC774\uC158\n\n- `useMemo`, `useCallback`, `React.memo`\uB294 \uC2E4\uC81C \uC131\uB2A5 \uBB38\uC81C\uAC00 \uC788\uC744 \uB54C\uB9CC \uC0AC\uC6A9\uD55C\uB2E4.\n- \uBAA8\uB4E0 \uAC12/\uD568\uC218\uC5D0 \uBB34\uC870\uAC74 \uAC10\uC2F8\uB294 \uACFC\uB3C4\uD55C \uBA54\uBAA8\uC774\uC81C\uC774\uC158\uC744 \uC790\uC81C\uD55C\uB2E4.\n\n```tsx\n// \u274C \uBD88\uD544\uC694\uD55C \uBA54\uBAA8\uC774\uC81C\uC774\uC158\nconst userName = useMemo(() => `${firstName} ${lastName}`, [firstName, lastName]);\nconst handleClick = useCallback(() => {\n  setIsOpen(true);\n}, []);\n\n// \u2705 \uB2E8\uC21C \uC5F0\uC0B0\uC740 \uADF8\uB0E5 \uC0AC\uC6A9\nconst userName = `${firstName} ${lastName}`;\nconst handleClick = () => {\n  setIsOpen(true);\n};\n```\n\n### \uBAA8\uB2EC \uC0AC\uC6A9\n\n- \uAC04\uB2E8\uD55C \uC54C\uB9BC/\uD655\uC778 \uBAA8\uB2EC\uC740 `ModalUtils.alert`, `ModalUtils.confirm`\uC744 \uC0AC\uC6A9\uD55C\uB2E4.\n\n```typescript\n// \u2705 \uAC04\uB2E8\uD55C \uC54C\uB9BC\nModalUtils.alert(\'\uC800\uC7A5\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\');\n\n// \u2705 \uD655\uC778/\uCDE8\uC18C\nModalUtils.confirm(\'\uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?\');\n```\n\n---\n\n## \uC811\uADFC\uC131 \uAC00\uC774\uB4DC\n\n### \uAE30\uBCF8 \uC6D0\uCE59\n\n- [WCAG 2.1 AA](https://www.w3.org/TR/WCAG21/) \uAE30\uC900\uC744 \uBAA9\uD45C\uB85C \uD55C\uB2E4.\n- \uBAA8\uB4E0 \uC778\uD130\uB799\uD2F0\uBE0C \uC694\uC18C\uB294 **\uD0A4\uBCF4\uB4DC\uB85C \uC811\uADFC\xB7\uC870\uC791** \uAC00\uB2A5\uD574\uC57C \uD55C\uB2E4.\n- \uC2A4\uD06C\uB9B0 \uB9AC\uB354 \uC0AC\uC6A9\uC790\uAC00 \uCF58\uD150\uCE20\uB97C \uC774\uD574\uD560 \uC218 \uC788\uB3C4\uB85D **\uC2DC\uBA58\uD2F1 HTML**\uC744 \uC6B0\uC120 \uC0AC\uC6A9\uD55C\uB2E4.\n\n---\n\n### \uC2DC\uBA58\uD2F1 \uB9C8\uD06C\uC5C5\n\n```html\n<!-- \u2705 \uC2DC\uBA58\uD2F1 \uC694\uC18C \uC0AC\uC6A9 -->\n<nav aria-label="\uBA54\uC778 \uB124\uBE44\uAC8C\uC774\uC158">...</nav>\n<main>...</main>\n<button type="button">\uB2EB\uAE30</button>\n\n<!-- \u274C div\uB85C \uB300\uCCB4 -->\n<div onClick="{handleClick}">\uB2EB\uAE30</div>\n```\n\n- \uD074\uB9AD \uAC00\uB2A5\uD55C \uC694\uC18C\uB294 `<button>` \uB610\uB294 `<a>`\uB97C \uC0AC\uC6A9\uD55C\uB2E4.\n- `<div>`, `<span>`\uC5D0 onClick\uB9CC \uBD99\uC774\uC9C0 \uC54A\uB294\uB2E4.\n\n---\n\n### \uC774\uBBF8\uC9C0 & \uC544\uC774\uCF58\n\n```tsx\n// \u2705 \uC758\uBBF8 \uC788\uB294 \uC774\uBBF8\uC9C0 \u2014 \uC124\uBA85\uD558\uB294 alt\n<img src="/profile.png" alt="\uC0AC\uC6A9\uC790 \uD504\uB85C\uD544 \uC0AC\uC9C4" />\n\n// \u2705 \uC7A5\uC2DD\uC6A9 \uC774\uBBF8\uC9C0 \u2014 \uBE48 alt\n<img src="/divider.png" alt="" />\n\n// \u2705 \uC544\uC774\uCF58 \uBC84\uD2BC \u2014 aria-label \uD544\uC218\n<button aria-label="\uB2EB\uAE30">\n  <IconSubUiClose />\n</button>\n```\n\n---\n\n### \uD3FC \uC694\uC18C\n\n- \uBAA8\uB4E0 \uC785\uB825 \uC694\uC18C\uC5D0 `<label>` \uB610\uB294 `aria-label`\uC744 \uC81C\uACF5\uD55C\uB2E4.\n- \uC5D0\uB7EC/\uB3C4\uC6C0\uB9D0\uC740 `aria-describedby`\uB85C \uC5F0\uACB0\uD55C\uB2E4.\n\n```tsx\n// \u2705 label \uC5F0\uACB0\n<label htmlFor="user-name">\uC774\uB984</label>\n<input id="user-name" type="text" />\n\n// \u2705 \uC5D0\uB7EC \uBA54\uC2DC\uC9C0 \uC5F0\uACB0\n<input id="email" aria-describedby="email-error" aria-invalid={hasError} />\n{hasError && <span id="email-error" role="alert">\uC62C\uBC14\uB978 \uC774\uBA54\uC77C\uC744 \uC785\uB825\uD558\uC138\uC694.</span>}\n```\n\n---\n\n### \uD0A4\uBCF4\uB4DC \uC811\uADFC\uC131\n\n| \uC694\uC18C            | \uAE30\uB300 \uB3D9\uC791                                      |\n| --------------- | ---------------------------------------------- |\n| \uBC84\uD2BC, \uB9C1\uD06C      | `Tab`\uC73C\uB85C \uD3EC\uCEE4\uC2A4, `Enter`/`Space`\uB85C \uC2E4\uD589       |\n| \uBAA8\uB2EC            | \uC5F4\uB9B4 \uB54C \uD3EC\uCEE4\uC2A4 \uC774\uB3D9, `Esc`\uB85C \uB2EB\uAE30, \uD3EC\uCEE4\uC2A4 \uD2B8\uB7A9 |\n| \uB4DC\uB86D\uB2E4\uC6B4/\uC140\uB809\uD2B8 | `Arrow` \uD0A4\uB85C \uD56D\uBAA9 \uC774\uB3D9, `Enter`\uB85C \uC120\uD0DD         |\n| \uD0ED              | `Arrow` \uD0A4\uB85C \uD0ED \uC804\uD658                           |\n\n- `tabIndex={0}`\uC740 \uB124\uC774\uD2F0\uBE0C \uD3EC\uCEE4\uC2A4\uAC00 \uC5C6\uB294 \uC694\uC18C\uC5D0\uB9CC \uC0AC\uC6A9\uD55C\uB2E4.\n- `tabIndex={-1}`\uC740 \uD504\uB85C\uADF8\uB798\uBC0D\uC801 \uD3EC\uCEE4\uC2A4 \uC774\uB3D9 \uC6A9\uB3C4\uB85C\uB9CC \uC0AC\uC6A9\uD55C\uB2E4.\n- `tabIndex > 0`\uC740 \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uB294\uB2E4.\n\n---\n\n### ARIA \uC0AC\uC6A9 \uADDC\uCE59\n\n- **\uCCAB \uBC88\uC9F8 \uADDC\uCE59**: \uB124\uC774\uD2F0\uBE0C HTML \uC694\uC18C\uB85C \uD574\uACB0 \uAC00\uB2A5\uD558\uBA74 ARIA\uB97C \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uB294\uB2E4.\n- `aria-label`, `aria-labelledby`: \uC2DC\uAC01\uC801 \uB808\uC774\uBE14\uC774 \uC5C6\uB294 \uC694\uC18C\uC5D0 \uC0AC\uC6A9\n- `aria-live="polite"`: \uB3D9\uC801 \uCF58\uD150\uCE20 \uBCC0\uACBD \uC54C\uB9BC (\uD1A0\uC2A4\uD2B8, \uB85C\uB529 \uC0C1\uD0DC \uB4F1)\n\n```tsx\n// \u2705 \uB124\uC774\uD2F0\uBE0C HTML\uB85C \uCDA9\uBD84\uD558\uBA74 ARIA \uBD88\uD544\uC694\n<button>\uC800\uC7A5</button>\n\n// \u2705 \uB124\uC774\uD2F0\uBE0C\uB85C \uD45C\uD604 \uBD88\uAC00\uD560 \uB54C\uB9CC ARIA \uC0AC\uC6A9\n<div role="tablist">\n  <button role="tab" aria-selected={isActive}>\uD0ED 1</button>\n</div>\n\n// \u274C \uBD88\uD544\uC694\uD55C ARIA\n<button role="button">\uC800\uC7A5</button>\n```\n\n---\n\n### \uC0C9\uC0C1 & \uB300\uBE44\n\n- \uD14D\uC2A4\uD2B8\uC640 \uBC30\uACBD\uC758 \uBA85\uC554\uBE44 **4.5:1 \uC774\uC0C1** (\uC77C\uBC18 \uD14D\uC2A4\uD2B8), **3:1 \uC774\uC0C1** (\uD070 \uD14D\uC2A4\uD2B8 18px+)\n- \uC0C9\uC0C1\uB9CC\uC73C\uB85C \uC815\uBCF4\uB97C \uC804\uB2EC\uD558\uC9C0 \uC54A\uB294\uB2E4 (\uC5D0\uB7EC \uD45C\uC2DC \uC2DC \uC0C9\uC0C1 + \uC544\uC774\uCF58/\uD14D\uC2A4\uD2B8 \uBCD1\uD589)\n- `design-system-context`\uC758 \uD1A0\uD070\uC744 \uC0AC\uC6A9\uD558\uBA74 \uAE30\uBCF8\uC801\uC73C\uB85C \uCDA9\uC871\uB428\n';

// src/platform/assets/rules/fe/naming-rule.md
var naming_rule_default = "# \uBA85\uBA85\uADDC\uCE59\n\n> `/gen-html`, `/gen-storybook`, `/review` \uC5D0\uC11C \uACF5\uD1B5\uC73C\uB85C \uC0AC\uC6A9\uD558\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC \uB124\uC774\uBC0D \uADDC\uCE59\uC774\uB2E4.\n\n## \uCC38\uC870 \uC870\uAC74\n\n- \uD30C\uC77C\uBA85, \uCEF4\uD3EC\uB10C\uD2B8\uBA85, \uD568\uC218\uBA85, \uBCC0\uC218\uBA85, \uD0C0\uC785\uBA85 \uADDC\uCE59\uC744 \uD655\uC778\uD574\uC57C \uD560 \uB54C \uC774 \uBB38\uC11C\uB97C \uC77D\uB294\uB2E4.\n- \uC0C8 \uC774\uB984\uC744 \uC815\uD574\uC57C \uD558\uAC70\uB098 \uAE30\uC874 \uC774\uB984\uC744 \uAD50\uC815\uD574\uC57C \uD560 \uB54C \uC774 \uBB38\uC11C\uB97C \uC77D\uB294\uB2E4.\n\n## \uC218\uD589 \uACC4\uC57D\n\n- \uD30C\uC77C\uBA85, \uCEF4\uD3EC\uB10C\uD2B8\uBA85, \uD568\uC218\uBA85, \uBCC0\uC218\uBA85, \uD0C0\uC785\uBA85\uC740 \uAC00\uB2A5\uD55C \uD55C \uC774 \uBB38\uC11C \uD45C\uAE30\uBC95\uC744 \uADF8\uB300\uB85C \uB530\uB978\uB2E4.\n- \uAE30\uC874 \uC800\uC7A5\uC18C \uAD00\uB840\uC640 \uCDA9\uB3CC\uD558\uC9C0 \uC54A\uB294 \uD55C, \uC784\uC758 \uC57D\uC5B4\xB7\uCD95\uC57D\uD615\xB7\uC608\uC678 \uB124\uC774\uBC0D\uC744 \uC0C8\uB85C \uB9CC\uB4E4\uC9C0 \uC54A\uB294\uB2E4.\n\n## \uAE30\uBCF8 \uBA85\uBA85 \uADDC\uCE59\n\n| \uAD6C\uBD84                       | \uD45C\uAE30\uBC95           | \uC608                            |\n| :------------------------- | :--------------- | :---------------------------- |\n| 1. \uD504\uB85C\uC81D\uD2B8\uBA85              | kebab case       | hli-nxl-dsp-{\uC5C5\uBB34\uAD6C\uBD84\uCF54\uB4DC}-fe |\n| 2. \uACBD\uB85C\uBA85(pathname \uD3EC\uD568)   | kebab case       | /user-info/user-name          |\n| 3. \uCEF4\uD3EC\uB10C\uD2B8 \uD568\uC218\uBA85         | Pascal case      | UserName                      |\n| 4. \uD074\uB798\uC2A4\uBA85 / \uB124\uC784\uC2A4\uD398\uC774\uC2A4 | Pascal case      | DataUtil, StringUtil          |\n| 5. \uD568\uC218\uBA85(\uC77C\uBC18)            | camel case       | getUserName                   |\n| 6. \uBCC0\uC218\uBA85(\uC77C\uBC18)            | camel case       | userName                      |\n| 7. \uC0C1\uC218\uBA85                  | upper snake case | BASE_URL                      |\n| 8. type\uBA85                  | Pascal case      | NetworkStatus                 |\n| 9. interface\uBA85             | Pascal case      | UserName, ProductName         |\n| 10. enum                   | Pascal case      |                               |\n\n## \uD30C\uC77C \uBA85\uBA85 \uADDC\uCE59\n\n| \uAD6C\uBD84         | \uD45C\uAE30\uBC95             | \uD655\uC7A5\uC790        | \uC608                                                                                      |\n| :----------- | :----------------- | :------------ | :-------------------------------------------------------------------------------------- |\n| 1. \uCEF4\uD3EC\uB10C\uD2B8  | kebab case         | .tsx          | user-name.tsx                                                                           |\n| 2. \uCEE4\uC2A4\uD140 \uD6C5 | kebab case         | .tsx          | use-user-name.tsx                                                                       |\n| 3. \uC2A4\uD0C0\uC77C    | kebab case         | .scss or .css | user-name.module.scss<br>global.css                                                     |\n| 4. \uC2A4\uD1A0\uB9AC\uBD81  | kebab case or \uD55C\uAE00 | .stories.tsx  | user-name.stories.tsx or 1\\_\uAC1C\uC778\uC815\uBCF4\uCC98\uB9AC\uB3D9\uC758.stories.tsx<br>(\uAD00\uB9AC\uD558\uAE30 \uC26C\uC6B4 \uB124\uC774\uBC0D)      |\n| 5. \uC720\uD2F8\uB9AC\uD2F0  | kebab case         | .ts           | user-name-utils.ts<br>{\uC720\uD2F8\uB9AC\uD2F0\uBA85}-utils.ts                                             |\n| 6. \uD0C0\uC785      | kebab case         | .ts           | user-name.types.ts<br>{\uC774\uB984}.types.ts<br>(\uC678\uBD80 \uC0AC\uC6A9\uC774 \uD544\uC694\uD55C \uBD80\uBD84\uC740 \uBCC4\uB3C4\uC758 \uD30C\uC77C\uB85C \uBD84\uB9AC) |\n| 7. dto \uD0C0\uC785  | kebab case         | .ts           | user-name.dto.ts<br>{\uBC31\uC5D4\uB4DC \uC8FC\uC81C\uC601\uC5ED\uBA85}.dto.ts                                          |\n| 8. declare   | kebab case         | .d.ts         | user-name.d.ts                                                                          |\n\n- \uB9AC\uC561\uD2B8\uC640 \uAD00\uB828\uB41C \uAC83\uB4E4\uC740 .tsx\uB85C \uD1B5\uC77C (\uCEE4\uC2A4\uD140 \uD6C5, \uCEE8\uD14D\uC2A4\uD2B8 \uB4F1)\n\n## \uCEF4\uD3EC\uB10C\uD2B8 \uBA85\uBA85 \uADDC\uCE59\n\n- \uD45C\uAE30\uBC95: Pascal case\n- \uB2E8\uC77C \uCC45\uC784 \uC6D0\uCE59\uC744 \uAE30\uBC18\uC73C\uB85C \uD55C \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984(\uD2B9\uD788 \uACF5\uD1B5)\n- \uC22B\uC790, \uD2B9\uC218\uBB38\uC790 \uC0AC\uC6A9 X, \uC758\uBBF8\uC640 \uBAA9\uC801\uC774 \uB4DC\uB7EC\uB098\uB294 \uB124\uC774\uBC0D, \uB450\uBB38\uC790\uC5B4\uB3C4 \uD30C\uC2A4\uCE7C \uCF00\uC774\uC2A4 \uC0AC\uC6A9\n\n```javascript\n// \u2705 \uBAA9\uC801/\uC758\uBBF8 \uBD84\uBA85, Full Name\nexport const LoginForm = ({}: LoginFormProps) => {\n  ...\n}\n\n// \u274C \uC22B\uC790\nexport const UserView1 = () => {\n  ...\n}\n\n// \u2705 \uB450\uBB38\uC790\uC5B4\nexport const HtmlEditor = () => {\n  ...\n}\n// \u274C \uB450\uBB38\uC790\uC5B4\nexport const HTMLEditor = () => {\n  ...\n}\n\n// \u274C \uC57D\uC5B4, \uCD95\uC57D\uD615\nexport const UsrPrfl = () => {\n  ...\n}\n\n// \u274C \uD2B9\uC218\uBB38\uC790\nexport const User_Profile = () => {\n  ...\n}\n```\n\n## \uD568\uC218 \uBA85\uBA85 \uADDC\uCE59\n\n- \uD45C\uAE30\uBC95: camel case\n\n```javascript\n// \u2705 camel case\nconst getCamelCase = () => { ... }\n\n// \u274C\nconst Get_Camel_Case = () => { ... }\n\n// \u274C\nconst GetCamelCase = () => { ... }\n```\n\n- \uB3D9\uC0AC\uB85C \uC2DC\uC791\n\n```javascript\n// \u2705 \uB3D9\uC0AC\uB85C \uC2DC\uC791\nconst getCamelCase = () => { ... }\n\n// \u274C non \uB3D9\uC0AC\nconst camelCase = () => { ... }\n```\n\n- \uCD5C\uB300\uD55C \uAD6C\uCCB4\uC801 + \uBAA9\uD45C\uBD84\uBA85 + \uD55C \uAC00\uC9C0 \uCC45\uC784\uC744 \uB2F4\uB2F9\uD558\uB294 \uD568\uC218\uBA85\n- \uD568\uC218\uC758 \uC5ED\uD560\uC744 \uBA85\uD655\uD788 \uC54C \uC218 \uC788\uB3C4\uB85D \uD558\uACE0 \uB85C\uC9C1\uC774 \uACFC\uB3C4\uD558\uAC8C \uBAB0\uB9AC\uB294 \uAC78 \uBC29\uC9C0\uD558\uAE30 \uC704\uD568\n\n```javascript\n// \u2705 \uAD6C\uCCB4\uC801\uC774\uACE0 \uB2E8\uC77C\uBAA9\uC801\nconst formatDateToKorean = () => { ... }\n\n// \u274C \uCD94\uC0C1, \uC904\uC784\nconst format = () => { ... }\n```\n\n- \uC870\uAC74\uBD80\n- is/has/should + \uC870\uAC74\n\n```javascript\n// \u2705 \uC870\uAC74\uBD80 (is/has/should + \uB300\uC0C1)\nconst isTablet = () => { ... }\nconst hasChildren = () => { ... }\nconst shouldPreventEvent = () => { ... }\n```\n\n- API \uD638\uCD9C\uD568\uC218\n- C(create): create + \uB300\uC0C1 + (\uC0C1\uC138\uC815\uBCF4) (\uC608: createUserProfile)\n- R(read): \uB2E8\uAC74: get + \uB300\uC0C1 + (\uC0C1\uC138\uC815\uBCF4) (\uC608: getUserProfile), \uB2E4\uAC74: getList + \uB300\uC0C1 + (\uC0C1\uC138\uC815\uBCF4) (\uC608: getListUserProfile)\n- U(update): update + \uB300\uC0C1 + (\uC0C1\uC138\uC815\uBCF4) (\uC608: updateUserProfile)\n- D(delete): delete + \uB300\uC0C1 + (\uC0C1\uC138\uC815\uBCF4) (\uC608: deleteUserProfile)\n\n```javascript\n// \u2705 \uB2E8\uAC74 \uC870\uD68C API \uD638\uCD9C (get + \uB300\uC0C1)\nconst getUserName = () => { ... }\n\n// \u2705 \uB2E4\uAC74 \uC870\uD68C API \uD638\uCD9C (getList + \uB300\uC0C1)\nconst getListUserName = () => { ... }\n\n// \u2705 update \uC131\uACA9\uC758 API \uD638\uCD9C (update + \uB300\uC0C1)\nconst updateUserName = () => { ... }\n\n// \u2705 \uC0AD\uC81C \uC131\uACA9\uC758 API \uD638\uCD9C (delete + \uB300\uC0C1)\nconst deleteUserName = () => { ... }\n\n// \u2705 insert \uC131\uACA9\uC758 API \uD638\uCD9C (create + \uB300\uC0C1)\nconst createUserName = () => { ... }\n```\n\n- \uB370\uC774\uD130 \uBCC0\uD658\n- convert / format / parse + \uB300\uC0C1\n\n```javascript\n// \u2705 \uBCC0\uD658 \uD568\uC218 (convert/format/parse + \uB300\uC0C1)\nconst convertUserName = () => { ... }\nconst formatUserName = () => { ... }\nconst parseUserName = () => { ... }\n```\n\n- \uAC80\uC99D\n- validate + \uB300\uC0C1\n\n```javascript\n// \u2705 \uB370\uC774\uD130 \uAC80\uC99D (validate + \uB300\uC0C1)\nconst validateUserName = () => { ... }\n```\n\n- \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\n- handle + \uB300\uC0C1\n\n```javascript\n// \u2705 \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC (handle + \uC774\uBCA4\uD2B8\uD0C0\uC785 + \uB300\uC0C1)\nconst handleUserNameClick = () => { ... }\nconst handleModalClose = () => { ... }\n\n// \u2705 \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\uB97C Props\uB85C \uB118\uAE38 \uB550 (on + \uD578\uB4E4\uB7EC \uD568\uC218)\n<UserName onUserNameClick={handleUserNameClick} onModalClose={handleModalClose} />\n```\n\n- \uCD08\uAE30\uD654 / \uC0DD\uC131\n- create / initialize + \uB300\uC0C1\n\n```javascript\n// \u2705 \uCD08\uAE30\uD654 \uBC0F \uAC1D\uCCB4 \uC0DD\uC131 (create/initialize + \uB300\uC0C1)\nconst createApiInstance = () => { ... }\nconst initializeLoginInformation = () => { ... }\n```\n\n## \uBCC0\uC218 \uBA85\uBA85 \uADDC\uCE59\n\n- \uB2E8, \uBC31\uC5D4\uB4DC\uC5D0\uC11C \uC815\uC758\uB41C \uD544\uB4DC\uB294 \uADF8\uB300\uB85C \uB530\uB978\uB2E4.\n- \uAE30\uBCF8 \uD45C\uAE30\uBC95: camel case (object \uD3EC\uD568)\n- \uC0C1\uC218: Upper Snake case\n\n```javascript\n// \u2705 camel case\nconst userName = '\uAE40\uD55C\uD654';\n\n// \u2705 \uC0C1\uC218 case\nconst USER_NAME = '\uAE40\uD55C\uD654';\n\n// \u2705 object case\nconst testUtils = {\n  convertCurrency() {...}\n}\n\n// \u274C\nconst user_name = '';\nconst UserName = '';\nconst User_Name = '';\nconst TestUtils = {...};\n```\n\n- \uC758\uBBF8 \uC788\uACE0 \uAD6C\uCCB4\uC801\uC778 \uC774\uB984\n\n```javascript\n// \u2705 \uAD6C\uCCB4\uC801\nconst userName = '\uAE40\uD55C\uD654';\nconst isEmailValidated = false;\n\n// \u274C\nconst un = ''\nconst total = 0;\nconst item = [];\n\n// \u274C \uC9C4\uC9DC \uAE08\uC9C0\nconst flag = false;\n```\n\n- \uC22B\uC790\n\n```javascript\n// \u2705 \uAC1C\uC218 \uAD00\uB828 count, total, num \uC811\uB450\uC0AC/\uC811\uBBF8\uC0AC \uD65C\uC6A9\nconst userCount = 100;\nconst totalUsers = 1000;\nconst numPages = 100;\n\n// \u2705 \uD06C\uAE30/\uC591 \uAD00\uB828 size, amount, length \uC811\uBBF8\uC0AC \uD65C\uC6A9\nconst fileSize = 100;\nconst fileAmount = 100;\nconst fileLength = 100;\n```\n\n- \uBC30\uC5F4\n\n```javascript\n// \u2705 \uBCF5\uC218\uD615\uC73C\uB85C \uB0B4\uC6A9\uC744 \uC815\uD655\uD558\uAC8C \uD45C\uD604\nconst selectedUsers = [];\nconst errorMessages = [];\n\n// \u274C \uB2E8\uC218, \uCD94\uC0C1\uC801 \uC601\uBB38\uBA85\nconst user = [];\nconst data = [];\n```\n\n- boolean\n\n```javascript\n// \u2705 is/has/should \uC811\uB450\uC0AC \uD65C\uC6A9\n\n// ~\uC774\uB2E4, \uC544\uB2C8\uB2E4\nconst isLoading = false;\nconst isValid = false;\n\n// \uAC16\uB2E4, \uC544\uB2C8\uB2E4\nconst hasError = false;\n\n// \uD574\uC57C\uD560\uC9C0, \uB9D0\uC544\uC57C\uD560\uC9C0\nconst shouldUpdate = false;\n```\n\n- Class\n\n```javascript\n// \u2705 pascal case\nclass BridgeCore {}\n\n// \u274C\nclass bridgeCore {}\n```\n\n## Type, Interface \uBA85\uBA85 \uADDC\uCE59\n\n- \uAE30\uBCF8 \uD45C\uAE30\uBC95: Pascal Case\n\n```typescript\n// \u2705 Pascal case\ninterface UserInfo {\n  id: string;\n  name: string;\n}\n\n// \u2705 Swagger DTO \uBA85 \uADF8\uB300\uB85C \uC2B9\uACC4\ninterface ApiResponse<T> {\n  data: T;\n  message: string;\n}\n\n// \u274C\ninterface User_Info {}\n\n// \u274C\ninterface I_User_ {}\n```\n\n- Type: Pascal Case\n\n```typescript\n// \u2705 Pascal case\ntype UserName = 'user' | 'admin';\n\n// \u2705\ntype ApiStatus = 'success' | 'loading' | 'error';\n\n// \u274C\ntype TUserName = 'user' | 'admin';\n\n// \u274C\ntype API_STATUS = 'success' | 'loading' | 'error';\n```\n\n- interface \uC0AC\uC6A9 case\n- DTO: Swagger\uC5D0 \uC815\uC758\uB41C Request/Response \uBA85\uC744 \uADF8\uB300\uB85C \uB530\uB978\uB2E4.\n\n```typescript\n// \u2705 \uAC1D\uCCB4 \uAD6C\uC870 \uC815\uC758\ninterface UserInfo {}\n\n// \u2705 class \uAD6C\uD604\uC744 \uC704\uD55C \uC815\uC758\ninterface BridgeController {\n  call: () => void;\n  open: () => void;\n}\n\n// \u2705 \uD655\uC7A5 \uAC00\uB2A5\uD55C \uAD6C\uC870\ninterface BaseConfig {}\ninterface ApiClient extends BaseConfig {}\n\n// \u2705 Swagger\uC5D0 UserInfoRequest/UserInfoResponse \uB77C\uACE0 \uC815\uC758\uB41C \uACBD\uC6B0\ninterface UserInfoRequest {}\ninterface UserInfoResponse {}\n```\n\n- Type \uC0AC\uC6A9 case\n\n```typescript\n// \uC720\uB2C8\uC628 \uD0C0\uC785\ntype Status = 'success' | 'loading' | 'reject';\n\n// \uC870\uAC74 \uCF00\uC774\uC2A4\ntype NonNullable<T> = T extends null | undefined ? never : T;\n```\n";

// src/platform/assets/rules/fe/index.ts
var sharedFeCodingConventionRuleReference = createPromptMarkdownFileAsset(
  (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)),
  "src/platform/assets/rules/fe/coding-convention.md"
);
var sharedFeNamingRuleReference = createPromptMarkdownFileAsset(
  (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)),
  "src/platform/assets/rules/fe/naming-rule.md"
);
var sharedFeCodingConventionRule = coding_convention_default;
var sharedFeNamingRule = naming_rule_default;

// src/features/gen-storybook/assets/rules/fe/storybook-guide.md
var storybook_guide_default = "# \uC2A4\uD1A0\uB9AC\uBD81 \uC791\uC131 \uAC00\uC774\uB4DC\n\n> `/gen-storybook` \uC774 \uC2E4\uC81C story \uD30C\uC77C\uC744 \uC0DD\uC131\uD560 \uB54C \uCC38\uACE0\uD558\uB294 \uC0C1\uC138 Storybook \uADDC\uCE59\uC774\uB2E4.\n> \uBAA8\uB4E0 \uD328\uD0A4\uC9C0(`packages/`)\uC5D0\uC11C `.stories.tsx` \uD30C\uC77C\uC744 \uC791\uC131\uD560 \uB54C \uC801\uC6A9\uD55C\uB2E4.\n\n---\n\n## \uC720\uD615 \uD310\uB2E8\n\n| \uC720\uD615 | \uD310\uB2E8 \uAE30\uC900 | \uB300\uC0C1 \uD328\uD0A4\uC9C0 |\n|------|-----------|-------------|\n| **1. UI \uCEF4\uD3EC\uB10C\uD2B8 (\uB2E8\uC77C)** | Props\uB85C \uB80C\uB354\uB9C1\uC744 \uC81C\uC5B4\uD558\uB294 \uB2E8\uC77C \uCEF4\uD3EC\uB10C\uD2B8 | design-system, components |\n| **2. Compound \uCEF4\uD3EC\uB10C\uD2B8** | Root + \uD558\uC704 \uCEF4\uD3EC\uB10C\uD2B8 \uC870\uD569 \uD328\uD134 | design-system, components |\n| **3. \uC720\uD2F8\uB9AC\uD2F0 / \uD6C5** | \uC21C\uC218 \uD568\uC218 \uB610\uB294 React \uD6C5 | utils, hooks |\n| **4. \uC778\uD504\uB77C / Provider** | \uC0C1\uD0DC \uAD00\uB9AC, \uD1B5\uC2E0, \uD658\uACBD \uC124\uC815 \uB4F1 | stores, bridge, api, features, sentry |\n| **5. Foundation \uD1A0\uD070** | \uB514\uC790\uC778 \uD1A0\uD070 \uC2DC\uAC01 \uB808\uD37C\uB7F0\uC2A4 | design-system (Foundation) |\n\n---\n\n## \uD544\uC218 \uC2A4\uD1A0\uB9AC \uAD6C\uC131\n\n### \uC720\uD615 1/2: UI \uCEF4\uD3EC\uB10C\uD2B8\n\n| \uC21C\uC11C | export\uBA85 | name | Chromatic |\n|------|----------|------|-----------|\n| 1 | `UsageGuide` | `'\uC0AC\uC6A9 \uAC00\uC774\uB4DC'` | disableSnapshot |\n| 2 | `Faq` (\uC120\uD0DD) | `'\uC790\uC8FC \uBB3B\uB294 \uC9C8\uBB38'` | disableSnapshot |\n| 3 | `Playground` / `PlaygroundXxx` | `'Playground'` / `'Playground--Xxx'` | capture |\n| 4+ | `CaseXxx` | `'Cases--\uC124\uBA85'` | capture |\n\n- **Playground** \u2014 args\uB85C Props \uC778\uD130\uB799\uD2F0\uBE0C \uC870\uC791. args \uC870\uC791\uC774 \uC758\uBBF8 \uC5C6\uC73C\uBA74 \uC0DD\uB7B5 \uAC00\uB2A5\n- **Playground--Xxx** \u2014 Compound \uC804\uC6A9. \uD558\uC704 \uCEF4\uD3EC\uB10C\uD2B8\uBCC4\uB85C \uBD84\uB9AC. args \uC870\uC791\uC774 \uAC00\uB2A5\uD558\uBA74 args \uC0AC\uC6A9, \uBD88\uAC00\uD558\uBA74 render \uD568\uC218\uB85C \uAE30\uBCF8 \uB3D9\uC791 \uD655\uC778\uC6A9\uC73C\uB85C \uAD6C\uC131\n- **Cases--** \u2014 \uAC1C\uBCC4 props/\uC870\uD569 \uCF00\uC774\uC2A4. Chromatic \uC2A4\uB0C5\uC0F7 \uACB8\uC6A9\n- **Faq** \u2014 \uBE44\uC790\uBA85\uD55C \uB3D9\uC791 \uC2DC\uB098\uB9AC\uC624(\uC635\uC158 \uC0C1\uD638\uC791\uC6A9, \uB204\uC801, \uB77C\uC774\uD504\uC0AC\uC774\uD074 \uB4F1)\uB97C Q&A \uD615\uC2DD\uC73C\uB85C \uBAA8\uC544\uB450\uB294 \uBCC4\uB3C4 \uC2A4\uD1A0\uB9AC. \uC0C1\uC138\uB294 \uD6C4\uC220 [\uBE44\uC790\uBA85\uD55C \uB3D9\uC791 \uC2DC\uB098\uB9AC\uC624 \u2192 FAQ \uC2A4\uD1A0\uB9AC \uBD84\uB9AC] \uCC38\uC870\n\n### \uC720\uD615 3/4: \uC720\uD2F8\uB9AC\uD2F0 / \uD6C5 / \uC778\uD504\uB77C\n\n| \uC21C\uC11C | export\uBA85 | name | Chromatic |\n|------|----------|------|-----------|\n| 1 | `UsageGuide` | `'\uC0AC\uC6A9 \uAC00\uC774\uB4DC'` | disableSnapshot |\n| 2 | `Faq` (\uC120\uD0DD) | `'\uC790\uC8FC \uBB3B\uB294 \uC9C8\uBB38'` | disableSnapshot |\n| 3+ | `ExampleXxx` | `'\uC608\uC81C--\uC124\uBA85'` | disableSnapshot |\n\n### \uC720\uD615 5: Foundation \uD1A0\uD070\n\n| \uC21C\uC11C | export\uBA85 | name | Chromatic |\n|------|----------|------|-----------|\n| 1 | `UsageGuide` | `'\uC0AC\uC6A9 \uAC00\uC774\uB4DC'` | disableSnapshot |\n| 2 | `Playground` | `'Playground'` | capture |\n| 3 | `Total` | `'\uC804\uCCB4'` | capture |\n\n---\n\n## Meta \uC815\uC758 \uADDC\uCE59\n\n### Title \uD328\uD134\n\n\uD328\uD0A4\uC9C0\uBA85\uC774 \uBC18\uB4DC\uC2DC 1depth\uB85C \uC704\uCE58:\n\n```\nDesign System/Component/{Category}/{Name}\nDesign System/Composite/{Name}\nDesign System/Foundation/{Name}\nComponents/{Category}/{Name}\nUtils/{\uBAA8\uB4C8\uBA85}\nHooks/{hook-name}\nAPI/{topic}\n```\n\n### Meta \uD0C0\uC785 \uC120\uD0DD\n\n| \uC0C1\uD669 | \uD328\uD134 |\n|------|------|\n| UI \uCEF4\uD3EC\uB10C\uD2B8 | `const meta: Meta<typeof Component> = { ... }` |\n| Compound | `const meta: Meta<typeof Component.Root> = { ... }` + `subcomponents` |\n| \uBE44\uCEF4\uD3EC\uB10C\uD2B8 | `const meta = { ... } satisfies Meta` |\n\n### \uACF5\uD1B5 \uD544\uC218 \uD56D\uBAA9\n\n```typescript\nconst meta = {\n  title: '\uD328\uD0A4\uC9C0\uBA85/\uC911\uAC04\uAD6C\uBD84/\uAE30\uB2A5\uBA85',\n  tags: ['autodocs'],\n  parameters: {\n    docs: {\n      description: {\n        component: `...`  // \uC544\uB798 \uD3EC\uB9F7 \uCC38\uC870\n      }\n    }\n  }\n};\n```\n\n---\n\n## description.component \uD3EC\uB9F7\n\n### \uAC1C\uBCC4 \uCEF4\uD3EC\uB10C\uD2B8/\uC720\uD2F8 \uC2A4\uD1A0\uB9AC\n\n\uD328\uD0A4\uC9C0\uBA85/\uC124\uCE58\uD558\uAE30\uB294 **\uB300\uD45C Docs\uC5D0\uB9CC** \uC791\uC131. \uAC1C\uBCC4 \uC2A4\uD1A0\uB9AC\uC5D0\uB294 \uD3EC\uD568\uD558\uC9C0 \uC54A\uB294\uB2E4.\n\n````markdown\n\uCEF4\uD3EC\uB10C\uD2B8/\uD568\uC218 \uC5ED\uD560 \uC694\uC57D (1~2\uC904)\n\n### \uC0AC\uC6A9\uD558\uAE30\n\n```javascript\nimport { Xxx } from 'sales-frontend-xxx';\n```\n\n## \uD2B9\uC9D5\n- \uD2B9\uC9D5 1\n- \uD2B9\uC9D5 2\n\n## \uC720\uC758\uC0AC\uD56D (\uD574\uB2F9\uD558\uB294 \uACBD\uC6B0)\n- \uC8FC\uC758\uD560 \uC810 1\n````\n\n### \uB300\uD45C Docs (\uD328\uD0A4\uC9C0 \uC778\uB371\uC2A4 \uC2A4\uD1A0\uB9AC)\n\n````markdown\n\uD328\uD0A4\uC9C0 \uC5ED\uD560 \uC694\uC57D (1~2\uC904)\n\n## \uD328\uD0A4\uC9C0\uBA85\n\n**sales-frontend-xxx**\n\n### \uC124\uCE58\uD558\uAE30\n\n```bash\npnpm add sales-frontend-xxx\n```\n\n### Peer Dependencies (\uD574\uB2F9\uD558\uB294 \uACBD\uC6B0)\n\n```bash\npnpm add @tanstack/react-query\n```\n\n### \uC0AC\uC6A9\uD558\uAE30\n\n```javascript\nimport { Xxx } from 'sales-frontend-xxx';\n```\n\n## \uD2B9\uC9D5 / \uC720\uC758\uC0AC\uD56D / \uC81C\uACF5 \uBAA8\uB4C8\n````\n\n---\n\n## \uC0AC\uC6A9 \uAC00\uC774\uB4DC \uC2A4\uD1A0\uB9AC \uC791\uC131 \uD328\uD134\n\n```tsx\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';\n\nconst sampleCode = `import { Xxx } from 'sales-frontend-xxx';\n// \uCF54\uB4DC \uC608\uC81C...`;\n\nexport const UsageGuide: Story = {\n  name: '\uC0AC\uC6A9 \uAC00\uC774\uB4DC',\n  parameters: { chromatic: { disableSnapshot: true } },\n  render: function UsageGuide() {\n    return (\n      <div style={{ display: 'grid', gap: '24px', maxWidth: '980px' }}>\n        <section className=\"sb-code-section\">\n          <h3 style={{ margin: 0 }}>\uC81C\uBAA9</h3>\n          <p style={{ margin: 0 }}>\uC124\uBA85 (\uC120\uD0DD)</p>\n          <SyntaxHighlighter language=\"tsx\" style={vscDarkPlus} className=\"sb-code-block\">\n            {sampleCode}\n          </SyntaxHighlighter>\n        </section>\n      </div>\n    );\n  }\n};\n```\n\n- \uC0D8\uD50C\uCF54\uB4DC \uBCC0\uC218\uB294 meta \uC815\uC758 **\uC804\uC5D0** \uC120\uC5B8\n- \uC5EC\uB7EC \uC139\uC158\uC774\uBA74 \uBC88\uD638 prefix: `1. \uAE30\uBCF8 \uC0AC\uC6A9\uBC95`, `2. \uACE0\uAE09 \uC0AC\uC6A9\uBC95`\n- \uB2E8\uC77C \uC139\uC158\uC774\uBA74 `{\uCEF4\uD3EC\uB10C\uD2B8\uBA85} \uC0AC\uC6A9 \uC608\uC81C`\n\n### \uBE44\uC790\uBA85\uD55C \uB3D9\uC791 \uC2DC\uB098\uB9AC\uC624 \u2192 FAQ \uC2A4\uD1A0\uB9AC \uBD84\uB9AC\n\n**\uC6D0\uCE59**: \uC2A4\uD1A0\uB9AC\uBD81 \uC0AC\uC6A9 \uAC00\uC774\uB4DC\uB294 \"\uC18C\uBE44\uC790(\uD0C0 \uD504\uB85C\uC81D\uD2B8 \uAC1C\uBC1C\uC790)\uAC00 \uD328\uD0A4\uC9C0 \uCF54\uB4DC\uC640 JSDoc\uC744 \uBCF4\uC9C0 \uC54A\uACE0\uB3C4 \uC548\uC804\uD558\uAC8C \uC0AC\uC6A9\uD560 \uC218 \uC788\uB3C4\uB85D\" \uC791\uC131\uD55C\uB2E4.\n\uD0C0\uC785/\uC2DC\uADF8\uB2C8\uCC98\uB9CC \uBCF4\uACE0 \uC54C \uC218 \uC5C6\uB294 \uBAA8\uB4E0 **\uBE44\uC790\uBA85\uD55C \uB3D9\uC791 \uC2DC\uB098\uB9AC\uC624**\uB294 \uBCC4\uB3C4 \uC2A4\uD1A0\uB9AC **`Faq` (`'\uC790\uC8FC \uBB3B\uB294 \uC9C8\uBB38'`)** \uB85C \uBD84\uB9AC\uD574 \uC791\uC131\uD55C\uB2E4.\n\n#### \uC65C \uBCC4\uB3C4 \uC2A4\uD1A0\uB9AC\uC778\uAC00\n\n- `UsageGuide`(\uC0AC\uC6A9 \uAC00\uC774\uB4DC)\uB294 \"\uCC98\uC74C \uC4F0\uB294 \uC0AC\uB78C\uC774 5\uBD84 \uC548\uC5D0 \uB530\uB77C \uCE60 \uC218 \uC788\uB294 \uD575\uC2EC \uC0AC\uC6A9\uBC95\"\uC5D0 \uC9D1\uC911\uD55C\uB2E4. \uC2DC\uB098\uB9AC\uC624\xB7\uC608\uC678 \uCC98\uB9AC\xB7\uB0B4\uBD80 \uB3D9\uC791 \uC124\uBA85\uC774 \uC11E\uC774\uBA74 \uAC00\uC774\uB4DC\uAC00 \uBB34\uAC70\uC6CC\uC838 \uD559\uC2B5 \uBE44\uC6A9\uC774 \uCEE4\uC9C4\uB2E4.\n- FAQ \uC2A4\uD1A0\uB9AC\uB294 \"\uC774\uBBF8 \uC4F0\uACE0 \uC788\uB294 \uC0AC\uB78C\uC774 \uB9C9\uD614\uC744 \uB54C \uCC3E\uC544\uC624\uB294 \uCC38\uACE0\uC11C\" \uC5ED\uD560\uC774\uB2E4. Q&A \uD3EC\uB9F7\uC73C\uB85C \uAC80\uC0C9\xB7\uC2A4\uCE94\uC774 \uC27D\uB3C4\uB85D \uD55C\uB2E4.\n- Storybook sidebar\uC5D0\uC11C \uAC00\uC774\uB4DC\uC640 FAQ\uAC00 \uBD84\uB9AC\uB418\uC5B4 \uB178\uCD9C\uB418\uBBC0\uB85C, \uC2E0\uADDC \uD559\uC2B5 vs \uD2B8\uB7EC\uBE14\uC288\uD305 \uB450 \uB3D9\uC120\uC774 \uBA85\uD655\uD788 \uAC08\uB9B0\uB2E4.\n\n#### \uC791\uC131 \uC6D0\uCE59\n\n- \uD328\uD0A4\uC9C0 \uAC1C\uBC1C\uC790\uC5D0\uAC8C\uB294 \uCF54\uB4DC \uC8FC\uC11D\uC73C\uB85C \uCDA9\uBD84\uD558\uC9C0\uB9CC, \uC18C\uBE44\uC790\uB294 \uD328\uD0A4\uC9C0 \uCF54\uB4DC\uB97C \uBCF4\uC9C0 \uC54A\uC73C\uBBC0\uB85C FAQ\uC5D0\uB9CC \uC788\uB294 \uC815\uBCF4\uB294 \uC804\uB2EC\uB418\uC9C0 \uC54A\uB294\uB2E4.\n- \uAC01 \uD56D\uBAA9\uC740 **`Q. ...?`** \uD5E4\uB354\uB85C \uC2DC\uC791\uD574 \uAC80\uC0C9\uC131\uC744 \uD655\uBCF4\uD55C\uB2E4.\n- \uC2DC\uB098\uB9AC\uC624\uB294 **\uCC28\uC218/\uC21C\uC11C/\uC0C1\uD0DC \uC804\uC774**\uAC00 \uB4DC\uB7EC\uB098\uB3C4\uB85D \uB2E8\uACC4\uBCC4\uB85C \uAE30\uC220\uD55C\uB2E4(\uD14C\uC774\uBE14 \uAD8C\uC7A5).\n- Chromatic\uC740 `disableSnapshot`\uC73C\uB85C \uB450\uC5B4 \uC2DC\uAC01 \uD68C\uADC0 \uB300\uC0C1\uC5D0\uC11C \uC81C\uC678\uD55C\uB2E4.\n\n#### \uC5B4\uB5A4 \uB3D9\uC791\uC774 \"\uBE44\uC790\uBA85\"\uC778\uAC00 \u2014 \uCD94\uAC00 \uC2E0\uD638 \uCCB4\uD06C\uB9AC\uC2A4\uD2B8\n\n\uB2E4\uC74C \uC911 \uD558\uB098\uB77C\uB3C4 \uD574\uB2F9\uD558\uBA74 \uAC00\uC774\uB4DC\uC5D0 \uC2DC\uB098\uB9AC\uC624 \uC139\uC158\uC744 \uB9CC\uB4E0\uB2E4.\n\n1. **\uC635\uC158 \uAC04 \uC0C1\uD638\uC791\uC6A9**: props\uAC00 \uC11C\uB85C \uC758\uC874\uD558\uAC70\uB098(\uC608: `maxPhotos \xD7 pageLimit`, `min \xD7 max`, `debounceMs \xD7 enabled`) \uD55C\uCABD \uAC12\uC774 \uB2E4\uB978 \uCABD\uC758 \uC758\uBBF8\uB97C \uBC14\uAFB8\uB294 \uACBD\uC6B0\n2. **\uB204\uC801/\uB36E\uC5B4\uC4F0\uAE30/\uB9AC\uC14B**: \uD638\uCD9C \uCC28\uC218\xB7\uC2DC\uAC04 \uD750\uB984\uC5D0 \uB530\uB77C \uB0B4\uBD80 \uC0C1\uD0DC\uAC00 \uB204\uC801\uB418\uAC70\uB098 \uB36E\uC5B4\uC368\uC9C0\uB294 \uACBD\uC6B0 (\uC608: `type/mode` \uAC12\uC5D0 \uB530\uB77C \uB204\uC801 vs \uB2E8\uC77C \uCC98\uB9AC\uAC00 \uAC08\uB9BC)\n3. **\uD55C\uB3C4/\uC81C\uD55C \uBD84\uAE30**: \uCD08\uACFC \uC2DC \uC815\uCC45 \uBD84\uAE30(`error` / `truncate` / `silent` / \uC7AC\uC2DC\uB3C4 \uB4F1)\uC640 \uAC01 \uBAA8\uB4DC\uBCC4 \uAE30\uBCF8\uAC12\n4. **\uB77C\uC774\uD504\uC0AC\uC774\uD074 \uBD80\uC218\uD6A8\uACFC**: mount/unmount \uC2DC \uC790\uB3D9 cleanup \uC5EC\uBD80, `ref`/\uB9AC\uC18C\uC2A4(blob URL, subscription) \uD574\uC81C \uCC45\uC784, \uC758\uC874\uC131 \uBCC0\uACBD \uC2DC \uB9AC\uC14B \uC5EC\uBD80\n5. **\uBE44\uB3D9\uAE30 \uD750\uB984**: \uD638\uCD9C \uC21C\uC11C\xB7\uACBD\uD569(race) \uCC98\uB9AC \uBC29\uC2DD, \uC911\uBCF5 \uD638\uCD9C \uC2DC \uB3D9\uC791(\uAC00\uC7A5 \uCD5C\uADFC\uB9CC \uC720\uD6A8 / \uC9C1\uB82C\uD654 / \uBB34\uC2DC), \uC9C4\uD589 \uC911 unmount \uC2DC \uB3D9\uC791\n6. **\uC5D0\uB7EC/\uC608\uC678 \uACBD\uB85C**: \uC5B4\uB5A4 \uC785\uB825\uC774 throw \uD558\uB294\uC9C0, \uD638\uCD9C\uC790\uAC00 catch \uD574\uC57C \uD558\uB294\uC9C0, \uC5D0\uB7EC \uD6C4 \uB0B4\uBD80 \uC0C1\uD0DC\uAC00 \uC5B4\uB5BB\uAC8C \uB418\uB294\uC9C0(\uBCF5\uAD6C \uAC00\uB2A5 \uC5EC\uBD80)\n7. **\uD50C\uB7AB\uD3FC/\uD658\uACBD \uBD84\uAE30**: OS\xB7\uBE0C\uB77C\uC6B0\uC800\xB7\uB514\uBC14\uC774\uC2A4\uBCC4 \uB3D9\uC791 \uCC28\uC774(iOS Safari, Android WebView, \uB370\uC2A4\uD06C\uD0D1), \uB124\uC774\uD2F0\uBE0C \uBE0C\uB9AC\uC9C0 \uC720\uBB34\uC5D0 \uB530\uB978 \uD3F4\uBC31\n8. **\uC131\uB2A5/\uB9AC\uB80C\uB354 \uD2B9\uC131**: \uBA54\uBAA8\uC774\uC988 \uAD8C\uC7A5 props, \uD070 \uC785\uB825 \uC2DC \uB3D9\uAE30 vs \uBE44\uB3D9\uAE30 \uCC98\uB9AC, \uC774\uBCA4\uD2B8 \uB514\uBC14\uC6B4\uC2A4/\uC2A4\uB85C\uD2C0\uC758 \uAE30\uBCF8\uAC12\n9. **\uC811\uADFC\uC131\xB7\uD0A4\uBCF4\uB4DC \uB3D9\uC791**: \uD3EC\uCEE4\uC2A4 \uC774\uB3D9 \uADDC\uCE59, Esc/Enter \uB4F1 \uD0A4 \uBC14\uC778\uB529, `aria-*` \uC0C1\uD0DC\uAC00 \uBCC0\uD558\uB294 \uC2DC\uC810\n10. **\uC678\uBD80 \uC758\uC874**: \uD2B9\uC815 Provider/Context \uD544\uC218 \uC5EC\uBD80, peerDependency \uBC84\uC804 \uC81C\uC57D, \uC804\uC5ED \uC124\uC815 \uD0A4\uC640\uC758 \uCDA9\uB3CC\n\n> Rule of thumb: \"\uC774 \uC2DC\uADF8\uB2C8\uCC98\uB9CC \uBCF4\uACE0 \uCC98\uC74C \uC4F0\uB294 \uAC1C\uBC1C\uC790\uAC00 30\uBD84 \uC548\uC5D0 \uB514\uBC84\uAE45\uD560 \uC218 \uC788\uB294\uAC00?\" \uB2F5\uC774 No \uB77C\uBA74 \uADF8 \uB3D9\uC791\uC740 \uAC00\uC774\uB4DC \uC139\uC158\uC774 \uD544\uC694\uD558\uB2E4.\n\n#### \uC2DC\uB098\uB9AC\uC624 \uC791\uC131 \uD615\uC2DD\n\n\uAC01 \uC139\uC158\uC740 \uB2E4\uC74C 4\uC694\uC18C \uC911 \uD574\uB2F9\uD558\uB294 \uAC83\uC744 \uD3EC\uD568\uD55C\uB2E4.\n\n- **What**: \uC5B4\uB5A4 \uC2DC\uB098\uB9AC\uC624\uC778\uC9C0 \uD55C \uC904 \uC694\uC57D\n- **How**: \uCC28\uC218/\uB2E8\uACC4\uBCC4 \uB3D9\uC791 (`1\uCC28 \u2192 2\uCC28 \u2192 3\uCC28`, `mount \u2192 \uC0AC\uC6A9 \u2192 unmount`, `\uC815\uC0C1 \u2192 \uC5D0\uB7EC \u2192 \uBCF5\uAD6C` \uB4F1 \uC0C1\uD0DC \uC804\uC774)\n- **Edge cases**: \uACBD\uACC4 \uC870\uAC74(0, \uC74C\uC218, \uBE48 \uBC30\uC5F4, \uCD5C\uB300\uCE58, undefined), \uB2E4\uB978 \uC635\uC158 \uC870\uD569\uC5D0 \uB530\uB978 \uBD84\uAE30\n- **\uC8FC\uC758 \uC0AC\uD56D**: \uC790\uC8FC \uBC1C\uC0DD\uD558\uB294 \uC624\uD574/\uC548\uD2F0\uD328\uD134/\uC0AC\uC774\uB4DC\uC774\uD399\uD2B8\n\n#### \uC608\uC2DC 1 \u2014 \uC635\uC158 \uC0C1\uD638\uC791\uC6A9 (`maxPhotos \xD7 pageLimit` \uB204\uC801 \uB3D9\uC791)\n\n> FAQ \uC2A4\uD1A0\uB9AC \uB0B4\uBD80 \uAC01 Q&A \uC139\uC158\uC740 **\uC694\uC57D \uD5E4\uB354(callout) + \uB2E8\uACC4\uBCC4 \uD14C\uC774\uBE14(`sb-table`) + \uC8FC\uC758 \uC0AC\uD56D \uBC15\uC2A4** \uD328\uD134\uC744 \uAD8C\uC7A5\uD55C\uB2E4.\n> \uD3C9\uBB38 `<p>`/`<ul>`\uB9CC \uB098\uC5F4\uD558\uBA74 \uC2DC\uAC01\uC801\uC73C\uB85C \uBB49\uAC1C\uC9C0\uBBC0\uB85C \uD53C\uD55C\uB2E4.\n\n```tsx\nexport const Faq: Story = {\n  name: '\uC790\uC8FC \uBB3B\uB294 \uC9C8\uBB38',\n  parameters: { chromatic: { disableSnapshot: true } },\n  render: function Faq() {\n    return (\n      <div style={{ display: 'grid', gap: '32px', maxWidth: '980px' }}>\n        <section className=\"sb-code-section\">\n          <h3 style={{ margin: 0 }}>Q. maxPhotos \xD7 pageLimit \uC740 \uC5B4\uB5BB\uAC8C \uB204\uC801\uB418\uB098\uC694?</h3>\n          <p style={{ margin: 0, lineHeight: 1.7 }}>\n            \uD55C \uBC88\uC758 <code>onClick</code>\uC740 \uCD5C\uB300 <code>pageLimit</code> \uC7A5\uC744 \uCEA1\uCC98\uD558\uACE0, \uACB0\uACFC\uB294 \uAE30\uC874 \uBAA9\uB85D\uC5D0 \uB204\uC801\uB429\uB2C8\uB2E4.\n            \uB204\uC801 \uCD1D\uB7C9\uC740 <code>maxPhotos</code>\uB85C \uC81C\uD55C\uB429\uB2C8\uB2E4.\n          </p>\n\n          {/* \uC694\uC57D \uD5E4\uB354 (callout): \uD575\uC2EC \uC870\uD569\uACFC \uACB0\uACFC\uB97C \uD55C \uC904\uB85C */}\n          <div\n            style={{\n              display: 'flex', flexWrap: 'wrap', gap: '12px', alignItems: 'center',\n              padding: '12px 16px', fontSize: '14px',\n              background: '#f6f8fa', border: '1px solid #d0d7de', borderRadius: '8px'\n            }}\n          >\n            <strong style={{ color: '#0969da' }}>\uC608\uC2DC</strong>\n            <code>maxPhotos: 10</code>\n            <span style={{ color: '#6e7781' }}>\xD7</span>\n            <code>pageLimit: 5</code>\n            <span style={{ color: '#6e7781' }}>\u2192</span>\n            <span>5\uC7A5\uC529 \uB450 \uBC88 \uCD2C\uC601 = <strong>\uCD1D 10\uC7A5</strong></span>\n          </div>\n\n          {/* \uB2E8\uACC4\uBCC4 \uD14C\uC774\uBE14: \uCC28\uC218/\uC0C1\uD0DC \uC804\uC774\uB97C \uD55C\uB208\uC5D0 */}\n          <table className=\"sb-table\">\n            <thead>\n              <tr>\n                <th style={{ width: 56 }}>\uCC28\uC218</th>\n                <th style={{ width: 96 }}>current</th>\n                <th style={{ width: 96 }}>remaining</th>\n                <th>\uB4F1\uB85D \uACB0\uACFC</th>\n                <th style={{ width: 132 }}>\uB204\uC801 \uCD1D\uB7C9</th>\n              </tr>\n            </thead>\n            <tbody>\n              <tr><td>1\uCC28</td><td>0</td><td>10</td><td>5\uC7A5 \uC804\uBD80 \uD1B5\uACFC</td><td>5\uC7A5</td></tr>\n              <tr><td>2\uCC28</td><td>5</td><td>5</td><td>5\uC7A5 \uC804\uBD80 \uD1B5\uACFC</td><td>10\uC7A5</td></tr>\n              <tr>\n                <td>3\uCC28</td><td>10</td><td>0</td>\n                <td>\uB4F1\uB85D \uCC28\uB2E8 \u2014 <code>'error'</code>(\uAE30\uBCF8)\uBA74 \uD578\uB4E4\uB7EC \uD638\uCD9C, <code>'truncate'</code>\uBA74 \uC870\uC6A9\uD788 \uC798\uB9BC</td>\n                <td>10\uC7A5 (\uBCC0\uB3D9 \uC5C6\uC74C)</td>\n              </tr>\n            </tbody>\n          </table>\n\n          {/* \uC8FC\uC758 \uC0AC\uD56D \uBC15\uC2A4 (warning callout) */}\n          <div\n            style={{\n              padding: '12px 16px', fontSize: '14px', lineHeight: 1.7,\n              background: '#fffbeb', border: '1px solid #fde68a',\n              borderLeft: '4px solid #f59e0b', borderRadius: '6px'\n            }}\n          >\n            <strong style={{ color: '#92400e' }}>\uC8FC\uC758 \uC0AC\uD56D</strong>\n            <ul style={{ margin: '6px 0 0', paddingLeft: '20px' }}>\n              <li><code>type === 'single'</code>\uC774\uBA74 \uB9E4\uBC88 \uB36E\uC5B4\uC368 \uB204\uC801\uB418\uC9C0 \uC54A\uC74C</li>\n              <li>\uD55C \uBC88\uC5D0 \uB0A8\uC740 \uC2AC\uB86F \uCD08\uACFC \uC785\uB825 \uC2DC \u2014 <code>'error'</code>\uB294 \uC804\uBD80 \uAC70\uBD80, <code>'truncate'</code>\uB294 \uB0A8\uC740 \uC2AC\uB86F\uB9CC\uD07C \uC798\uB77C \uB4F1\uB85D</li>\n            </ul>\n          </div>\n        </section>\n        {/* Q&A \uCD94\uAC00 \uC2DC \uAC19\uC740 \uD328\uD134\uC73C\uB85C <section>\uC744 \uB298\uB824\uAC04\uB2E4 */}\n      </div>\n    );\n  }\n};\n```\n\n**\uC2A4\uD0C0\uC77C \uD1A0\uD070 \uAC00\uC774\uB4DC** \u2014 \uC778\uB77C\uC778 \uC2A4\uD0C0\uC77C\uC774 \uAE38\uC5B4\uC9C0\uBA74 \uAC00\uB3C5\uC131\uC744 \uD574\uCE5C\uB2E4. \uAC00\uB2A5\uD558\uBA74 `apps/docs/app/global.css`\uC758 \uAE30\uC874 \uD074\uB798\uC2A4(`sb-code-section`, `sb-table`)\uB97C \uC6B0\uC120 \uD65C\uC6A9\uD558\uACE0, \uC704\uC640 \uAC19\uC774 \uC790\uC8FC \uC4F0\uB294 \uD328\uD134(\uC694\uC57D callout, warning callout)\uC774 \uBC18\uBCF5\uB418\uBA74 \uAE00\uB85C\uBC8C CSS\uC5D0 \uC0C8 \uD074\uB798\uC2A4 \uCD94\uAC00\uB97C \uAC80\uD1A0\uD55C\uB2E4.\n\n#### \uC608\uC2DC 2 \u2014 \uB77C\uC774\uD504\uC0AC\uC774\uD074\xB7\uBE44\uB3D9\uAE30 (Q&A \uC591\uC2DD\uB9CC)\n\n```tsx\n<section className=\"sb-code-section\">\n  <h3 style={{ margin: 0 }}>Q. \uBE44\uB3D9\uAE30 \uD638\uCD9C \uC911 \uCEF4\uD3EC\uB10C\uD2B8\uAC00 unmount \uB418\uBA74 \uC5B4\uB5BB\uAC8C \uB418\uB098\uC694?</h3>\n  <p>\uC694\uCCAD \uC9C4\uD589 \uC911 unmount \uB418\uBA74 \uACB0\uACFC\uB294 \uBB34\uC2DC\uB418\uACE0, \uC9C4\uD589 \uC911 \uC694\uCCAD\uC740 abort \uB429\uB2C8\uB2E4.</p>\n  <ul>\n    <li>mount \u2192 fetch \uC2DC\uC791 \u2192 unmount \u2192 \uC751\uB2F5 \uB3C4\uCC29: setState \uD638\uCD9C \uC548 \uB428 (warning \uC5C6\uC74C)</li>\n    <li>\uB3D9\uC77C \uC778\uC790\uB85C \uC911\uBCF5 \uD638\uCD9C \uC2DC: \uAC00\uC7A5 \uB9C8\uC9C0\uB9C9 \uD638\uCD9C\uB9CC \uC720\uD6A8, \uC774\uC804 \uD638\uCD9C\uC740 abort</li>\n    <li>\uC5D0\uB7EC \uD6C4: \uB0B4\uBD80 \uC0C1\uD0DC\uB294 \uB9C8\uC9C0\uB9C9 \uC131\uACF5 \uC751\uB2F5\uC744 \uC720\uC9C0. \uC7AC\uD638\uCD9C \uC2DC \uC0C8 \uC694\uCCAD \uC2DC\uC791</li>\n  </ul>\n</section>\n```\n\n---\n\n## \uB124\uC774\uBC0D \uADDC\uCE59\n\n| \uD56D\uBAA9 | \uADDC\uCE59 |\n|------|------|\n| `name` | \uD55C\uAE00 (`'\uC0AC\uC6A9 \uAC00\uC774\uB4DC'`, `'\uC790\uC8FC \uBB3B\uB294 \uC9C8\uBB38'`, `'Cases--\uC124\uBA85'`, `'\uC608\uC81C--\uC124\uBA85'`). \uC608\uC678: `'Playground'`, `'Playground--Xxx'` |\n| export\uBA85 | PascalCase \uC601\uBB38 (`UsageGuide`, `Playground`, `CaseDisabled`) |\n| `--` prefix | sidebar flat \uB098\uC5F4\uC6A9 \uC2DC\uAC01\uC801 \uAD6C\uBD84 (\uD3F4\uB354 \uC544\uB2D8) |\n| render \uD568\uC218\uBA85 | export\uBA85\uACFC \uB3D9\uC77C (`function UsageGuide() {}`) |\n| \uC0D8\uD50C\uCF54\uB4DC \uBCC0\uC218 | camelCase (`sampleCodeBasic`, `sampleCodeAdvanced`) |\n\n---\n\n## argTypes \uADDC\uCE59\n\n| Props \uC720\uD615 | control |\n|------------|---------|\n| \uC5F4\uAC70\uD615 (4\uAC1C+) | `{ type: 'select' }` |\n| \uC5F4\uAC70\uD615 (2~3\uAC1C) | `{ type: 'radio' }` |\n| boolean | `{ type: 'boolean' }` |\n| \uD14D\uC2A4\uD2B8 | `{ type: 'text' }` |\n| \uBCF5\uD569 \uD0C0\uC785 (ReactNode, \uD568\uC218) | `false` |\n\n- \uBAA8\uB4E0 props\uC5D0 `description` (\uD55C\uAE00) \uD544\uC218\n- `table.type.summary` \u2014 \uD0C0\uC785 \uC694\uC57D\n- `table.defaultValue.summary` \u2014 \uAE30\uBCF8\uAC12 (\uC788\uB294 \uACBD\uC6B0)\n- required props \u2014 `type: { required: true, name: 'string' }`\n\n---\n\n## import \uC21C\uC11C\n\n```typescript\n// 1. React (\uD544\uC694\uC2DC)\nimport React from 'react';\n\n// 2. \uC678\uBD80 \uB77C\uC774\uBE0C\uB7EC\uB9AC\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';\n\n// 3. \uB0B4\uBD80 \uCEF4\uD3EC\uB10C\uD2B8/\uC720\uD2F8\nimport { SomeComponent } from './some-component';\n\n// 4. type import\nimport type { Meta, StoryObj } from '@storybook/nextjs-vite';\n```\n\n---\n\n## Chromatic \uC2A4\uB0C5\uC0F7 \uADDC\uCE59\n\n| \uCEA1\uCC98 \uB300\uC0C1 | \uC81C\uC678 \uB300\uC0C1 |\n|-----------|-----------|\n| Playground, Playground--Xxx, Cases--Xxx, Total | UsageGuide, Faq, \uC608\uC81C--, \uD14C\uC2A4\uD2B8 |\n\n### Cases-- \uC791\uC131 \uC6D0\uCE59 (\uC2A4\uB0C5\uC0F7 \uACB8\uC6A9)\n\n- \uB79C\uB364/\uC2DC\uAC04 \uC758\uC874 \uB370\uC774\uD130 \uC0AC\uC6A9 \uAE08\uC9C0\n- \uACE0\uC815 \uCEE8\uD14C\uC774\uB108 \uD06C\uAE30: `style={{ width: 600 }}`\n- \uBC18\uC751\uD615 \uCEF4\uD3EC\uB10C\uD2B8: `viewports: [375, 768, 1192]`\n- \uC560\uB2C8\uBA54\uC774\uC158: `delay` + `pauseAnimationAtEnd`\n\n---\n\n## \uD30C\uC77C \uC704\uCE58 \uBC0F \uAD6C\uC870\n\n| \uAD6C\uBD84 | \uC704\uCE58 | \uD30C\uC77C\uBA85 |\n|------|------|--------|\n| \uCEF4\uD3EC\uB10C\uD2B8 \uC2A4\uD1A0\uB9AC | \uCEF4\uD3EC\uB10C\uD2B8\uC640 \uAC19\uC740 \uB514\uB809\uD1A0\uB9AC | `{component-name}.stories.tsx` |\n| \uC720\uD2F8 \uC2A4\uD1A0\uB9AC | \uC720\uD2F8 \uD30C\uC77C\uACFC \uAC19\uC740 \uB514\uB809\uD1A0\uB9AC | `{util-name}.stories.tsx` |\n| \uD328\uD0A4\uC9C0 \uC778\uB371\uC2A4 | \uD328\uD0A4\uC9C0 `src/` \uB8E8\uD2B8 | `{package-name}-docs.stories.tsx` |\n\n### \uD30C\uC77C \uB0B4\uBD80 \uAD6C\uC870 \uC21C\uC11C\n\n```\n1. import \uBB38\n2. \uC0D8\uD50C\uCF54\uB4DC \uBCC0\uC218 (const sampleCode = `...`)\n3. Meta \uC815\uC758\n4. export default meta\n5. type Story \uC815\uC758\n6. UsageGuide \uC2A4\uD1A0\uB9AC\n7. Faq \uC2A4\uD1A0\uB9AC (\uBE44\uC790\uBA85\uD55C \uB3D9\uC791 \uC2DC\uB098\uB9AC\uC624\uAC00 \uC788\uB294 \uACBD\uC6B0 \u2014 UsageGuide\uC640 \uD568\uAED8 reference \uB3C4\uD050\uBA3C\uD2B8\uB85C \uBB36\uAE30 \uC704\uD574 \uBC14\uB85C \uB4A4\uC5D0 \uB454\uB2E4)\n8. Playground \uC2A4\uD1A0\uB9AC (\uD574\uB2F9\uC2DC)\n9. Cases-- / \uC608\uC81C-- \uC2A4\uD1A0\uB9AC\n```\n\n---\n\n## \uAE00\uB85C\uBC8C CSS \uD074\uB798\uC2A4\n\n`apps/docs/app/global.css`\uC5D0 \uC815\uC758:\n\n| \uD074\uB798\uC2A4 | \uC6A9\uB3C4 |\n|--------|------|\n| `sb-code-section` | \uCF54\uB4DC \uC139\uC158 \uCEE8\uD14C\uC774\uB108 (`<section>`) |\n| `sb-code-block` | SyntaxHighlighter\uC758 `className` |\n| `sb-table` | \uD14C\uC774\uBE14 \uC2A4\uD0C0\uC77C |\n";

// src/features/gen-storybook/assets/rules/index.ts
var genStorybookPromptRules = [
  sharedFeNamingRuleReference,
  sharedFeCodingConventionRuleReference,
  createPromptMarkdownFileAsset((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)), "src/features/gen-storybook/assets/rules/fe/storybook-guide.md")
];
var genStorybookRules = [
  sharedFeNamingRule,
  sharedFeCodingConventionRule,
  storybook_guide_default
];
var genStorybookRuleAssets = {
  codingConventionRule: sharedFeCodingConventionRule,
  namingRule: sharedFeNamingRule,
  storybookGuideRule: storybook_guide_default
};

exports.genStorybookPromptRules = genStorybookPromptRules;
exports.genStorybookRuleAssets = genStorybookRuleAssets;
exports.genStorybookRules = genStorybookRules;
