diff --git a/Aug/article/Server-Component copy.md b/Aug/article/Server-Component copy.md new file mode 100644 index 0000000..b6d286c --- /dev/null +++ b/Aug/article/Server-Component copy.md @@ -0,0 +1,179 @@ +## ๐Ÿ”— [Storybook 8.2](https://storybook.js.org/blog/storybook-8-2/) + +### ๐Ÿ—“๏ธ ๋ฒˆ์—ญ ๋‚ ์งœ: 2024.08.19 + +### ๐Ÿงš ๋ฒˆ์—ญํ•œ ํฌ๋ฃจ: ๋Ÿฌ๊ธฐ(๋ฐ•์ •์šฐ) + +--- + +## Storybook 8.2 + +Storybook์€ ์„ธ๊ณ„์ ์ธ ๋””์ž์ธ ์‹œ์Šคํ…œ(Carbon, Polaris, Fluent, Lightning ๋“ฑ) ๋’ค์—์„œ ํ™œ์•ฝํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ํ”ํžˆ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ž‘์€ ๋‹จ์œ„์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐ๋ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ UI ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์–‘ํ•œ ํฌ๊ธฐ์™€ ํ˜•ํƒœ๋กœ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. + +Faire, Yoobic, Monday.com์˜ ํŒ€๋“ค์€ Storybook์„ ์‡ผํ•‘ ์นดํŠธ, ๋Œ€์‹œ๋ณด๋“œ, ์ฑ„ํŒ… ์œ„์ ฏ, ๋‹ฌ๋ ฅ, ์ „์ฒด ํŽ˜์ด์ง€ ๋“ฑ๊ณผ ๊ฐ™์€ "์ œํ’ˆ UI"๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ์ฃผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋“ค์€ ๋ณต์žกํ•˜๊ณ  ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๋Š” ์ปดํฌ๋„ŒํŠธ๋กœ, ๋†’์€ ํ’ˆ์งˆ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœํŒ€์€ ์•ˆ์ •์„ฑ์„ ํ™•๋ณดํ•˜๊ณ  ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” Storybook์—์„œ ํ…Œ์ŠคํŠธ ๊ธฐ๋Šฅ์„ ๋”์šฑ ๊ฐ•ํ™”ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์˜ค๋Š˜, ์šฐ๋ฆฌ๋Š” ํƒ€ํ˜‘ ์—†๋Š” ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ๋ฅผ ํ–ฅํ•œ ์—ฌ์ •์˜ ๋‹ค์Œ ๋‹จ๊ณ„์ธ Storybook 8.2๋ฅผ ๋ฐœํ‘œํ•˜๊ฒŒ ๋˜์–ด ๋งค์šฐ ๊ธฐ์ฉ๋‹ˆ๋‹ค. + +### Storybook 8.2 ์ฃผ์š” ๊ธฐ๋Šฅ: + +- ๐Ÿช ์ธ๊ธฐ ์žˆ๋Š” ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ ๋„๊ตฌ๋“ค๊ณผ ๋™๋“ฑํ•œ ์ˆ˜์ค€์˜ ์ƒˆ๋กœ์šด ํ…Œ์ŠคํŠธ ํ›… +- ๐Ÿงณ ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ ๋ฐ ๋ฌธ์„œํ™” ๋„๊ตฌ์—์„œ๋„ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํœด๋Œ€ ๊ฐ€๋Šฅํ•œ ์Šคํ† ๋ฆฌ +- ๐Ÿ“ฆ ์ข…์†์„ฑ ์ถฉ๋Œ์„ ์ค„์ด๊ธฐ ์œ„ํ•œ ํŒจํ‚ค์ง€ ํ†ตํ•ฉ +- ๐Ÿ›ผ ์ƒˆ ์‚ฌ์šฉ์ž๊ฐ€ ์‰ฝ๊ฒŒ ์ ์‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ์˜จ๋ณด๋”ฉ ๊ณผ์ • ๊ฐ„์†Œํ™” +- โœจ ๋” ๋‚˜์€ ๋ฌธ์„œ ์ œ๊ณต์„ ์œ„ํ•œ ์ƒˆ๋กญ๊ฒŒ ๊ฐœ์„ ๋œ ์›น์‚ฌ์ดํŠธ +- ๐Ÿ’ฏ ์ˆ˜๋ฐฑ ๊ฐ€์ง€์˜ ์ถ”๊ฐ€ ๊ฐœ์„ ์‚ฌํ•ญ + +### ์ƒˆ๋กœ์šด ํ…Œ์ŠคํŠธ ํ›… + +Jest, Vitest, Playwright, Cypress์™€ ๊ฐ™์€ ์ตœ์‹  ํ…Œ์ŠคํŠธ ๋„๊ตฌ๋“ค์€ ๋ชจ๋‘ ๋น„์Šทํ•œ ํ…Œ์ŠคํŠธ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ๋ฒ•์—๋Š” ์•ฝ๊ฐ„์˜ ์ฐจ์ด๊ฐ€ ์žˆ์ง€๋งŒ, ๊ธฐ๋ณธ์ ์ธ ํ…Œ์ŠคํŠธ ํ›…์€ ๋ชจ๋‘ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.`before/afterAll`, `before/afterEach`, `describe`, `test`. + +Storybook์€ ์ž์ฒด ์Šคํ† ๋ฆฌ ๋ฌธ๋ฒ•์ธ Component Story Format(CSF)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. CSF๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ค์–‘ํ•œ ์ƒํƒœ์—์„œ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ณด์—ฌ์ฃผ๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. Storybook 6.4์—์„œ๋Š” ์ƒํ˜ธ์ž‘์šฉ๊ณผ ๊ฒ€์ฆ์„ ์œ„ํ•ด play ๊ธฐ๋Šฅ์„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. + +```jsx +// ToolbarMenu.stories.js +import { fn, expect } from "@storybook/test"; +import { ToolbarMenu } from "./ToolbarMenu"; + +export default { component: ToolbarMenu }; +export const Disabled = { + args: { disabled: true, onSelected: fn() }, + play: async ({ canvas, args }) => { + await userEvent.click(canvas.getByRole("button")); + expect(args.onSelected).not.toHaveBeenCalled(); + }, +}; +``` + +์ด play ๊ธฐ๋Šฅ์„ ํ†ตํ•ด Storybook์—์„œ๋„ ๋งŽ์€ Jasmine ์Šคํƒ€์ผ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ๋‹ค ์ง€์›ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์—ˆ๊ณ , ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ ๋„๊ตฌ์—์„œ ์ „ํ™˜ํ•ด ์˜จ ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ๋Š” CSF ๋ฌธ๋ฒ•์ด ์ต์ˆ™ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. + +์ด์ œ Storybook 8.2์—์„œ๋Š” `before` ํ›…(ํด๋ฆฐ์—… ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ `after` ํ›…์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ)๊ณผ React, Vue 3, Svelte์šฉ `play`์˜ ์„ ํƒ์  `mount` ์ธ์ˆ˜๋ฅผ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ด์ œ๋Š” โ€˜Arrangeโ€™, โ€˜Actโ€™, โ€˜Assertโ€™๋ฅผ ํ•˜๋‚˜์˜ play ํ•จ์ˆ˜ ๋‚ด์—์„œ ํ•  ์ˆ˜ ์žˆ์–ด, Jasmine ์Šคํƒ€์ผ ๋„๊ตฌ์™€ ๋™์ผํ•œ ํ๋ฆ„์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```jsx +// ToolbarMenu.stories.jsx +import { fn, expect } from "@storybook/test"; +import { ToolbarMenu } from "./ToolbarMenu"; + +export default { + component: ToolbarMenu, +}; + +export const Disabled = { + args: { disabled: true, onSelected: fn() }, + play: async ({ mount, args }) => { + // Arrange + const items = await loadItems(10); + const canvas = await mount(); + + // Act + await userEvent.click(canvas.getByRole("button")); + + // Assert + expect(canvas.getAllByRole("button").length).toBe(items.length); + expect(args.onSelected).not.toHaveBeenCalled(); + }, +}; +``` + +์ด๋ฒˆ ๋ณ€ํ™”๋Š” ๊ธฐ์กด์˜ ์Šคํ† ๋ฆฌ์™€ ํ˜ธํ™˜๋˜๋ฏ€๋กœ ๋ชจ๋“  ๊ธฐ์กด ์Šคํ† ๋ฆฌ๊ฐ€ ์ด์ „๊ณผ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์•”์‹œ์  ๋งˆ์šดํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์Šคํ† ๋ฆฌ ์ž‘์„ฑ ๊ถŒ์žฅ ๋ฐฉ์‹๋„ ๊ทธ๋Œ€๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•  ๋•Œ, ์ด์ œ ์ƒˆ๋กœ์šด ํ…Œ์ŠคํŠธ ํ›…์ด ์ค€๋น„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +โ€œ์ฒ˜์Œ์œผ๋กœ @storybookjs์˜ ํ”Œ๋ ˆ์ด ํ…Œ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ–ˆ์–ด์š”. ์ •๋ง ๋†€๋ผ์›Œ์š”! ์ด๋ ‡๊ฒŒ ๋น ๋ฅด๊ฒŒ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•œ ์ ์ด ์—†์–ด์š”!!โ€ โ€” @brechtilliet + +๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜์‹œ๊ณ , ๊ณง ๋‚˜์˜ฌ ์ „์ฒด ๊ธฐ๋Šฅ ๋ฐœํ‘œ์™€ ๋” ๋งŽ์€ ํ›„ํฌ ์˜ˆ์ œ๋ฅผ ๊ธฐ๋Œ€ํ•ด ์ฃผ์„ธ์š”! + +### ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์Šคํ† ๋ฆฌ (Portabel Stories) + +Storybook์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ฐœ๋ฐœํ•˜๊ณ , ๋ฌธ์„œํ™”ํ•˜๊ณ , ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐ ์ตœ๊ณ ์˜ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ JS ์ƒํƒœ๊ณ„์—๋Š” ํ›Œ๋ฅญํ•œ ๋„๊ตฌ๋“ค์ด ๋งŽ๊ณ , ์—ฌ๋Ÿฌ๋ถ„์ด ์›ํ•˜๋Š” ๋„๊ตฌ์—์„œ ์Šคํ† ๋ฆฌ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. + +8.1์—์„œ๋Š” Playwright ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ "Portable Story"๋ฅผ ์ œํ•œ์ ์œผ๋กœ ์ œ๊ณตํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ 8.2์—์„œ๋Š” React ๋ฐ Vue 3์šฉ ํœด๋Œ€ ๊ฐ€๋Šฅํ•œ ์Šคํ† ๋ฆฌ๋ฅผ ์™„์„ฑํ•˜๊ณ , ์‹คํ—˜์ ์œผ๋กœ Svelte ์ง€์›๋„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์Šคํ† ๋ฆฌ๋ฅผ ํ”„๋ ˆ์ž„์›Œํฌ์— ๋งž๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ, ํ•„์š”ํ•œ ํ…Œ์ŠคํŠธ ํ›…์„ ํฌํ•จํ•œ ์ถ”๊ฐ€ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```jsx +// Button.test.js +import { test, expect } from "vitest"; +import { screen } from "@testing-library/react"; +import { composeStories } from "@storybook/react"; + +// ๋ชจ๋“  ์Šคํ† ๋ฆฌ์™€ ์ปดํฌ๋„ŒํŠธ ์ฃผ์„์„ ์Šคํ† ๋ฆฌ ํŒŒ์ผ์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ +import * as stories from "./Button.stories"; + +// ๋ฐ˜ํ™˜๋œ ์ปดํฌ๋„ŒํŠธ๋Š” ์Šคํ† ๋ฆฌ์™€ 1:1๋กœ ๋งคํ•‘๋˜๋ฉฐ, +// ์Šคํ† ๋ฆฌ, ๋ฉ”ํƒ€, ํ”„๋กœ์ ํŠธ ์ˆ˜์ค€์˜ ๋ชจ๋“  ์ฃผ์„์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. +const { Primary, Secondary } = composeStories(stories); + +test("๊ธฐ๋ณธ ์ธ์ˆ˜๋กœ ๊ธฐ๋ณธ ๋ฒ„ํŠผ ๋ Œ๋”๋ง", async () => { + /** + * ์Šคํ† ๋ฆฌ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ํ†ตํ•ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค: + * 1. ๋กœ๋” + * 2. beforeEach + * 3. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๋“ฑ ์ฃผ์„๊ณผ ํ•จ๊ป˜ ๋ Œ๋”๋ง + * 4. play ํ•จ์ˆ˜ (mount ์‚ฌ์šฉ ์‹œ ํฌํ•จ) + * 5. cleanup (beforeEach, hooks์—์„œ) + */ + await Primary.play(); +}); +``` + +์ด API ์™ธ์—๋„, Vitest ๋ฐ Jest์—์„œ ์Šคํ† ๋ฆฌ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ๋ฌธ์„œ๋ฅผ ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”, ๊ทธ๋ฆฌ๊ณ  ๊ณง ์ „์ฒด ๊ธฐ๋Šฅ ๋ฐœํ‘œ๊ฐ€ ์žˆ์„ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. + +### ํ†ตํ•ฉ๋œ ์ข…์†์„ฑ ๊ด€๋ฆฌ + +State of JS ์„ค๋ฌธ์กฐ์‚ฌ์—์„œ 20,000๋ช… ์ด์ƒ์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ์‘๋‹ตํ•œ ๊ฒฐ๊ณผ, JS ์ƒํƒœ๊ณ„์˜ ํ๋ฆ„์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. 2022๋…„์—๋Š” ์•ฝ๊ฐ„ ํ•˜๋ฝ์„ธ์˜€์ง€๋งŒ, Storybook ๊ฐœ์„ ์„ ์œ„ํ•œ ์šฐ๋ฆฌ์˜ ๋…ธ๋ ฅ์€ 2023๋…„์— ๋น›์„ ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ์„ค๋ฌธ์กฐ์‚ฌ์—์„œ ๊ฐ€์žฅ ํฐ ๋ถˆ๋งŒ์€ ์ข…์†์„ฑ ๊ด€๋ฆฌ(๊ณผ๋„ํ•˜๊ฒŒ ํฐ ์„ค์น˜ ํฌ๊ธฐ, ๊ธด ์„ค์น˜ ์‹œ๊ฐ„, ๋ฒ„์ „ ์ถฉ๋Œ ๋“ฑ)์—ˆ์Šต๋‹ˆ๋‹ค. + +8.2์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. 18๊ฐœ์˜ ํŒจํ‚ค์ง€๋ฅผ ํ•˜๋‚˜์˜ ํ•ต์‹ฌ ํŒจํ‚ค์ง€(storybook)์™€ ๋นŒ๋”/๋ Œ๋”๋Ÿฌ/์• ๋“œ์˜จ์„ ์œ„ํ•œ ์œ„์„ฑ ํŒจํ‚ค์ง€๋กœ ํ†ตํ•ฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” Vite์˜ ํŒจํ‚ค์ง€ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฅด๋Š” ๋น„ํŒŒ๊ดด์  ๋ณ€ํ™”์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ Storybook์˜ ๋งŽ์€ ์ข…์†์„ฑ์„ ๋ฒˆ๋“ค๋งํ•˜์—ฌ ๋ฒ„์ „ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค. + +์šฐ๋ฆฌ๋Š” ๋˜ํ•œ Ecosystem Performance(e18e) ํ”„๋กœ์ ํŠธ์˜ ๋ฆฌ๋”์ธ James Garbutt์™€ ํ˜‘๋ ฅํ•˜์—ฌ ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋” ์ž‘๊ณ  ๋น ๋ฅด๋ฉฐ ํ˜„๋Œ€์ ์ธ ๋ฒ„์ „์œผ๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ–ˆ์Šต๋‹ˆ๋‹ค(์•ˆ๋…• doctrine! ๐Ÿ‘‹). + +์ด ์ž‘์—…์€ ์•„์ง ์ดˆ๊ธฐ ๋‹จ๊ณ„์ด์ง€๋งŒ, ํ˜„์žฌ๊นŒ์ง€ ์„ค์น˜ ํฌ๊ธฐ์™€ ์‹œ๊ฐ„์„ ์•ฝ 20% ์ค„์˜€์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ํ†ตํ•ฉ ๊ตฌ์กฐ๋Š” ํ–ฅํ›„ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ ๋ฐœํŒ์ด ๋˜์–ด, 8.3 ๋ฐ ๊ทธ ์ดํ›„์—๋Š” ๋” ํฐ ๊ฐœ์„ ์„ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ๊ฐ„์†Œํ™”๋œ ์˜จ๋ณด๋”ฉ + +๋˜ ๋‹ค๋ฅธ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์€ ์˜จ๋ณด๋”ฉ ๊ฒฝํ—˜์ž…๋‹ˆ๋‹ค. ๋งค์ฃผ ์ˆ˜์ฒœ ๋ช…์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ Storybook์„ ์ฒ˜์Œ ์‚ฌ์šฉํ•ด๋ณด์ง€๋งŒ, ์„ค์น˜๋ถ€ํ„ฐ ์„ฑ๊ณต์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ์ด๋ฅด๊ธฐ๊นŒ์ง€๋Š” ์—ฌ๋Ÿฌ ๋‚œ๊ด€์ด ์žˆ์Šต๋‹ˆ๋‹ค. Storybook 8.2์—์„œ๋Š” ์˜จ๋ณด๋”ฉ ๊ฒฝํ—˜์„ ์ƒˆ๋กญ๊ฒŒ ๊ฐœ์„ ํ•˜๊ณ , React์—์„œ Vue 3 ๋ฐ Angular๋กœ ํ™•์žฅํ•˜์—ฌ ์‚ฌ์šฉ์ž๋ฅผ ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉํ–ฅ์œผ๋กœ ์•ˆ๋‚ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. + +์ด ๊ฒฝํ—˜์€ 8.x ๋ฒ„์ „์—์„œ ๋” ํ™•์žฅ๋˜์–ด, ํ”„๋กœ์ ํŠธ์—์„œ Storybook์„ ๋” ์‰ฝ๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +### ์ƒˆ๋กญ๊ฒŒ ๊ฐœ์„ ๋œ ๋ฌธ์„œ ์‚ฌ์ดํŠธ + +Storybook์€ ์ƒˆ๋กญ๊ฒŒ ๊ฐœํŽธ๋œ ๋ฌธ์„œ ์‚ฌ์ดํŠธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค! ์ด ์‚ฌ์ดํŠธ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‚ด์šฉ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค: + +- โœจ Storybook์˜ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ž˜ ๋ณด์—ฌ์ฃผ๋Š” ์ƒˆ๋กœ์šด ๋ฐ˜์‘ํ˜• ์• ๋‹ˆ๋ฉ”์ด์…˜๊ณผ ํ•จ๊ป˜ํ•œ ์ƒˆ๋กœ์šด ํ™ˆํŽ˜์ด์ง€ +- ๐Ÿ“š Next.js, SvelteKit ๋“ฑ ๊ฐ ํ”„๋ ˆ์ž„์›Œํฌ๋ณ„ ์ „์šฉ ๋žœ๋”ฉ ํŽ˜์ด์ง€๊ฐ€ ์žˆ๋Š” ์ƒˆ๋กœ์šด ๋ฌธ์„œ ํ™ˆ +- ๐ŸŒ™ ์‹œ์Šคํ…œ ์„ค์ •์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ ์ „ํ™˜๋˜๋Š” ๋ฌธ์„œ์˜ ๋ผ์ดํŠธ/๋‹คํฌ ๋ชจ๋“œ +- ๐Ÿงฑ ๋” ๋น ๋ฅธ ๊ฐœ์„ ์„ ์œ„ํ•œ ์ถ”๊ฐ€ ์ž‘์—…์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ๊ธฐ์ดˆ ์ž‘์—… + +### ์ˆ˜๋ฐฑ ๊ฐ€์ง€์˜ ์ถ”๊ฐ€ ๊ฐœ์„ ์‚ฌํ•ญ + +์œ„์˜ ๊ธฐ๋Šฅ ์™ธ์—๋„, ๋ชจ๋“  Storybook ๋ฆด๋ฆฌ์Šค์—๋Š” ๋ชจ๋“  ์ˆ˜์ค€์—์„œ ์ˆ˜๋ฐฑ ๊ฐ€์ง€์˜ ๊ฐœ์„ ์‚ฌํ•ญ๊ณผ ๋ฒ„๊ทธ ์ˆ˜์ •์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ช‡ ๊ฐ€์ง€ ํ•˜์ด๋ผ์ดํŠธ: + +- โœ… Webpack5/Vite: ์†Œ์Šค ๋งต ์ˆ˜์ • (#27171, @valentinpalkovic์—๊ฒŒ ๊ฐ์‚ฌ) +- โœ… Angular: ์†Œ์Šค ๋ฏธ๋ฆฌ๋ณด๊ธฐ์˜ ํ˜•์‹ ๊ตฌ์„ฑ ํ—ˆ์šฉ (#28305, @64BitAsura์—๊ฒŒ ๊ฐ์‚ฌ) +- โœ… CLI: init์— --no-dev ์˜ต์…˜ ์ถ”๊ฐ€ (#26918, @fastfrwrd์—๊ฒŒ ๊ฐ์‚ฌ) +- โœ… CLI: ์ƒˆ ํ”„๋กœ์ ํŠธ์— @storybook/addon-svelte-csf ํฌํ•จ (#27070, @benmccann์—๊ฒŒ ๊ฐ์‚ฌ) +- โœ… Core: watchStorySpecifiers๋กœ ์ธํ•œ ์‹œ์ž‘ ์ง€์—ฐ ์ˆ˜์ • (#27016, @heyimalex์—๊ฒŒ ๊ฐ์‚ฌ) +- โœ… Vue3: ์ƒˆ๋กœ์šด ํ•˜์ด๋“œ๋ ˆ์ด์…˜ ๋ถˆ์ผ์น˜ ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ํ”Œ๋ž˜๊ทธ ํ™œ์„ฑํ™” (#27192, @Cherry์—๊ฒŒ ๊ฐ์‚ฌ) + +### ์ง€๊ธˆ ๋ฐ”๋กœ ์‚ฌ์šฉํ•ด๋ณด์„ธ์š”! + +Storybook 8.2๋Š” ์˜ค๋Š˜๋ถ€ํ„ฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ ํ”„๋กœ์ ํŠธ์—์„œ ์‹œ๋„ํ•ด๋ณด์„ธ์š” + +``` +npx storybook@latest init +``` + +๋˜๋Š” ๊ธฐ์กด ํ”„๋กœ์ ํŠธ๋ฅผ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜์„ธ์š” + +``` +npx storybook@latest upgrade +``` + +๋งŒ์•ฝ 7.x ๋ฒ„์ „์—์„œ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋Š” ๊ฒฝ์šฐ, ๋„์›€์ด ๋  ๊ฐ€์ด๋“œ๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ „ ๋ฒ„์ „์—์„œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๊ฐ€์ด๋“œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ๋‹ค์Œ ๋‹จ๊ณ„ + +์šฐ๋ฆฌ๋Š” 8.3์„ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๊ฐ€์ง€๋ฅผ ์ค€๋น„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค: + +- ๋ฒˆ๊ฐœ์ฒ˜๋Ÿผ ๋น ๋ฅธ ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ Vitest์™€์˜ ํ†ตํ•ฉ +- Next.js ํ”„๋ ˆ์ž„์›Œํฌ์— Vite ์ง€์› ์ถ”๊ฐ€๋กœ Vitest ํ˜ธํ™˜์„ฑ๊ณผ ๋” ๋‚˜์€ ๊ฐœ๋ฐœ ๊ฒฝํ—˜ ์ œ๊ณต +- ์ƒํ˜ธ์ž‘์šฉํ˜• ์‚ฌ์ด๋“œ๋ฐ” ํ•„ํ„ฐ๋ง์„ ์œ„ํ•œ UI๊ฐ€ ํฌํ•จ๋œ ์Šคํ† ๋ฆฌ ํƒœ๊ทธ +- ์„ค์น˜ ํฌ๊ธฐ๋ฅผ ๋”์šฑ ์ค„์ด๊ธฐ(8.3-alpha๋ฅผ ์‹œ๋„ํ•ด๋ณด์„ธ์š”, 40% ์ถ”๊ฐ€ ๊ฐ์†Œ!) +- ํŠน์ • ๋ทฐํฌํŠธ, ํ…Œ๋งˆ, ๋กœ์ผ€์ผ์— ๋งž์ถ˜ ์Šคํ† ๋ฆฌ ์ž‘์„ฑ์˜ ์ƒˆ๋กœ์šด ๋ฐฉ์‹