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

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

    2024-02

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

    The package that broke NPM (accidentally)

    NPM ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ๋“ฑ๋ก๋œ ๋ชจ๋“  ํŒจํ‚ค์ง€๋“ค์„ ํฌํ•จํ•˜๋Š” ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฐฐํฌํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

    ์•ฝ 10๋…„ ์ „, PatrckJS ๋‹‰๋„ค์ž„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋Š” โ€œeverythingโ€์ด๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฐฐํฌํ–ˆ์—ˆ๋‹ค. ๊ทธ ๋‹น์‹œ NPM ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋Š” ๋“ฑ์žฅํ•œ์ง€ 5๋…„ ์ •๋„ ๋˜์—ˆ๋˜ ์‹œ์ ์ด์—ˆ๋‹ค.

    ์ด ๊ธ€์€ ํ˜„์žฌ ์‹œ์ ์—, ๋ชจ๋“  ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ๋“ฑ๋ก๋œ ๋ชจ๋“  ํŒจํ‚ค์ง€๋“ค์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ ๊ฐ–๋Š” ๋‹จ์ผ ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฐฐํฌํ•˜๋Š” ๊ณผ์ •์„ ๋‹ค๋ฃฌ๋‹ค.

    ๊ณผ์ •์„ ํ†ตํ•ด ๋ช‡ ๊ฐ€์ง€ ๋ฐํ˜€์ง„ ์‚ฌ์‹ค ์ค‘ ํ•˜๋‚˜๋Š”, ๋‹จ์ผ NPM ํŒจํ‚ค์ง€์—์„œ ์˜์กด์„ฑ์€ ์ตœ๋Œ€ 800๊ฐœ๊นŒ์ง€๋ผ๋Š” ์ ์ด๋‹ค. ์žฌ๋ฏธ์žˆ๋Š” ์‹œ๋„์™€ ๊ทธ ๋’ท์ด์•ผ๊ธฐ๋ฅผ ์ฝ์–ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    [์ฐธ๊ณ ] ๊ธ€์—์„œ ๋ฐฐํฌ๋œ scoped ํŒจํ‚ค์ง€๋Š” ๋ชจ๋‘ ์‚ญ์ œ๋œ ์ƒํƒœ๋‹ค.

    npm in Review: A 2023 Retrospective on Growth, Security, and Quirky Facts

    ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž์ธ npm์˜ 23๋…„์˜ ๋ณ€ํ™”๋“ค์„ ๋˜๋Œ์•„ ๋ณด๊ณ  ์ •๋ฆฌํ•œ ๊ธ€๋กœ, ์ƒํƒœ๊ณ„์˜ ์ฃผ์š” ํŠธ๋ Œ๋“œ ๋ช‡ ๊ฐ€์ง€์™€ ๋ฐ์ดํ„ฐ์— ๊ธฐ๋ฐ˜ํ•ด ์–ด๋–ป๊ฒŒ ์„ฑ์žฅํ–ˆ๋Š”์ง€ ๋‹ค๋ฃฌ๋‹ค.

    ๋˜ํ•œ ์ง๋ฉดํ–ˆ๋˜ ๋ฉ€์›จ์–ด์™€ ์ŠคํŒธ ๋ฌธ์ œ, ๊ฐ€์žฅ ๊ธด ์ด๋ฆ„(ํŒจํ‚ค์ง€ ๋ช…์œผ๋กœ๋Š” ์ตœ๋Œ€ 214์ž๊นŒ์ง€ ํ—ˆ์šฉ)์„ ๊ฐ€์ง„ ํŒจํ‚ค์ง€๋‚˜ ๊ฐ€์žฅ ํฐ ํฌ๊ธฐ(5.96GB)๋ฅผ ๊ฐ€์ง„ ํŒจํ‚ค์ง€์™€ ๊ฐ™์ด ์•Œ๊ณ  ์‹ถ์—ˆ์ง€๋งŒ ์•Œ์ง€ ๋ชปํ–ˆ๋˜ ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋‹ต์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

    New client-side hooks coming to React 19

    React 19 ๋ฒ„์ „์— ํฌํ•จ๋  ์ƒˆ๋กœ์šด hook๋“ค์„ ์†Œ๊ฐœํ•œ๋‹ค. React ๊ฐœ๋ฐœํŒ€์€ data fetching๊ณผ form ๊ด€๋ จํ•œ ๊ธฐ์กด์˜ pain point๋ฅผ ๊ฐœ์„ ํ•˜๋Š”๋ฐ ์ง‘์ค‘ํ–ˆ๋‹ค. ์ƒˆ๋กœ์šด hook๋“ค์€ ๊ฐœ๋ฐœ์ž๋“ค์˜ ์ƒ์‚ฐ์„ฑ์„ ํ–ฅ์ƒ์‹œ์ผœ์ค„ ๊ฒƒ์ด๋‹ค. React Canary์™€ Experimental Channels๋ฅผ ํ†ตํ•ด ๋ฏธ๋ฆฌ ๊ฒฝํ—˜ํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    19๋ฒ„์ „์—์„œ ์ƒˆ๋กœ ํฌํ•จ๋  ํ›…๋“ค์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

    • use(Promise)
    • use(Context)
    • useFormState()
    • useFormStatus()
    • useOptimistic()

    2023 JavaScript Rising Stars

    ์ž‘๋…„ ํ•œ ํ•ด ๋™์•ˆ ๊ฐ€์žฅ ๋งŽ์€ Github Star๋ฅผ ๋ฐ›์€ ํ”„๋กœ์ ํŠธ๋“ค์ด ์ •๋ฆฌ๋˜์–ด ์žˆ๋‹ค. ํ…Œ์ŠคํŒ…, ์Šคํƒ€์ผ๋ง, ์ƒํƒœ ๊ด€๋ฆฌ ๋“ฑ์˜ ๊ฐ ๋ถ€๋ฌธ๋ณ„ ์ˆœ์œ„๋„ ์ •๋ฆฌ๋˜์–ด ์žˆ์–ด์„œ, 23๋…„์˜ ์ธ๊ธฐ ์˜คํ”ˆ์†Œ์Šค๋ฅผ ๋˜๋Œ์•„๋ณด๊ธฐ ์ข‹์€ ๊ธ€์ด๋‹ค.

    TL;DR

    ์ˆซ์ž 1์€ ์˜ฌ๋ฐ”๋ฅธ JSON ํ˜•์‹์ธ๊ฐ€?

    // data.json
    1
    

    ์ˆซ์ž 1๋งŒ ๋“ค์–ด์žˆ๋Š” JSON ํŒŒ์ผ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด์ž. ์ด JSON ํŒŒ์ผ์€ ์˜ฌ๋ฐ”๋ฅธ JSON ํ˜•์‹์ผ๊นŒ? ์ •๋‹ต์€ "๊ทธ๋ ‡๋‹ค!"์ด๋‹ค.

    ํ•ด๋‹น ์ŠคํŽ™์ด ํ‘œ์ค€ JSON ์ŠคํŽ™์ด ๋˜๊ธฐ๊นŒ์ง€์˜ ๋’ท์ด์•ผ๊ธฐ๊ฐ€ ํฅ๋ฏธ๋กญ๋‹ค.

    JSON's Numeric Boundaries: The Lesser-Known Reality of Inaccurate Figures

    JSON์€ ๋‹จ์ˆœ์„ฑ๊ณผ ๊ฐ€๋…์„ฑ์ด๋ผ๋Š” ๋งค๋ ฅ ๋•๋ถ„์— ์ „ ์„ธ๊ณ„ ๊ฐœ๋ฐœ์ž๋“ค์ด ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ๊ตํ™˜, ํŠนํžˆ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ถ„์•ผ์—์„œ ์ดˆ์„์ด ๋˜์—ˆ๋‹ค.

    ๊ทธ๋Ÿฌ๋‚˜ ์ˆซ์ž๋ฅผ ๋‹ค๋ฃฐ ๋•Œ JSON์˜ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ฒ˜์Œ์— ๋ณด์ด๋Š” ๊ฒƒ๋ณด๋‹ค ๋‹ค์†Œ ๋œ ๊ฐ„๋‹จํ•˜๋‹ค. ๋‹ค์Œ ์ฝ”๋“œ๋Š” ์–ด๋–ค ๊ฐ’์„ ์ถœ๋ ฅํ• ๊นŒ?

    const x = 9223372036854775807;
    console.log(x);
    

    ์ด๋ชจ์ง€์˜ ์ด๋ชจ์ €๋ชจ

    ์›น์— ์ ‘์†ํ•˜๋Š” ๋งค์ผ, ์ด๋ชจ์ง€(Emoji)๋ฅผ ๋ณด์ง€ ์•Š๋Š” ๋‚ ์ด ์—†๋‹ค. ๊ทธ๋งŒํผ ์ด๋ชจ์ง€๋Š” ์ƒํ™œ์— ๊นŠ์ˆ™์ด ๋“ค์–ด์™”๋‹ค. ์ด๋ชจ์ง€๋Š” ๋‹ค๋ฅธ ๋ฌธ์ž์™€ ๋ญ๊ฐ€ ๋‹ค๋ฅธ ๊ฑธ๊นŒ? ์–ด๋–ป๊ฒŒ ํ‘œ์‹œ๋˜๋Š” ๊ฑธ๊นŒ? ์ด๋ชจ์ง€์— ๋Œ€ํ•œ ๊ถ๊ธˆ์ฆ์„ ํ’€์–ด๋ณด์ž.

    JS์˜ ์ฃผ์„์€ //๊ณผ /* */๋ฟ๋งŒ์ด ์•„๋‹ˆ๋‹ค

    //์™€ /* */๋กœ ๊ฐ๊ฐ ํ•œ ์ค„ ์ฃผ์„๊ณผ ์—ฌ๋Ÿฌ ์ค„ ์ฃผ์„์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ๋ชจ๋‘ ์•Œ๊ณ  ์žˆ์„ ๊ฒƒ์ด๋‹ค.

    ํ•˜์ง€๋งŒ ECMAScript ๋ช…์„ธ์—๋Š” #!๋กœ ์‹œ์ž‘ํ•˜๋Š” Hashbang Comments์™€ HTML ์ฃผ์„ ํ˜•์‹์ธ <!--์™€ -->๋กœ ๊ฐ์‹ธ๋Š” HTML-like Comments ๋“ฑ ๋‹ค๋ฅธ ๊ฒƒ๋„ ์ •์˜๋˜์–ด ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค๋„ ์•Œ๊ณ  ์žˆ๋Š”๊ฐ€?

    ์–ด๋–ค ์ด์œ ์—์„œ ์ด๋Ÿฐ ๋‹ค์–‘ํ•œ ์ฃผ์„ ํ˜•์‹๋“ค์ด ๋„์ž…๋˜์—ˆ๋Š”์ง€, JavaScript๊ฐ€ ๊ฑธ์–ด์˜จ ๊ธธ์„ ๋”ฐ๋ผ ๊ฑธ์œผ๋ฉฐ ํ™•์ธํ•ด ๋ณด์ž.

    ์•„๋ฆ„๋‹ค์šด ์ฝ”๋“œ์— ๋Œ€ํ•˜์—ฌ

    ๋Œ€์ฒด ์•„๋ฆ„๋‹ค์šด ์ฝ”๋“œ๋ž€ ๋Œ€์ฒด ๋ฌด์—‡์ธ๊ฐ€. ์ง„์ง€ํ•˜๊ฒŒ ๊ฐœ๋ฐœ์ž๋ฅผ ์—…์œผ๋กœ ์‚ผ๋Š” ์‚ฌ๋žŒ์ด๋ผ๋ฉด ํ•œ ๋ฒˆ์ฏค ๊ณ ๋ฏผํ•ด ๋ณธ ์ ์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ •๋‹ต์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฌผ์Œ์— ํ•„์ž๋Š” ์‚ฌํšŒ์„ฑ, ์‹ ๋ขฐ์„ฑ, ์„ ํ˜•์„ฑ, ์„ ์–ธ์„ฑ์˜ ์ธก๋ฉด์—์„œ ์•„๋ฆ„๋‹ค์›€์— ๋Œ€ํ•œ ์ƒ๊ฐ์„ ํ’€์–ด๋‚ธ๋‹ค.

    ์›น ๊ฐœ๋ฐœ์— ๋Œ€ํ•ด ์—”์ง€๋‹ˆ์–ด๋“ค์ด ๋ฏฟ๋Š” ์ด์ƒํ•œ ๊ฒƒ๋“ค

    Mozilla์—์„œ ๋ธŒ๋ผ์šฐ์ € ๊ฐœ๋ฐœ์— ์ฐธ์—ฌํ–ˆ๋˜ ์ €์ž๊ฐ€ ์›น ๊ฐœ๋ฐœ๋กœ ๋Œ์•„์˜จ ์ดํ›„ ๋А๋ผ๊ฒŒ ๋œ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์›น ๊ฐœ๋ฐœ์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ๋†€๋ผ์šด ์ฃผ์žฅ๋“ค์— ๋Œ€ํ•ด ์†Œ๊ฐœํ•œ๋‹ค. ์ „์ง ๋ธŒ๋ผ์šฐ์ € ๊ฐœ๋ฐœ์ž์˜ ์‹œ๊ฐ์„ ํฅ๋ฏธ๋กญ๊ฒŒ ํ’€์–ด ๋‚ด์–ด ์žฌ๋ฏธ์žˆ๊ฒŒ ์ฝ์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

    ํ•œ๊ธ€ ๋ฒˆ์—ญ: https://velog.io/@sehyunny/weired-things-engineers-believe

    The Two Reacts

    React ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ํ™œ๋ฐœํ•œ ํ™œ๋™์„ ์ด์–ด ๋‚˜๊ฐ€๊ณ  ์žˆ๋Š” Dan Abramov์˜ ๊ธ€์ด๋‹ค.

    Dan์€ ํ˜„์žฌ์˜ React๋ฅผ ์•„๋ž˜์˜ ๋‘ ๊ฐ€์ง€ ๊ณต์‹์œผ๋กœ ์–‘๋ถ„ํ•ด์„œ ์„ค๋ช…ํ•œ๋‹ค.

    • UI = f(state), client component
    • UI = f(data), server component

    ๋์œผ๋กœ, UI = f(state, data)์ฒ˜๋Ÿผ ํ•˜๋‚˜์˜ ๊ณต์‹์œผ๋กœ ํ†ตํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ๋…์ž์—๊ฒŒ ์งˆ๋ฌธ์„ ๋˜์ง€๋ฉฐ ๋‹ค์Œ ๊ธ€์„ ์˜ˆ๊ณ ํ•œ๋‹ค.

    React ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ ์™€ ๋ฐฉ๋ฒ•

    React ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์™œ ํ•„์š”ํ•œ์ง€, ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š”์ง€ ์•Œ์•„๋ณธ๋‹ค.

    Common mistakes with the Next.js App Router and how to fix them

    Vercel์—์„œ ์ˆ˜๋ฐฑ ๋ช…์˜ ๊ฐœ๋ฐœ์ž์™€ ์ˆ˜์ฒœ ๊ฐœ์˜ Next.js Repository ์‚ฌ๋ก€๋ฅผ ์ข…ํ•ฉํ•˜์—ฌ Next.js App Router๋ฅผ ์“ธ ๋•Œ ํ”ํžˆ ์ €์ง€๋ฅด๋Š” 10๊ฐ€์ง€ ์‹ค์ˆ˜๋ฅผ ์ •๋ฆฌํ–ˆ๋‹ค.

    ์™œ ์ด๋Ÿฐ ์‹ค์ˆ˜๋ฅผ ํ•˜๋Š”์ง€, ๋ชจ๋ฒ” ์‚ฌ๋ก€๋Š” ๋ฌด์—‡์ธ์ง€, ๊ทธ๋ฆฌ๊ณ  App Router ํŒ ๋ช‡ ๊ฐ€์ง€๋ฅผ ์†Œ๊ฐœํ•œ๋‹ค.

    TL;DR

    Using Route Handlers with Server Components

    • ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ผ์šฐํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ๋ง ๊ฒƒ
    • ๋Œ€์‹  ๋ผ์šฐํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€์— ๋ฐฐ์น˜ํ•˜๋ ค๋Š” ๋กœ์ง์„ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋ผ

    Static or dynamic Route Handlers

    • ๋ผ์šฐํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” GET ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์บ์‹œ ๋จ
    • GET ๋ผ์šฐํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ๋ฆฌํ„ดํ•œ JSON ๋ฐ์ดํ„ฐ๋Š” ๋‹ค๋ฅธ ๋นŒ๋“œ๊ฐ€ ์ผ์–ด๋‚  ๋•Œ๊นŒ์ง€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Œ

    Route Handlers and Client Components

    • Form์„ ๋งŒ๋“ค ๋•Œ ๋ผ์šฐํ„ฐ ํ•ธ๋“ค๋Ÿฌ ๋Œ€์‹  Server Action์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Œ

    Using Suspense with Server Components

    • Suspense์˜ ์œ„์น˜๋Š” ๋ฐ์ดํ„ฐ ํŒจ์นญ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋น„๋™๊ธฐ ์ปดํฌ๋„ŒํŠธ๋ณด๋‹ค ๋†’์€ ๊ณณ์— ์œ„์น˜ํ•ด์•ผ ํ•จ
    • Suspense๊ฐ€ ๋น„๋™๊ธฐ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์žˆ์œผ๋ฉด ์ž‘๋™ํ•˜์ง€ ์•Š์Œ

    Using the incoming request

    • ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š” ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ(Incoming Request)์˜ ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Œ
    • ๋Œ€์‹ , ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š” ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” function๊ณผ props๋ฅผ ์ œ๊ณตํ•จ
    • cookies(), headers(), params, searchParams์™€ ๊ฐ™์€ ์˜ต์…˜์„ ์‚ฌ์šฉ

    Using Context providers with App Router

    • ๋‘ ๊ฐ€์ง€ ์ผ๋ฐ˜์ ์ธ ์‹ค์ˆ˜๋Š” ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์™€ Context๋ฅผ ํ•จ๊ป˜ ์“ฐ๋ ค๊ณ  ํ•˜๋Š” ๊ฒƒ๊ณผ App Router์— Provider๋ฅผ ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ
    • ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ์— Provider๋ฅผ ๋ฐฐ์น˜ํ•˜๊ณ , ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ์— ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํฌํ•จํ•˜๋ผ

    Using Server and Client Components together

    • ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž์‹์œผ๋กœ ๋‘˜ ์ˆ˜ ์žˆ์Œ
    • ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž์‹์œผ๋กœ ๋‘˜ ์ˆ˜ ์žˆ์Œ

    Adding โ€œuse clientโ€ unnecessarily

    • ๋ชจ๋“  ํŒŒ์ผ์— use client๋ฅผ ์ถ”๊ฐ€ํ•  ํ•„์š”๋Š” ์—†์Œ
    • ํด๋ผ์ด์–ธํŠธ ๋ฐ”์šด๋”๋ฆฌ์— ์žˆ์œผ๋ฉด, ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์˜ ํ˜•์ œ ์ž๋งค๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋จ

    Not revalidating data after mutations

    • ๊ฐœ๋ฐœ์ž๋“ค์˜ ์ผ๋ฐ˜์ ์ธ ์‹ค์ˆ˜ ์ค‘ ํ•˜๋‚˜๋Š” data๋ฅผ ๋ณ€๊ฒฝ(mutate) ํ•˜๊ณ  ๋‚˜์„œ revalidate ํ•˜๋Š” ์ž‘์—…์„ ๊นŒ๋จน๋Š” ๊ฒƒ
    • ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์ดํ›„, next/cache์˜ revalidatePath()์„ ์‹คํ–‰ํ•˜๋ผ. ๊ทธ๋ž˜์•ผ ํ™”๋ฉด์— ๋ณด์ด๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์—…๋ฐ์ดํŠธ๋จ

    Redirects inside of try/catch blocks

    • return redirect() ๋Œ€์‹  redirect()๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ
    • redirect() ํ•จ์ˆ˜๋Š” TypeScript์˜ never ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ return์„ ๋ถ™์ผ ํ•„์š”๊ฐ€ ์—†์Œ

    Vercel Youtube ์˜์ƒ์œผ๋กœ ์‹œ์ฒญํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

    [์ฐธ๊ณ ] App router์— ๋Œ€ํ•œ ๊ธฐ๋Œ€์น˜์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ์‹ค์ œ production ๊ตฌํ˜„๊ณผ ์ ์šฉ์€ ์ข€ ๋” ์‹ ์ค‘ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ๋‹ค. page router์—์„œ app router๋กœ ๋ณ€๊ฒฝ์„ ๊ณ ๋ คํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ๋‹ค์Œ์˜ ๊ฒฝํ—˜์  ๊ธ€์„ ์ฐธ๊ณ ํ•ด ๋ณด๊ธฐ ๋ฐ”๋ž€๋‹ค.

    React Libraries for 2024

    React๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ฐธ๊ณ ํ•˜๋ฉด ์ข‹์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•ด์„œ ์ถ”์ฒœํ•ด ์ค€๋‹ค.

    React Project, Package Manager, State Management, Data Fetching, Router, CSS Styling๋ฅผ ํฌํ•จํ•˜์—ฌ 30๊ฐ€์ง€ ์ฃผ์ œ์— ๋Œ€ํ•ด ๋‹ค์–‘ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์— ์†Œ๊ฐœํ•œ๋‹ค.

    ๋‹ค๋งŒ, ๋ชจ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋‹ค ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์–ด์„œ, ๊ฐ€๋ณ๊ฒŒ ์ฐธ๊ณ ํ•ด ๋ณด๋ฉด ์ข‹๋‹ค.

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

    Compiling a standalone executable using modern JavaScript/TypeScript runtimes

    ๋™์ผํ•œ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋ชจ๋˜ JS/TS ๋Ÿฐํƒ€์ž„๋“ค(bun, deno, node)์„ ์‚ฌ์šฉํ•ด ๋‹จ์ผ ์‹คํ–‰ ํŒŒ์ผ๋กœ ์ปดํŒŒ์ผ ํ•˜๊ณ , ์ƒ์„ฑ๋œ ํŒŒ์ผ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€์˜ ๊ณผ์ •์„ ๊ธฐ์ˆ ํ•œ ๋‚ด์šฉ์ด๋‹ค.

    ๊ฒฐ๋ก ์ ์œผ๋ก  bun๊ณผ deno๋Š” ๋‹จ์ผ ์‹คํ–‰ ํŒŒ์ผ์„ ์ƒ์„ฑํ–ˆ์ง€๋งŒ, node์˜ ๊ฒฝ์šฐ๋Š”. CJS๋งŒ ๊ฐ€๋Šฅํ–ˆ๊ณ , ESM์˜ ๊ฒฝ์šฐ๋Š” ์‹คํŒจํ–ˆ๋‹ค.

    What are the parts of a URL?

    ์šฐ๋ฆฌ๊ฐ€ ๋„ˆ๋ฌด๋‚˜๋„ ๋‹น์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” URL์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์š”์†Œ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค. TLD, Fragment, pathname ๊ฐ™์€ ์šฉ์–ด๊ฐ€ ์ƒ์†Œํ•˜๊ฑฐ๋‚˜ Search์™€ Search params๋ฅผ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•˜์ง€ ๋ชปํ•œ๋‹ค๋ฉด ์ด ๊ธ€์„ ํ†ตํ•ด ํ™•์ธํ•ด ๋ณด์ž.

    Letโ€™s learn how modern JavaScript frameworks work by building one

    ์ฒ˜์Œ๋ถ€ํ„ฐ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋Š” ๊ฒฝํ—˜์„ ํ†ตํ•ด ํ˜„๋Œ€ JavaScript ํ”„๋ ˆ์ž„์›Œํฌ์˜ ํ•ต์‹ฌ ๊ฐœ๋…๊ณผ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•  ์ˆ˜ ์žˆ๋‹ค.

    ์Šคํ† ๋ฆฌ๋ถ์œผ๋กœ ์ธํ„ฐ๋ž™์…˜ ํ…Œ์ŠคํŠธํ•˜๊ธฐ

    ์Šคํ† ๋ฆฌ๋ถ์œผ๋กœ ์ž๋™ํ™” ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•, Interactive Stories ๊ธฐ๋Šฅ ๋“ฑ์„ ํ™œ์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ์˜ ์ธํ„ฐ๋ž™์…˜์„ ์ž๋™์œผ๋กœ ์žฌ์ƒํ•˜๋Š” ๋ฐฉ๋ฒ•, ๊ทธ๋ฆฌ๊ณ  E2E ๋„๊ตฌ๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•œ๋‹ค.

    Build a Next.js app in Storybook with React Server Components and Mock Service Worker

    MSW(Mock Service Worker)๋ฅผ ์ด์šฉํ•ด์„œ React Server Component Storybook์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณธ๋‹ค.

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

    nuqs

    'use client'; // app router: only works in client components
    
    import { useQueryState } from 'nuqs';
    
    export default () => {
      const [name, setName] = useQueryState('name');
      return (
        <>
          <h1>Hello, {name || 'anonymous visitor'}!</h1>
          <input value={name || ''} onChange={(e) => setName(e.target.value)} />
          <button onClick={() => setName(null)}>Clear</button>
        </>
      );
    };
    

    React.useState()์ฒ˜๋Ÿผ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. url Query String์— ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋ฉฐ type-safe๋ฅผ ๋ณด์žฅํ•ด ์ฃผ๋Š” ํŠน์ง•์ด ์žˆ๋‹ค.

    Bun Shell

    import { $ } from 'bun';
    
    const buffer = Buffer.alloc(1024);
    
    await $`ls *.js > ${buffer}`;
    
    console.log(buffer.toString('utf8'));
    

    macOS์˜ zsh, Linux์˜ bash, Windows์˜ cmd๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๋ฌธ๋ฒ•๊ณผ ๋ช…๋ น์–ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ํ˜ธํ™˜์„ฑ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

    Bun Shell์€ Bun์— ๋‚ด์žฅ๋œ ์ƒˆ๋กœ์šด ์‹คํ—˜์  ์–ธ์–ด ๋ฐ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋กœ, JavaScript ๋ฐ TypeScript์—์„œ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ์‰˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

    Bun Shell์€ ์ผ๋ฐ˜ JavaScript์ฒ˜๋Ÿผ ๋А๊ปด์ง€๋ฉด์„œ๋„, pipe๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ ์‰˜์ฒ˜๋Ÿผ ๋А๊ปด์ง€๊ธฐ๋„ ํ•œ๋‹ค.

    Ollama JavaScript Library

    Llama 2, Mistral ๋“ฑ LLM์„ ๋กœ์ปฌ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Ollama์˜ JavaScript ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. ๋‹จ ๋ช‡ ์ค„์˜ ์ฝ”๋“œ๋งŒ์œผ๋กœ ์ƒ์„ฑํ˜• AI๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    $ npm install ollama
    
    import ollama from 'ollama';
    
    const response = await ollama.chat({
      model: 'llama2',
      messages: [{ role: 'user', content: 'Why is the sky blue?' }],
    });
    
    console.log(response.message.content);
    

    Sit in Shade

    ๋ฒ„์Šค๋ฅผ ํƒ€๊ณ  ์ด๋™ํ•  ๊ฒฝ๋กœ์™€ ํ•จ๊ป˜ ์˜ˆ์ƒ ํƒ‘์Šน ์‹œ๊ฐ„์„ ์ž…๋ ฅํ•˜๋ฉด, ํ–‡๋น› ๋…ธ์ถœ์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋–ค ์œ„์น˜์˜ ์ขŒ์„์— ์•‰๋Š” ๊ฒƒ์ด ์ข‹์€์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

    Shoelace

    ํ‘œ์ค€ ๊ธฐ์ˆ ์ธ Web Components๋กœ ๊ฐœ๋ฐœ๋œ UI ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ํŠน์ • ํ”„๋ ˆ์ž„์›Œํฌ์— ๊ธฐ๋ฐ˜ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ํ”„๋ ˆ์ž„์›Œํฌ ํ™˜๊ฒฝ ๋˜๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    ์ปดํฌ๋„ŒํŠธ๋Š” LitElement๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐœ๋ฐœ๋˜์—ˆ๋‹ค.

    Awesome Figma Tips

    ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์—์„œ ํ•„์š”ํ•œ ์ž‘์—…์„ ๋น ๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” Figma ํŒ ๋ชจ์Œ์„ ์ œ๊ณตํ•œ๋‹ค.

    Automatic Class Sorting with Prettier

    TailwindCSS์˜ ๋‹ค์–‘ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค ๋ณด๋ฉด, ์ ์šฉ๋œ ํด๋ž˜์Šค๊ฐ€ ๋งŽ์•„์ง€๊ฒŒ ๋˜๋ฉด์„œ ์ •๋ ฌ๋˜์ง€ ์•Š์€ ํด๋ž˜์Šค๋ช…์œผ๋กœ ์ธํ•ด ๊ฐ€๋…์„ฑ์ด ๋‚ฎ์•„์ง€๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ข…์ข… ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

    ์ด Prettier ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ž๋™์œผ๋กœ ๊ถŒ์žฅ ํด๋ž˜์Šค ์ˆœ์„œ์— ๋”ฐ๋ผ ์ •๋ ฌํ•ด ์ค€๋‹ค.

    <!-- Before -->
    <button
      class="text-white px-4 sm:px-8 py-2 sm:py-3 bg-sky-700 hover:bg-sky-800"
    ></button>
    
    <!-- After -->
    <button
      class="bg-sky-700 px-4 py-2 text-white hover:bg-sky-800 sm:px-8 sm:py-3"
    ></button>