-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #51 from Wannabe-Woowa-Article/lurgi
- Loading branch information
Showing
1 changed file
with
179 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(<ToolbarMenu items={items} />); | ||
|
||
// 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% μΆκ° κ°μ!) | ||
- νΉμ λ·°ν¬νΈ, ν λ§, λ‘μΌμΌμ λ§μΆ μ€ν 리 μμ±μ μλ‘μ΄ λ°©μ |