naver/fe-news ๋‰ด์Šค๋ ˆํ„ฐ ๋ทฐ์–ด (๋น„๊ณต์‹)

๋ชฉ์ฐจ
๋ชฉ์ฐจ

    2023-08

    ๐Ÿ“š ๋งํฌ & ์ฝ์„ ๊ฑฐ๋ฆฌ

    Beyond Browsers: The Longterm Future of JavaScript Standards

    ๊ทธ๊ฐ„ JavaScript๋Š” ์ฃผ๋กœ ์›น์—์„œ์˜ ์‚ฌ์šฉ์„ ์œ„ํ•œ ์–ธ์–ด๋กœ ๋ฐœ์ „ํ•ด ์™”๊ณ , ECMAScript ํ‘œ์ค€ ๋˜ํ•œ ๋ธŒ๋ผ์šฐ์ € ๋ฒค๋”๋“ค์˜ ์š”๊ตฌ์— ๋”ฐ๋ผ ์ฃผ๋„๋˜์–ด ์™”๋‹ค. ํ•˜์ง€๋งŒ ์ด์ œ๋Š” ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋ฒ—์–ด๋‚œ JavaScript๊ฐ€ ์ผ๋ฐ˜ํ™”๋˜๊ณ  ์žˆ์ง€๋งŒ, ์•„์ง๋„ ๋Ÿฐํƒ€์ž„๋“ค์€ ๋ธŒ๋ผ์šฐ์ €์˜ JavaScript ์—”์ง„์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

    ์•ผ์‹ฌ์ฐฌ ์•„์ด๋””์–ด ์ค‘ ํ•˜๋‚˜๋Š” JavaScript ๋Ÿฐํƒ€์ž„์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒƒ์„ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•˜๋Š” ์‚ฌ์–‘์„ ํ‘œ์ค€ํ™”ํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ, ์ด๋Š” JavaScript ์‚ฌ์šฉ์˜ ํ™•์žฅ๊ณผ ๋ณดํŽธํ™”์— ๋”ฐ๋ผ ๋งŽ์€ ์ด๋“ค์ด ์ž์‹ ์˜ ํŠน์ • ์š”๊ตฌ ์‚ฌํ•ญ์— ๋งž๋Š” ๋Ÿฐํƒ€์ž„(๊ฐ€๋Šฅํ•œ ๋” ์ž‘์€)์„ ๋งŒ๋“ค๊ณ  ์‹ถ์–ด ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    Meet Jeff Delaney: The Mastermind Behind Fireship.io

    ์•„๋งˆ๋„ youtube์—์„œ ํ•œ ๋ฒˆ์ฏค์€ "100 seconds of Code" ์‹œ๋ฆฌ์ฆˆ๋กœ ์œ ๋ช…ํ•œ Fireship ์ฑ„๋„์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๋ณธ ๊ฒฝํ—˜์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค.

    ์งง๊ณ  ์‰ฝ๊ฒŒ ์ฃผ์š”ํ•œ ๊ธฐ์ˆ  ํŠธ๋ Œ๋“œ๋ฅผ ํ’€์–ด๋‚ด๋Š” ์ด ์ฑ„๋„์˜ ์šด์˜์ž์ธ Jeff Delaney์˜ ์ธํ„ฐ๋ทฐ๋ฅผ ํ†ตํ•ด ํŒŒ์ผ๋Ÿฟ๊ณผ ํšŒ๊ณ„์‚ฌ๋ฅผ ๊ฟˆ๊พธ๋˜ ๊ทธ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋…ํ•™์œผ๋กœ ์›น ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์—ˆ๋Š”์ง€๋ฅผ ๋“ค์–ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    Invisible Details of Interaction Design

    ๋””์ž์ธ์€ ๊ณผํ•™์ด ์—†๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋А๊ปด์ง€๊ณ , ์˜ค์ง ๋А๋‚Œ๊ณผ ์ง๊ด€๋งŒ์ด ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค. ์ธํ„ฐ๋ ‰์…˜ ๋””์ž์ธ์„ ๊ฒ€์ƒ‰ํ•ด ๋ณด๋ฉด, ์‚ฌ์šฉ์ž ํŽ˜๋ฅด์†Œ๋‚˜, ์Šคํ† ๋ฆฌ๋ณด๋“œ, UX/UI๋กœ ํ‘œํ˜„๋œ ๋ฒค ๋‹ค์ด์–ด๊ทธ๋žจ ๋“ฑ๋งŒ ์ž”๋œฉ ๋ณด๊ฒŒ ๋œ๋‹ค.

    ์ด ๊ธ€์€ ์ž์ฃผ ์‚ฌ์šฉ๋˜์ง€๋งŒ ๊ฑฐ์˜ ์ƒ๊ฐ๋˜์ง€ ์•Š๋Š” ๋ช‡๋ช‡ ์ƒํ˜ธ์ž‘์šฉ์˜ ๋ณด์ด์ง€ ์•Š๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•œ ์„ธ๋ถ€์  ๊ด€์ฐฐ์„ ๋‹ค๋ฃจ๊ณ  ์žˆ๋‹ค.

    What does the image decoding attribute actually do?

    ํƒœ๊ทธ์— "decoding" ์†์„ฑ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ๋Š”๊ฐ€?

    ์ด ์†์„ฑ์€ ์ด๋ฏธ์ง€๋ฅผ ์–ด๋–ป๊ฒŒ ๋””์ฝ”๋”ฉ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ํžŒํŠธ๋ฅผ ๊ธฐ์ˆ ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋™๊ธฐ(sync) ๋˜๋Š” ๋น„๋™๊ธฐ(async) ๊ฐ’์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ ๊ฐ’์€ "auto"๋กœ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๋ฐฉ์‹์„ ์„ ํƒํ•˜๋„๋ก ํ•œ๋‹ค. ์ด๋ฅผ ๊ธฐ๋ฐ˜ํ•ด ๋งŽ์€ ๊ณณ์—์„œ๋Š” ํฌ๊ธฐ๊ฐ€ ํฐ ์ด๋ฏธ์ง€๊ฐ€ ๋ Œ๋”๋ง์„ ๋ธ”๋ก ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ด ๊ฒฝ์šฐ ์™€ ๊ฐ™์ด ๋น„๋™๊ธฐ ๋””์ฝ”๋”ฉ์„ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•˜๊ธฐ๋„ ํ•œ๋‹ค.

    ๊ทธ๋Ÿฌ๋‚˜, ๊ณผ์—ฐ ๊ทธ๋Ÿฌํ• ๊นŒ? ์ด๋Ÿฌํ•œ ๊ถŒ์žฅ์€ ์ด๋ฏธ์ง€์˜ ๋””์ฝ”๋”ฉ์ด ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ์„ ๊ฐ€์ •ํ•˜์ง€๋งŒ, ์˜ค๋Š˜๋‚ ์˜ ๋ชจ๋˜ ๋ธŒ๋ผ์šฐ์ €๋“ค์€ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ์•„๋‹Œ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋””์ฝ”๋”ฉ ํ•œ๋‹ค.

    Lit Labs: SSR

    Web Components ๊ธฐ๋ฐ˜์˜ ํ”„๋ ˆ์ž„์›Œํฌ์ธ Lit์˜ ์‹คํ—˜์ ์ธ SSR ํŒจํ‚ค์ง€(@lit-labs/ssr)์— ๋Œ€ํ•œ ์†Œ๊ฐœ ์˜์ƒ์ด๋‹ค.

    [์ฐธ๊ณ ] Reddit์˜ ์ฐจ๊ธฐ ๋ชจ๋ฐ”์ผ ์ „์šฉ UI ๋ฒ„์ „์ธ https://sh.reddit.com ์€ Lit์„ ์‚ฌ์šฉํ•ด ๊ฐœ๋ฐœ๋˜์—ˆ๋‹ค.

    State Of Npm 2023

    2๊ฐœ์˜ ์‹œ๋ฆฌ์ฆˆ๋กœ ๊ตฌ์„ฑ๋œ ๊ธ€์—์„œ๋Š” npm์˜ ํ˜„์žฌ ์ƒํƒœ์™€ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ๋Œ€ํ•œ ํฅ๋ฏธ๋กœ์šด ๋‹ค์–‘ํ•œ ํ†ต๊ณ„ ๋“ฑ์„ ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    I feel bittersweet sharing iโ€™m leaving my job at meta in a few weeks

    ์ง€๋‚œ 7๋…„๊ฐ„ React์˜ ์•„์ด์ฝ”๋‹‰ ํ•œ ๊ฐœ๋ฐœ์ž๋กœ ํ™œ๋™ํ–ˆ๋˜ Dan Abramov๊ฐ€ Meta์—์„œ ํ‡ด์‚ฌํ•  ๊ณ„ํš์ด๋ผ๊ณ  ๋ฐํ˜”๋‹ค.

    ์ง€๋‚œ ๋ช‡ ๋…„๊ฐ„์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ๋ณด๋‹จ ๊ฐœ๋ฐœํŒ€๊ณผ ์ปค๋ฎค๋‹ˆํ‹ฐ, ์ƒํƒœ๊ณ„๋ฅผ ์ž‡๋Š” ๊ฐ€๊ต ์—ญํ• ์— ์ง‘์ค‘ํ•ด ์™”์—ˆ์ง€๋งŒ ์–ด๋А ์ˆœ๊ฐ„ ์žฌ๋ฏธ๋ฅผ ์žƒ์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค. ๋” ๋งŽ์€ ๋‚ด์šฉ์€ ํŠธ์œ— ์Šค๋ ˆ๋“œ๋ฅผ ํ†ตํ•ด ์†ŒํšŒ๋ฅผ ์ฝ์–ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    JSNation 2023

    ์ง€๋‚œ 6์›” 1~5์ผ, ๋„ค๋œ๋ž€๋“œ ์•”์Šคํ…Œ๋ฅด๋‹ด์—์„œ ์—ด๋ ธ๋˜ JSNation 2023 ์ฝ˜ํผ๋Ÿฐ์Šค์˜ ๋ชจ๋“  ์„ธ์…˜์— ๋Œ€ํ•œ ๋™์˜์ƒ์ด ๊ณต๊ฐœ๋˜์—ˆ๋‹ค.

    SolidJS ๊ฐœ๋ฐœ์ž์ธ Ryan Carnato, Webpack๊ณผ Turbopack ๊ฐœ๋ฐœ์ž์ธ Tobias Koppers, Angular ๊ฐœ๋ฐœ์ž์ธ Miลกko Hevery ๋“ฑ ์œ ๋ช…ํ•œ ๊ฐœ๋ฐœ์ž๋“ค์˜ ๋ฐœํ‘œ๋ฅผ ๋“ค์–ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    UX/UI ๋ ˆ๋ฒจ ํ…Œ์ŠคํŠธ

    ๊ฐ„๋‹จํ•œ UX/UI ๋””์ž์ธ ์‚ฌ๋ก€๋“ค์— ๋Œ€ํ•œ ์„ ํƒ์„ ํ†ตํ•ด ์ž์‹ ์˜ UX/UI ๋ ˆ๋ฒจ์„ ํ…Œ์ŠคํŠธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ฐ ํ•ญ๋ชฉ๋ณ„๋กœ ์ข‹์€ UX/UI๊ฐ€ ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•œ ์„ค๋ช…์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    Polymorphic ํ•œ React ์ปดํฌ๋„ŒํŠธ ๋งŒ๋“ค๊ธฐ

    <PolymorphicButton as="a" href="https://naver.com">
      I am anchor
    </PolymorphicButton>
    <PolymorphicButton as="button" onClick={handleClick}>
      I am button
    </PolymorphicButton>
    <PolymorphicButton as="span">
      I am span
    </PolymorphicButton>
    

    MUI, Mantine ๋“ฑ์˜ components library์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ polymorphicํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณธ๋‹ค.

    [์ฐธ๊ณ ] Polymorphic: ๋‹คํ˜•์„ฑ. ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง„๋‹ค๋Š” ์˜๋ฏธ๋ฅผ ๊ฐ€์ง„ ๊ทธ๋ฆฌ์Šค์–ด์—์„œ ์œ ๋ž˜๋œ ๋‹จ์–ด.

    Polymorphic ํ•œ ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์–‘ํ•œ Semantic์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š”, ๋‹ค์–‘ํ•œ ์†์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š”, ๋‹ค์–‘ํ•œ ์Šคํƒ€์ผ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋กœ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋‹ค.

    Multiple Layers of Abstraction in Design Systems

    ๋””์ž์ธ ์‹œ์Šคํ…œ ์ปดํฌ๋„ŒํŠธ, ํ˜น์€ ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ๋ผ๋ฉด ์ˆ˜๋งŽ์€ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถฉ์กฑ ์‹œ์ผœ์•ผ ํ•˜๋ฉฐ, ์•ž์œผ๋กœ ๋” ๋งŽ์€ ์š”๊ตฌ์‚ฌํ•ญ ๋ฐ˜์˜ ๋ฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„์— ์ง๋ฉดํ•˜๊ฒŒ ๋  ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์„ ์ž˜ ํ•ด๊ฒฐํ•ด ๋‚˜๊ฐ€๋ ค๋ฉด '์ด๊ฒƒ ์•„๋‹ˆ๋ฉด ์ €๊ฒƒ'์ด๋ผ๋Š” ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๋‹ค.

    ์ด ๊ธ€์—์„œ ์ œ์‹œํ•œ ํ•ด๊ฒฐ์ฑ…์€ ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ๊ณ„์ธต์˜ ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ๋ฅผ ํŒจ์‹ฑํ•˜๊ณ  ๋ Œ๋”๋ง ํ•˜๋Š” config ๋ฐฉ์‹, ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋Š” slot ๋ฐฉ์‹, ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ ๋ฐ ์Šคํƒ€์ผ๋ง์„ ์ง์ ‘ ์œ„์ž„ํ•˜๋Š” custom ๋ฐฉ์‹ ์ด ์„ธ ๊ฐ€์ง€์˜ ์ถ”์ƒ ๊ณ„์ธต์œผ๋กœ ์ปดํฌ๋„ŒํŠธ์˜ ํ™œ์šฉ๋„์™€ ์žฌ์‚ฌ์šฉ์„ฑ์˜ ํ–ฅ์ƒ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

    ๐Ÿ•น ํŠœํ† ๋ฆฌ์–ผ

    Demystifying React Server Components with NextJS 13 App Router

    RSC๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๊ฑฐ๋‚˜ ๋˜๋Š” RSC๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ๋” ๋งŽ์ด ์ดํ•ดํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋ฅผ ๋Œ€์ƒ์œผ๋กœ Next.js 13์˜ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋…๊ณผ ์ฝ”๋“œ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ์ดํ•ดํ•ด ๋ณผ ์ˆ˜ ์žˆ๋Š” ํŠœํ† ๋ฆฌ์–ผ์ด๋‹ค.

    What is Hydration

    Hydration์€ ์˜ค๋Š˜๋‚  ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์—์„œ ๋นˆ๋ฒˆํ•˜๊ฒŒ ํ™œ์šฉ๋˜๋Š” ๊ฐœ๋…์ด๋‹ค. ์ด๊ฒƒ์ด ๋ฌด์—‡์ด๋ฉฐ, ์–ด๋–ป๊ฒŒ ์—ฌ๊ธฐ๊นŒ์ง€ ๋ฐœ์ „ํ•ด ์™”๋Š”์ง€๋ฅผ Angular์˜ ๊ฐœ๋ฐœ์ž์˜€๋˜ Miลกko Hevery๊ฐ€ ์„ค๋ช…ํ•˜๋Š” ํŠœํ† ๋ฆฌ์–ผ์„ ํ†ตํ•ด ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    [์ฐธ๊ณ ] ์ถ”๊ฐ€์ ์œผ๋กœ ๋‹ค์Œ ๋งํฌ๋ฅผ ํ†ตํ•ด Dehydrate์™€ hydrate์— ๋Œ€ํ•ด ๋ณด๋‹ค ์‰ฝ๊ฒŒ ๊ฐœ๋…์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

    ๐—ช๐—ต๐—ฎ๐˜ ๐—ต๐—ฎ๐—ฝ๐—ฝ๐—ฒ๐—ป๐˜€ ๐˜„๐—ต๐—ฒ๐—ป ๐˜†๐—ผ๐˜‚ ๐˜๐˜†๐—ฝ๐—ฒ ๐—ฎ ๐—จ๐—ฅ๐—Ÿ ๐—ถ๐—ป๐˜๐—ผ ๐˜†๐—ผ๐˜‚๐—ฟ ๐—ฏ๐—ฟ๐—ผ๐˜„๐˜€๐—ฒ๐—ฟ?

    ๋ธŒ๋ผ์šฐ์ €์— URL์„ ์ž…๋ ฅํ•˜๋ฉด ์–ด๋–ค ๊ณผ์ •์ด ์ผ์–ด๋‚ ๊นŒ? ํŠธ์œ—์— ํฌํ•จ๋œ ๊ทธ๋ฆผ๊ณผ ์„ค๋ช…์„ ํ†ตํ•ด ๋น ๋ฅด๊ฒŒ ์ดํ•ดํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    Understanding SVG Paths

    ์ด์ „์— SVG ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณธ ์ ์ด ์žˆ๋‹ค๋ฉด, <path> ์š”์†Œ์˜ d ์†์„ฑ์— ์ •์˜๋œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฒฝ๋กœ ๊ฐ’์„ ํ†ตํ•ด ๊ทธ๋ฆผ์ด ๊ทธ๋ ค์ง„๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ณ  ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•œ ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๋‹ค์–‘ํ•œ path ๊ตฌ์„ฑ๊ณผ ๊ทธ๋ฆผ์ด ๊ทธ๋ ค์ง€๋Š” ๊ณผ์ •์„ ๋ฐฐ์šธ ์ˆ˜ ์žˆ๋‹ค.

    ๐Ÿ“ฆ ์ฝ”๋“œ์™€ ๋„๊ตฌ

    ComponentizeJS

    ComponentizeJS๋Š” ์‹คํ—˜์  ๋„๊ตฌ๋กœ ์ž„๋ฒ ๋“œ ๋œ SpiderMonkey JS ์—”์ง„์„ ์‚ฌ์šฉํ•ด, JavaScript ์ฝ”๋“œ๋ฅผ WebAssembly Component๋กœ ์ƒ์„ฑํ•ด ์ค€๋‹ค.

    import { componentize } from '@bytecodealliance/componentize-js';
    import { writeFile } from 'node:fs/promises';
    
    const { component } = await componentize(
    // WIT์— ๋ถ€ํ•ฉํ•˜๋Š” JS ์ฝ”๋“œ
    `export function fn () {}`,
    
    // Wasm Interface Type(WIT) ํ˜•์‹์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜
    // https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md
    `default world test {
        export fn: func()
      }
    `);
    
    // wasm ํŒŒ์ผ๋กœ ์ปดํŒŒ์ผ
    await writeFile('test.component.wasm', component);
    

    dnt - Deno to Node transform

    dnt๋Š” Deno ํŒ€์—์„œ ๊ฐœ๋ฐœํ•œ ํŒจํ‚ค์ง€ ๋นŒ๋“œ ๋„๊ตฌ๋กœ, ์˜ค๋Š˜๋‚ ์˜ ํŒจํ‚ค์ง€๋“ค์ด ์ง€์›ํ•ด์•ผ ํ•˜๋Š” ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ๋“ค(๋ชจ๋“ˆ ์ง€์›: CJS/ESM, ๋Ÿฐํƒ€์ž„ ์ง€์›: Node/Deno ๋˜๋Š” ๋ธŒ๋ผ์šฐ์ €)๋กœ ์ธํ•ด ํŒจํ‚ค์ง€ ๋นŒ๋“œ ๊ณผ์ •์˜ ๋ณต์žก๋„(๋ณต์žกํ•œ ๋นŒ๋“œ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์„ฑ ๊ฐ™์€)์™€ ์ด๋ฅผ ์œ„ํ•œ ์†Œ์Šค ์ฝ”๋“œ ๊ด€๋ฆฌ ๋“ฑ์˜ ์–ด๋ ค์›€์„ ํ•ด๊ฒฐํ•ด ์ฃผ๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•œ๋‹ค.

    TypeScript๋กœ ์ž‘์„ฑ๋œ ํŒจํ‚ค์ง€๋Š” dnt ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋Š” ๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ ์ž‘์„ฑ์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋„๋ก ํƒ€๊ฒŒํŒ… ํ•  ์ˆ˜ ์žˆ๋‹ค.

    // build_npm.ts
    import { build, emptyDir } from "https://deno.land/x/dnt@0.37.0/mod.ts";
    
    // output ๋””๋ ‰ํ† ๋ฆฌ ์ง€์ •
    await emptyDir("./npm");
    
    await build({
      entryPoints: ["./ํŒจํ‚ค์ง€_์†Œ์Šค์ฝ”๋“œ_entry_point_ํŒŒ์ผ๋ช….ts"],
      outDir: "./npm",
      shims: {
        deno: true,
      },
      package: {
        // package.json ํŒŒ์ผ์— ์ถ”๊ฐ€๋  ํ•ญ๋ชฉ์„ ๊ธฐ์ˆ ํ•œ๋‹ค.
        name: "ํŒจํ‚ค์ง€๋ช…",
        version: Deno.args[0],
        ...
      },
      // ๋นŒ๋“œ ์ดํ›„, ์ˆ˜ํ–‰ํ•  ์ž‘์—…์„ ๊ธฐ์ˆ ํ•œ๋‹ค. (๋ผ์ด์„ผ์Šค์™€ README ํŒŒ์ผ์„ ๋ณต์‚ฌ ๋“ฑ)
      postBuild() {
        Deno.copyFileSync("LICENSE", "npm/LICENSE");
        Deno.copyFileSync("README.md", "npm/README.md");
      },
    });
    

    ๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜ํ–‰ํ•ด ๋ฒ„์ €๋‹๊ณผ ํ…Œ์ŠคํŠธ(ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ํ•„์š”)๊ฐ€ ๊ฐ™์ด ์ˆ˜ํ–‰๋˜๊ฒŒ ํ•œ๋‹ค.

    $ deno run -A build_npm.ts 0.0.1
    

    [์ฐธ๊ณ ] ๋ณด๋‹ค ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์˜ ์†Œ๊ฐœ ๊ธ€์„ ์ฐธ๊ณ ํ•˜๋ผ.

    Animotion

    Animotion์€ ๋ฉ‹์ง„ ์Šฌ๋ผ์ด๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  ์ฝ”๋“œ๋กœ ์•„์ด๋””์–ด๋ฅผ ์‹œ๊ฐํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ํ”„๋ ˆ์ž„์›Œํฌ์ด๋‹ค. Svelte, Reveal.js and Tailwind CSS๋ฅผ ์ง€์›ํ•œ๋‹ค.

    valibot

    ๊ตฌ์กฐ์  ๋ฐ์ดํ„ฐ์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•˜๊ธฐ ์œ„ํ•œ ์Šคํ‚ค๋งˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

    [์ฐธ๊ณ ] ์œ ์‚ฌํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ๋Š” Zod, Ajv, Joi, Yup ๋“ฑ์ด ์žˆ๋‹ค.

    // email ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
    import { email, endsWith, parse, string } from 'valibot';
    
    const EmailSchema = string([email(), endsWith('@example.com')]);
    
    parse(EmailSchema, null); // throws error
    parse(EmailSchema, 'foo'); // throws error
    
    parse(EmailSchema, 'jane@example.com'); // returns 'jane@example.com'
    
    // ํƒ€์ž… ์ถ”๋ก 
    import { type Output, email, minLength, object, string } from 'valibot';
    
    const LoginSchema = object({
      email: string([email()]),
      password: string([minLength(8)]),
    });
    
    type LoginData = Output<typeof LoginSchema>; // { email: string; password: string }
    

    [์ฐธ๊ณ ] ๋ณด๋‹ค ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ฐœ๋ฐœ์ž์˜ ์†Œ๊ฐœ ๊ธ€์„ ์ฐธ๊ณ ํ•ด ๋ณด๋ฉด ์ข‹๋‹ค.

    Radix

    ์ ‘๊ทผ์„ฑ, ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ๋ฐ ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜์— ์ค‘์ ์„ ๋‘” ๋กœ์šฐ ๋ ˆ๋ฒจ UI ์ปดํฌ๋„ŒํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋””์ž์ธ ์‹œ์Šคํ…œ์˜ ๊ธฐ๋ณธ ๋ ˆ์ด์–ด๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋„๋ก ์Šคํƒ€์ผ์ด ์ง€์ •๋˜์ง€ ์•Š์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

    Tiptap

    ProseMirror ๊ธฐ๋ฐ˜์˜ ํ…์ŠคํŠธ ์—๋””ํ„ฐ์ด๋‹ค. ๋ฐ๋ชจ์—์„œ ๋™์ž‘์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

    ์ต์Šคํ…์…˜์„ ํ†ตํ•ด์„œ ์—๋””ํ„ฐ์˜ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ณ , ์‰ฝ๊ฒŒ ์ต์Šคํ…์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

    LocatorJS

    ๊ฐœ๋ฐœ ์ค‘์ธ ์ปดํฌ๋„ŒํŠธ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์†์‰ฝ๊ฒŒ ์ฐพ์•„์ฃผ๋Š” ๋„๊ตฌ์ด๋‹ค. ์›น ํŽ˜์ด์ง€์—์„œ ๊ฐ„๋‹จํžˆ ํด๋ฆญํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ IDE ๋‚ด์˜ ์ปดํฌ๋„ŒํŠธ ์†Œ์Šค ์ฝ”๋“œ๋กœ ์ด๋™ํ•˜๊ฒŒ ํ•ด์ค€๋‹ค. Chrome ์ต์Šคํ…์…˜์„ ์ด์šฉํ•˜๊ฑฐ๋‚˜ Babel ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค์น˜ํ•˜์—ฌ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    ํ˜„์žฌ React, Preact, Solid, Vue, Svelte๋ฅผ ์ง€์›ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.