[๐ค] React/Next.js ๋ฒ๋ค ์ต์ ํ: ์ฝ๋ ์คํ๋ฆฌํ ๊ณผ ๋ ์ด์ง ๋ก๋ฉ ์๋ฒฝ ๊ฐ์ด๋
React์ Next.js ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ๋ก๋ฉ ์๋๋ฅผ ๊ฐ์ ํ๋ ์ฝ๋ ์คํ๋ฆฌํ ๊ณผ ๋ ์ด์ง ๋ก๋ฉ ๊ธฐ๋ฒ์ ์ค์ฉ์ ์ธ ์์์ ํจ๊ป ์์ธํ ์์๋ด์. ์นํฉ ์ค์ ๋ถํฐ React.lazy, Next.js dynamic import๊น์ง ๋ค๋ค์.
์ ๋ณด๐ค ์ด ํฌ์คํ ์ Gemini 2.5 Flash AI๊ฐ ์์ฑํ์ด์.
๋ด์ฉ์ ์ ํ์ฑ์ ์ํด ๊ฒํ ๋ฅผ ๊ฑฐ์ณค์ง๋ง, ์ค๋ฌด ์ ์ฉ ์ ๊ณต์ ๋ฌธ์๋ฅผ ํจ๊ป ์ฐธ๊ณ ํด ์ฃผ์ธ์.
์ ์ฉํ ํ์ด ๊ธ์์๋ React์ Next.js ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๊ธฐ ๋ก๋ฉ ์ฑ๋ฅ์ ํ๊ธฐ์ ์ผ๋ก ๊ฐ์ ํ๋ ์ฝ๋ ์คํ๋ฆฌํ ๊ณผ ๋ ์ด์ง ๋ก๋ฉ ๊ธฐ๋ฒ์ ์ค์ ์ฝ๋ ์์์ ํจ๊ป ์์ธํ ๋ค๋ฃจ๊ณ , ์ต์ ํ ์ ๋ต๊ณผ ๋ฒ๋ค ํฌ๊ธฐ ๋ถ์ ๋ฐฉ๋ฒ๊น์ง ์์๋ด์.
๐ ์น ์ฑ๋ฅ์ ํต์ฌ: ๋ฒ๋ค ์ต์ ํ์ ์ค์์ฑ
0๏ธโฃ ์ ๋ฒ๋ค ์ต์ ํ๊ฐ ํ์์ ์ผ๊น์?
ํ๋์ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ์ ์ ๋ ๋ณต์กํด์ง๊ณ , ๋ง์ ์์ JavaScript ์ฝ๋๋ฅผ ํฌํจํ๊ฒ ๋ผ์. ์ด๋ฌํ ์ฝ๋๋ค์ ์ฌ์ฉ์์๊ฒ ํ์ํ ๋ชจ๋ ๊ธฐ๋ฅ๊ณผ UI๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ๋ฒ๋ค(bundle)์ด๋ผ๋ ํ๋์ ํ์ผ ๋๋ ์ฌ๋ฌ ํ์ผ๋ก ๋ฌถ์ฌ ๋ฐฐํฌ๋๋๋ฐ์. ๋ฌธ์ ๋ ์ด ๋ฒ๋ค์ ํฌ๊ธฐ๊ฐ ๋๋ฌด ์ปค์ง๋ฉด ์ด๊ธฐ ํ์ด์ง ๋ก๋ฉ ์๊ฐ์ด ๊ธธ์ด์ ธ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ํดํ ์ ์๋ค๋ ์ ์ด์์.
๊ตฌ๊ธ์ Core Web Vitals์ ๊ฐ์ ์น ์ฑ๋ฅ ์งํ์์๋ ๋ก๋ฉ ์ฑ๋ฅ์ ์ค์ํ ์์๋ก ๋ค๋ค์ง๊ณ ์์ด์. ๋ฒ๋ค ํฌ๊ธฐ๊ฐ ํฌ๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ํ์ผ์ ๋ค์ด๋ก๋ํ๊ณ ํ์ฑํ๋ฉฐ ์คํํ๋ ๋ฐ ๋ ๋ง์ ์๊ฐ์ด ์์๋๊ณ , ์ด๋ ์ฌ์ฉ์๊ฐ ์น์ฌ์ดํธ๋ฅผ ์ค์ ๋ก ์ฌ์ฉํ ์ ์์ ๋๊น์ง์ ์๊ฐ์ ๋ฆ์ถ๊ฒ ๋ผ์.
1๏ธโฃ ๊ธฐ์กด ๋ฐฉ์์ ํ๊ณ์ ์๋ก์ด ์ ๊ทผ
๊ธฐ์กด์๋ ๋ชจ๋ JavaScript ์ฝ๋๋ฅผ ํ๋์ ํฐ ๋ฒ๋ค๋ก ๋ง๋ค์ด์ ๋ฐฐํฌํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์์ด์. ์ด๋ ๊ฐ๋ฐ ํธ์์ฑ ์ธก๋ฉด์์๋ ์ข์ง๋ง, ์ฌ์ฉ์๊ฐ ์น์ฌ์ดํธ์ ํน์ ํ์ด์ง๋ง ๋ฐฉ๋ฌธํ๋๋ผ๋ ๋ชจ๋ ์ฝ๋๋ฅผ ๋ค์ด๋ก๋ํด์ผ ํ๋ ๋นํจ์จ์ ๋ณ์์ฃ .
์๋ฅผ ๋ค์ด, ๊ด๋ฆฌ์ ํ์ด์ง๋ ํน์ ๊ธฐ๋ฅ์ ์ผ๋ฐ ์ฌ์ฉ์๊ฐ ๊ฑฐ์ ์ ๊ทผํ์ง ์๋๋ฐ๋ ๋ถ๊ตฌํ๊ณ , ํด๋น ํ์ด์ง์ ์ฝ๋๊น์ง ์ด๊ธฐ ๋ก๋ ์์ ์ ํจ๊ป ๋ค์ด๋ก๋๋๋ ์์ด์์. ์ด๋ฌํ ๋นํจ์จ์ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ๊ฒ์ด ๋ฐ๋ก '์ฝ๋ ์คํ๋ฆฌํ
(Code Splitting)'๊ณผ '๋ ์ด์ง ๋ก๋ฉ(Lazy Loading)'์ด์์. ์ด ๋ ๊ฐ์ง ๊ธฐ๋ฒ์ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ์ฑ๋ฅ์ ํ๊ธฐ์ ์ผ๋ก ๊ฐ์ ํ ์ ์๋ ๊ฐ๋ ฅํ ๋๊ตฌ๋๋๋ค.
๐ก ์ฝ๋ ์คํ๋ฆฌํ ๊ณผ ๋ ์ด์ง ๋ก๋ฉ, ๋ฌด์์ด ๋ค๋ฅธ๊ฐ์?
0๏ธโฃ ๊ฐ๋ ์ดํดํ๊ธฐ
๋ง์ ๋ถ๋ค์ด ์ฝ๋ ์คํ๋ฆฌํ
๊ณผ ๋ ์ด์ง ๋ก๋ฉ์ ํผ์ฉํด์ ์ฌ์ฉํ์๊ฑฐ๋, ์ ํํ ์ฐจ์ด๋ฅผ ํท๊ฐ๋ ค ํ์๋๋ฐ์. ๊ฐ๋จํ ์ค๋ช
ํด ๋๋ฆด๊ฒ์.
์ ๋ณด**์ฝ๋ ์คํ๋ฆฌํ (Code Splitting)**์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฒด ์ฝ๋ ๋ฒ๋ค์ ์ฌ๋ฌ ๊ฐ์ ์์ ๋ฒ๋ค๋ก ๋๋๋ ๊ณผ์ ์ ๋งํด์. ์๋ฅผ ๋ค์ด, ์นํฉ(Webpack)๊ณผ ๊ฐ์ ๋ฒ๋ค๋ฌ๊ฐ ์ด ์ญํ ์ ์ํํ์ฃ . ์ฌ์ฉ์๊ฐ ๋ชจ๋ ์ฝ๋๋ฅผ ํ ๋ฒ์ ๋ค์ด๋ก๋ํ๋ ๋์ , ํ์ํ ์ฝ๋๋ง ๊ทธ๋๊ทธ๋ ๋ค์ด๋ก๋ํ ์ ์๋๋ก ์ค๋นํ๋ ๊ณผ์ ์ด๋ผ๊ณ ์๊ฐํ์๋ฉด ๋ผ์.
์ ๋ณด**๋ ์ด์ง ๋ก๋ฉ (Lazy Loading)**์ ์ฝ๋๋ฅผ ์ค์ ๋ก ํ์ํ ๋๊น์ง ๋ก๋ฉ์ ์ง์ฐ์ํค๋ ๊ธฐ๋ฒ์ด์์. ์ฆ, ์ฝ๋ ์คํ๋ฆฌํ ์ผ๋ก ๋๋ ์์ ๋ฒ๋ค๋ค์ ์ธ์ ๋ก๋ํ ์ง ๊ฒฐ์ ํ๋ ์คํ ์ ๋ต์ด์ฃ . ์ฌ์ฉ์๊ฐ ํน์ ๋ฒํผ์ ํด๋ฆญํ๊ฑฐ๋, ํน์ ๊ฒฝ๋ก๋ก ์ด๋ํ์ ๋ ํด๋น ๋ฒ๋ค์ ๋์ ์ผ๋ก ๋ถ๋ฌ์ค๋ ๊ฒ์ด ๋ ์ด์ง ๋ก๋ฉ์ ํต์ฌ์ด์์.
๊ฒฐ๋ก ์ ์ผ๋ก, ์ฝ๋ ์คํ๋ฆฌํ ์ด '์ด๋ป๊ฒ ์ชผ๊ฐค ๊ฒ์ธ๊ฐ'์ ๋ํ ์ ๋ต์ด๋ผ๋ฉด, ๋ ์ด์ง ๋ก๋ฉ์ '์ธ์ ์ชผ๊ฐ ๊ฒ์ ๋ถ๋ฌ์ฌ ๊ฒ์ธ๊ฐ'์ ๋ํ ์ ๋ต์ด๋ผ๊ณ ์ดํดํ์๋ฉด ์ฌ์ธ ๊ฑฐ์์.
1๏ธโฃ ์ ์ด๋ค์ ํจ๊ป ์ฌ์ฉํด์ผ ํ ๊น์?
์ด ๋ ๊ฐ์ง ๊ธฐ๋ฒ์ ์ํธ ๋ณด์์ ์ด์์. ์ฝ๋ ์คํ๋ฆฌํ
์ผ๋ก ๋ฒ๋ค์ ์๊ฒ ์ชผ๊ฐ ๋์ง ์์ผ๋ฉด, ๋ ์ด์ง ๋ก๋ฉ์ ํ ์ ์๋ ๋จ์ ์์ฒด๊ฐ ์๊ฒ ์ฃ ? ๋ฐ๋๋ก, ์ฝ๋๋ฅผ ์ชผ๊ฐ ๋๊ธฐ๋ง ํ๊ณ ์ค์ ๋ก ํ์ํ ๋๋ง ๋ถ๋ฌ์ค๋ ๋ ์ด์ง ๋ก๋ฉ์ ์ ์ฉํ์ง ์๋๋ค๋ฉด, ์ฌ์ ํ ์ด๊ธฐ ๋ก๋ ์์ ์ ๋ชจ๋ ๋ฒ๋ค์ ๋ค์ด๋ก๋ํ๊ฒ ๋์ด ์ฑ๋ฅ ๊ฐ์ ํจ๊ณผ๋ฅผ ๋ณด๊ธฐ ์ด๋ ค์์.
๋ฐ๋ผ์ React๋ Next.js์ ๊ฐ์ ๋ชจ๋ ์น ํ๋ ์์ํฌ์์๋ ์ด ๋ ๊ฐ์ง๋ฅผ ํจ๊ป ํ์ฉํ์ฌ ์ต์ ์ ์ฑ๋ฅ์ ๋์ด๋ธ๋ต๋๋ค.
โ๏ธ React์์ ์ฝ๋ ์คํ๋ฆฌํ ๊ณผ ๋ ์ด์ง ๋ก๋ฉ ์ ์ฉํ๊ธฐ
React์์๋ React.lazy์ Suspense ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐํธํ๊ฒ ์ฝ๋ ์คํ๋ฆฌํ
๊ณผ ๋ ์ด์ง ๋ก๋ฉ์ ๊ตฌํํ ์ ์์ด์.
0๏ธโฃ React.lazy์ Suspense ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
React.lazy๋ ๋์ import(import())๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ ๋ ํ์ํ ์ฝ๋๋ฅผ ๋ก๋ํ๊ฒ ํด์ค์. ๊ทธ๋ฆฌ๊ณ Suspense๋ ๋ ์ด์ง ๋ก๋๋ ์ปดํฌ๋ํธ๊ฐ ๋ก๋ฉ๋๋ ๋์ ๋ณด์ฌ์ค ํด๋ฐฑ(fallback) UI๋ฅผ ์ ์ํ ์ ์๊ฒ ํด์ฃผ์ฃ .
// src/components/HeavyComponent.tsx import React from "react"; const HeavyComponent = () => { // ์ด ์ปดํฌ๋ํธ๋ ๋ณต์กํ ๋ก์ง์ด๋ ๋ง์ ์์กด์ฑ์ ๊ฐ์ง ์ ์์ด์. return ( <div style={{ padding: "20px", border: "1px solid blue" }}> <h2>์๋ ํ์ธ์! ์ ๋ ๋ฌด๊ฑฐ์ด ์ปดํฌ๋ํธ์์.</h2> <p>์ ๊ฐ ๋ก๋ฉ๋ ๋๊น์ง ์ ์ ๊ธฐ๋ค๋ ค ์ฃผ์ ์ ๊ฐ์ฌํด์!</p> </div> ); }; export default HeavyComponent;
์ด์ ์ด HeavyComponent๋ฅผ ๋ ์ด์ง ๋ก๋ฉํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณผ๊ฒ์.
// src/App.tsx import React, { useState, Suspense } from "react"; import "./App.css"; // HeavyComponent๋ฅผ React.lazy๋ก ๊ฐ์ธ ๋์ ์ํฌํธํด์. const LazyHeavyComponent = React.lazy( () => import("./components/HeavyComponent"), ); function App() { const [showHeavyComponent, setShowHeavyComponent] = useState(false); const handleClick = () => { setShowHeavyComponent(true); }; return ( <div className="App"> <h1>React ๋ ์ด์ง ๋ก๋ฉ ์์</h1> <button onClick={handleClick}>๋ฌด๊ฑฐ์ด ์ปดํฌ๋ํธ ๋ถ๋ฌ์ค๊ธฐ</button> {showHeavyComponent && ( <Suspense fallback={<div>โจ ์ปดํฌ๋ํธ ๋ก๋ฉ ์ค...</div>}> <LazyHeavyComponent /> </Suspense> )} </div> ); } export default App;
์ ์์์์ LazyHeavyComponent๋ showHeavyComponent ์ํ๊ฐ true๊ฐ ๋์ด ์ค์ ๋ก ๋ ๋๋ง๋ ๋๊น์ง ๋ก๋ฉ๋์ง ์์์. ์ฌ์ฉ์๊ฐ "๋ฌด๊ฑฐ์ด ์ปดํฌ๋ํธ ๋ถ๋ฌ์ค๊ธฐ" ๋ฒํผ์ ํด๋ฆญํด์ผ๋ง ํด๋น ์ปดํฌ๋ํธ์ ์ฝ๋๊ฐ ๋คํธ์ํฌ๋ฅผ ํตํด ๋ค์ด๋ก๋๋๊ณ ๋ ๋๋ง๋๋ ๊ฒ์ ํ์ธํ ์ ์์ ๊ฑฐ์์.
Suspense ์ปดํฌ๋ํธ์ fallback prop์ ๋ ์ด์ง ๋ก๋ฉ ์ค์ธ ์ปดํฌ๋ํธ๊ฐ ์ค๋น๋ ๋๊น์ง ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ค UI๋ฅผ ์ ์ํด์. ์ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค๋ ๋ฐ ์์ฃผ ์ค์ํ ์ญํ ์ ํ๋ต๋๋ค.
1๏ธโฃ ์ด๋ฆ์ด ์ง์ ๋(Named) export ๋ถ๋ฌ์ค๊ธฐ
React.lazy๋ ๊ธฐ๋ณธ์ ์ผ๋ก default export๋ง ์ง์ํด์. ๋ง์ฝ named export๋ ์ปดํฌ๋ํธ๋ฅผ ๋ ์ด์ง ๋ก๋ฉํ๊ณ ์ถ๋ค๋ฉด, ์ค๊ฐ ๋ชจ๋์ ๋ง๋ค์ด์ default export๋ก ๋ค์ ๋ด๋ณด๋ด์ผ ํด์.
// src/components/NamedExports.tsx export const NamedComponentA = () => <div>์ด๋ฆ ์๋ ์ปดํฌ๋ํธ A</div>; export const NamedComponentB = () => <div>์ด๋ฆ ์๋ ์ปดํฌ๋ํธ B</div>;
์ด ์ปดํฌ๋ํธ๋ค์ ๋ ์ด์ง ๋ก๋ฉํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํด์.
// src/App.tsx (์ผ๋ถ) import React, { useState, Suspense } from "react"; import "./App.css"; const LazyNamedComponentA = React.lazy(() => import("./components/NamedExports").then((module) => ({ default: module.NamedComponentA, })), ); const LazyNamedComponentB = React.lazy(() => import("./components/NamedExports").then((module) => ({ default: module.NamedComponentB, })), ); function App() { const [showNamedA, setShowNamedA] = useState(false); const [showNamedB, setShowNamedB] = useState(false); return ( <div className="App"> <h1>React ๋ ์ด์ง ๋ก๋ฉ ์์</h1> <button onClick={() => setShowNamedA(true)}>Named A ๋ถ๋ฌ์ค๊ธฐ</button> <button onClick={() => setShowNamedB(true)}>Named B ๋ถ๋ฌ์ค๊ธฐ</button> {showNamedA && ( <Suspense fallback={<div>Named A ๋ก๋ฉ ์ค...</div>}> <LazyNamedComponentA /> </Suspense> )} {showNamedB && ( <Suspense fallback={<div>Named B ๋ก๋ฉ ์ค...</div>}> <LazyNamedComponentB /> </Suspense> )} </div> ); } export default App;
์ด๋ ๊ฒ .then()์ ์ฌ์ฉํ์ฌ ๋์ ์ผ๋ก ์ํฌํธ๋ ๋ชจ๋์์ ์ํ๋ named export๋ฅผ default ์์ฑ์ผ๋ก ๋ฐํํด์ฃผ๋ฉด ๋ผ์.
2๏ธโฃ ์๋ฌ ์ฒ๋ฆฌ: ErrorBoundary ํ์ฉ
๋ ์ด์ง ๋ก๋ฉ ์ค ๋คํธ์ํฌ ๋ฌธ์ ๋ ์ฝ๋ ์๋ฌ๋ก ์ธํด ์ปดํฌ๋ํธ ๋ก๋ฉ์ ์คํจํ ์ ์์ด์. ์ด๋ฐ ๊ฒฝ์ฐ๋ฅผ ๋๋นํด ErrorBoundary๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์์.
// src/components/MyErrorBoundary.tsx import React, { Component, ErrorInfo, ReactNode } from "react"; interface Props { children?: ReactNode; fallback: ReactNode; } interface State { hasError: boolean; } class MyErrorBoundary extends Component<Props, State> { public state: State = { hasError: false, }; public static getDerivedStateFromError(_: Error): State { // ๋ค์ ๋ ๋๋ง์์ ํด๋ฐฑ UI๋ฅผ ํ์ํ๋๋ก ์ํ๋ฅผ ์ ๋ฐ์ดํธํด์. return { hasError: true }; } public componentDidCatch(error: Error, errorInfo: ErrorInfo) { console.error("Uncaught error:", error, errorInfo); } public render() { if (this.state.hasError) { return this.props.fallback; } return this.props.children; } } export default MyErrorBoundary;
์ด์ ์ด ErrorBoundary๋ฅผ Suspense์ ํจ๊ป ์ฌ์ฉํด ๋ณผ๊ฒ์.
// src/App.tsx (์ผ๋ถ) import React, { useState, Suspense } from "react"; import MyErrorBoundary from "./components/MyErrorBoundary"; // ErrorBoundary ์ํฌํธ // ... const LazyHeavyComponent = React.lazy( () => import("./components/HeavyComponent"), ); function App() { // ... return ( <div className="App"> {/* ... */} {showHeavyComponent && ( <MyErrorBoundary fallback={<div>โ ๏ธ ์ปดํฌ๋ํธ ๋ก๋ฉ์ ์คํจํ์ด์!</div>}> <Suspense fallback={<div>โจ ์ปดํฌ๋ํธ ๋ก๋ฉ ์ค...</div>}> <LazyHeavyComponent /> </Suspense> </MyErrorBoundary> )} </div> ); } // ...
์ด๋ ๊ฒ ํ๋ฉด ๋ ์ด์ง ๋ก๋๋ ์ปดํฌ๋ํธ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋, ์ ํ๋ฆฌ์ผ์ด์
์ ์ฒด๊ฐ ๋ง๊ฐ์ง๋ ๋์ ์ ์๋ fallback UI๋ฅผ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ค ์ ์์ด์.
๐ Next.js์์ ์ฝ๋ ์คํ๋ฆฌํ ๊ณผ ๋ ์ด์ง ๋ก๋ฉ ์ ์ฉํ๊ธฐ
Next.js๋ React ๊ธฐ๋ฐ์ด๋ฏ๋ก React.lazy์ Suspense๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง, Next.js ์์ฒด์ ์ผ๋ก ์ ๊ณตํ๋ next/dynamic์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๊ฐ๋ ฅํ๊ณ Next.js์ SSR/SSG/ISR ํ๊ฒฝ๊ณผ ๋ ์ ํตํฉ๋ผ์.
0๏ธโฃ next/dynamic ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
next/dynamic์ Next.js ์ ํ๋ฆฌ์ผ์ด์
์์ ํด๋ผ์ด์ธํธ ์ธก์์๋ง ๋ ๋๋ง๋ ์ปดํฌ๋ํธ๋ฅผ ๋์ ์ผ๋ก ์ํฌํธํ ๋ ์ฃผ๋ก ์ฌ์ฉ๋ผ์.
// components/ClientOnlyComponent.tsx "use client"; // ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์ ๋ช ์ํด์. import React from "react"; const ClientOnlyComponent = () => { const [count, setCount] = React.useState(0); return ( <div style={{ padding: "20px", border: "1px solid green" }}> <h3>์ ๋ ํด๋ผ์ด์ธํธ ์ ์ฉ ์ปดํฌ๋ํธ์์.</h3> <p>ํด๋ผ์ด์ธํธ์์๋ง ์ธํฐ๋ํฐ๋ธํ๊ฒ ๋์ํด์! Count: {count}</p> <button onClick={() => setCount((prev) => prev + 1)}>์ฆ๊ฐ</button> </div> ); }; export default ClientOnlyComponent;
์ด ์ปดํฌ๋ํธ๋ฅผ ํ์ด์ง์์ ๋์ ์ผ๋ก ๋ถ๋ฌ์ ๋ณผ๊ฒ์.
// app/page.tsx (App Router) ๋๋ pages/index.tsx (Pages Router) import dynamic from "next/dynamic"; import React from "react"; // next/dynamic์ ์ฌ์ฉํ์ฌ ClientOnlyComponent๋ฅผ ๋์ ์ผ๋ก ์ํฌํธํด์. const DynamicClientOnlyComponent = dynamic( () => import("../components/ClientOnlyComponent"), { loading: () => <p>ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ๋ก๋ฉ ์ค...</p>, // ๋ก๋ฉ ์ค ๋ณด์ฌ์ค UI ssr: false, // ์ด ์ปดํฌ๋ํธ๋ ์๋ฒ์์ ๋ ๋๋งํ์ง ์์์. }, ); export default function HomePage() { const [showComponent, setShowComponent] = React.useState(false); return ( <main style={{ padding: "20px" }}> <h1>Next.js Dynamic Import ์์</h1> <button onClick={() => setShowComponent(true)}> ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ๋ถ๋ฌ์ค๊ธฐ </button> {showComponent && <DynamicClientOnlyComponent />} </main> ); }
์ฌ๊ธฐ์ ์ค์ํ ์ต์
์ ssr: false์์. ์ด ์ต์
์ ์ฌ์ฉํ๋ฉด ํด๋น ์ปดํฌ๋ํธ๊ฐ ์๋ฒ์์ ์ฌ์ ๋ ๋๋ง๋์ง ์๊ณ , ์ค์ง ํด๋ผ์ด์ธํธ ๋ฒ๋ค์๋ง ํฌํจ๋์ด ํด๋ผ์ด์ธํธ์์๋ง ๋ก๋๋๊ณ ๋ ๋๋ง๋ผ์. ์ด๋ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR) ์ ๋ถํ์ํ ํด๋ผ์ด์ธํธ ์ ์ฉ ์ฝ๋ ๋ฒ๋ค๋ง์ ๋ง์์ค ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐ ํฐ ๋์์ด ๋๋ต๋๋ค.
loading ์ต์
์ React.Suspense์ fallback๊ณผ ์ ์ฌํ๊ฒ ์ปดํฌ๋ํธ๊ฐ ๋ก๋ฉ๋๋ ๋์ ๋ณด์ฌ์ค UI๋ฅผ ์ ์ํด์.
1๏ธโฃ next/dynamic with Server Components (App Router)
Next.js App Router์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ์ปดํฌ๋ํธ๊ฐ Server Component๋ก ๋์ํด์. Server Component์์ ๋์ ์ํฌํธ๋ฅผ ์ฌ์ฉํ๋ฉด, ํด๋น ๋ชจ๋์ ์ฌ์ ํ ์๋ฒ์์ ๋ฒ๋ค๋ง๋๊ณ ๋ ๋๋ง๋ ์ ์์ด์. ํ์ง๋ง next/dynamic์ ์ฌ์ฉํ๊ณ ssr: false ์ต์
์ ์ฃผ๋ฉด, ๊ทธ ์ปดํฌ๋ํธ๋ ํด๋ผ์ด์ธํธ ์ ์ฉ์ผ๋ก ๋ถ๋ฆฌ๋์ด ํด๋ผ์ด์ธํธ์์๋ง ๋ก๋๋ผ์.
Server Component ๋ด๋ถ์์ use client ์ง์์ด๊ฐ ์๋ Client Component๋ฅผ ๋์ ์ผ๋ก ๋ถ๋ฌ์ค๋ ๊ฒ์ next/dynamic์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ํจํด ์ค ํ๋์์.
2๏ธโฃ import() ํจ์๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
Next.js๋ ๋ด๋ถ์ ์ผ๋ก ์นํฉ์ ์ฌ์ฉํ๋ฏ๋ก, import() ํจ์๋ฅผ ์ง์ ์ฌ์ฉํ์ฌ ์ฝ๋ ์คํ๋ฆฌํ
์ ๊ตฌํํ ์๋ ์์ด์. ์ด๋ React.lazy๋ next/dynamic์ด ์ ๊ณตํ๋ ์ถ์ํ ์์ด ๋ ์ธ๋ฐํ ์ ์ด๊ฐ ํ์ํ ๋ ์ ์ฉํ ์ ์์ด์.
// app/dashboard/page.tsx (์์) "use client"; // ์ด ํ์ด์ง๋ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์. import React, { useState, useEffect } from "react"; export default function DashboardPage() { const [ChartComponent, setChartComponent] = useState<React.ComponentType | null>(null); useEffect(() => { // ์ฌ์ฉ์๊ฐ ๋์๋ณด๋์ ์ ๊ทผํ์ ๋๋ง ์ฐจํธ ์ปดํฌ๋ํธ๋ฅผ ๋์ ์ผ๋ก ๋ถ๋ฌ์์. import("../components/ChartComponent") .then((module) => { setChartComponent(() => module.default); }) .catch((error) => { console.error("Failed to load ChartComponent:", error); }); }, []); return ( <div> <h1>๋์๋ณด๋</h1> {ChartComponent ? <ChartComponent /> : <p>์ฐจํธ ๋ก๋ฉ ์ค...</p>} </div> ); }
์ด ๋ฐฉ์์ React.lazy๋ next/dynamic์ฒ๋ผ Suspense๋ loading ์ต์
์ ์๋์ผ๋ก ์ ๊ณตํ์ง ์์ผ๋ฏ๋ก, ์ง์ ๋ก๋ฉ ์ํ์ ์๋ฌ ํธ๋ค๋ง์ ๊ตฌํํด์ผ ํด์. ํ์ง๋ง ํน์ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๋ก๋ํด์ผ ํ๋ ๋ชจ๋์ด ์ปดํฌ๋ํธ๊ฐ ์๋ ๋(์: ํฐ ์ ํธ๋ฆฌํฐ ํจ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ) ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ด์.
๐ก ๋ฒ๋ค ์ต์ ํ ์ ๋ต๊ณผ ํ
0๏ธโฃ ์ธ์ ์ฝ๋ ์คํ๋ฆฌํ ์ ์ ์ฉํด์ผ ํ ๊น์?
๋ชจ๋ ์ปดํฌ๋ํธ๋ ๋ชจ๋์ ์ฝ๋ ์คํ๋ฆฌํ
์ ์ ์ฉํ๋ ๊ฒ์ด ๋ฅ์ฌ๋ ์๋์์. ์คํ๋ ค ๋ฒ๋ค ์ค๋ฒํค๋๋ ๋ณต์ก์ฑ๋ง ์ฆ๊ฐ์ํฌ ์ ์์ฃ . ๋ค์์ ๊ฒฝ์ฐ์ ์ ์ฉ์ ๊ณ ๋ คํด ๋ณด์ธ์.
์ ์ฉํ ํ
- ๊ฒฝ๋ก ๊ธฐ๋ฐ ์คํ๋ฆฌํ (Route-based Splitting): ๊ฐ ๋ผ์ฐํธ(ํ์ด์ง)๋ณ๋ก ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ผ๋ฐ์ ์ด๊ณ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ด์์. ์ฌ์ฉ์๊ฐ ํน์ ํ์ด์ง๋ก ์ด๋ํ ๋๋ง ํด๋น ํ์ด์ง์ ์ฝ๋๋ฅผ ๋ก๋ํ๊ฒ ๋ผ์. * ํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ/์ปดํฌ๋ํธ: ์ด๊ธฐ ๋ก๋ ์์ ์ ํ์ํ์ง ์์ ํฐ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์์ฒด ๊ฐ๋ฐํ ๋ฌด๊ฑฐ์ด ์ปดํฌ๋ํธ(์: ์ง๋, ์ฐจํธ, ๋ณต์กํ ์๋ํฐ)์ ์ ์ฉํด์. * ์กฐ๊ฑด๋ถ ๋ ๋๋ง ์ปดํฌ๋ํธ: ๋ชจ๋ฌ, ํญ ์ฝํ ์ธ , ๊ด๋ฆฌ์ ์ ์ฉ ๊ธฐ๋ฅ ๋ฑ ํน์ ์กฐ๊ฑด์์๋ง ๋ ๋๋ง๋๋ ์ปดํฌ๋ํธ์ ์ ์ฉํด์.
1๏ธโฃ ๋ฒ๋ค ํฌ๊ธฐ ๋ถ์ ๋๊ตฌ ํ์ฉํ๊ธฐ
์ฝ๋ ์คํ๋ฆฌํ
์ ์ ์ฉํ๊ธฐ ์ ์, ์ด๋ค ๋ฒ๋ค์ด ๊ฐ์ฅ ํฐ ๋ถ๋ถ์ ์ฐจ์งํ๋์ง ํ์
ํ๋ ๊ฒ์ด ์ค์ํด์. webpack-bundle-analyzer์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฒ๋ค ๊ตฌ์ฑ ์์๋ฅผ ์๊ฐ์ ์ผ๋ก ๋ถ์ํ ์ ์์ด์.
# Next.js ํ๋ก์ ํธ์ ๊ฒฝ์ฐ # package.json ์คํฌ๋ฆฝํธ์ ์ถ๊ฐ: # "analyze": "ANALYZE=true next build" # ๋๋ # "analyze": "cross-env ANALYZE=true next build" (cross-env ์ค์น ํ์) # ์คํ ์์ npm run analyze # ๋๋ yarn analyze
์ด ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด ๋น๋ ํ ๋ฒ๋ค์ ๊ตฌ์กฐ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ํํ ์น ํ์ด์ง๊ฐ ์ด๋ ค์. ์ด๋ค ํ์ผ์ด ๋ฒ๋ค ํฌ๊ธฐ์ ๊ฐ์ฅ ํฐ ์ํฅ์ ๋ฏธ์น๋์ง ์ง๊ด์ ์ผ๋ก ํ์ ํ๊ณ ์ต์ ํ ๋์์ ์ ์ ํ๋ ๋ฐ ํฐ ๋์์ด ๋๋ต๋๋ค.
2๏ธโฃ ์ถ๊ฐ์ ์ธ ์ต์ ํ ํ
- ํ๋ฆฌ๋ก๋/ํ๋ฆฌํ์น (Preload/Prefetch): Next.js์
Link์ปดํฌ๋ํธ๋ ๋ทฐํฌํธ์ ๋ค์ด์ค๋ฉด ์๋์ผ๋ก ํด๋น ํ์ด์ง์ ์ฝ๋๋ฅผ ํ๋ฆฌํ์นํด์.React.lazy์ ํจ๊ป ์ฌ์ฉํ ๊ฒฝ์ฐ, ์ฌ์ฉ์๊ฐ ๋ค์ ํ์ด์ง๋ก ์ด๋ํ๊ธฐ ์ ์ ๋ฏธ๋ฆฌ ๊ด๋ จ ๋ฒ๋ค์ ๋ค์ด๋ก๋ํ์ฌ ์ ํ ์๋๋ฅผ ๋์ฑ ๋น ๋ฅด๊ฒ ํ ์ ์์ด์. - ํธ๋ฆฌ ์์ดํน (Tree Shaking): ์ฌ์ฉํ์ง ์๋ ์ฝ๋๋ฅผ ์ต์ข
๋ฒ๋ค์์ ์ ๊ฑฐํ๋ ๊ธฐ๋ฒ์ด์์. ๋ชจ๋ JavaScript ๋ชจ๋ ๋ฒ๋ค๋ฌ(Webpack, Rollup ๋ฑ)๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ์ง๋ง, ์ฌ์ด๋ ์ดํํธ ์๋ ๋ชจ๋์ ์์ฑํ๊ณ
package.json์sideEffects: false๋ฅผ ๋ช ์ํ๋ ๋ฑ ๊ฐ๋ฐ์์ ๋ ธ๋ ฅ๋ ํ์ํด์. - ์์ถ (Compression): Brotli๋ Gzip๊ณผ ๊ฐ์ ์์ถ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก ์ ์ก๋๋ ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ์ค์ผ ์ ์์ด์. ๋๋ถ๋ถ์ ํธ์คํ ์๋น์ค๋ CDN์์ ์๋์ผ๋ก ์ฒ๋ฆฌํด ์ฃผ์ง๋ง, ์ง์ ์ค์ ํ๋ ๊ฒฝ์ฐ๋ ์์ด์.
๐ ์ ๋ฆฌํ๋ฉฐ
0๏ธโฃ ํต์ฌ ์์ฝ
์ค๋์ React์ Next.js ์ ํ๋ฆฌ์ผ์ด์ ์ ์น ์ฑ๋ฅ์ ํ๊ธฐ์ ์ผ๋ก ๊ฐ์ ํ ์ ์๋ ์ฝ๋ ์คํ๋ฆฌํ ๊ณผ ๋ ์ด์ง ๋ก๋ฉ ๊ธฐ๋ฒ์ ๋ํด ์์ธํ ์์๋ดค์ด์.
์ฑ๊ณต
- ์ฝ๋ ์คํ๋ฆฌํ ์ ๋ฒ๋ค์ ์ฌ๋ฌ ์์ ์กฐ๊ฐ์ผ๋ก ๋๋๋ ๊ณผ์ ์ด๊ณ , ๋ ์ด์ง ๋ก๋ฉ์ ์ด ์กฐ๊ฐ๋ค์ ํ์ํ ๋๋ง ๋ถ๋ฌ์ค๋ ์คํ ์ ๋ต์ด์์. * React์์๋
React.lazy์Suspense๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ๋ ์ด์ง ๋ก๋ฉ์ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ด์.ErrorBoundary๋ฅผ ํตํ ์๋ฌ ์ฒ๋ฆฌ๋ ์์ง ๋ง์ธ์. * Next.js์์๋next/dynamic์ ์ฌ์ฉํ์ฌ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ฅผ ๋์ ์ผ๋ก ์ํฌํธํ๊ณ ,ssr: false์ต์ ์ผ๋ก ์๋ฒ ๋ฒ๋ค์์ ์ ์ธํ ์ ์์ด์. * ์ต์ ํ ์ ๋ต์ผ๋ก๋ ๊ฒฝ๋ก ๊ธฐ๋ฐ ์คํ๋ฆฌํ , ํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ/์ปดํฌ๋ํธ ๋ถ๋ฆฌ, ์กฐ๊ฑด๋ถ ๋ ๋๋ง ์ปดํฌ๋ํธ ์ ์ฉ ๋ฑ์ ๊ณ ๋ คํด์ผ ํด์. *webpack-bundle-analyzer์ ๊ฐ์ ๋ถ์ ๋๊ตฌ๋ฅผ ํ์ฉํ์ฌ ์ต์ ํ ๋์์ ํ์ ํ๋ ๊ฒ์ด ์ค์ํด์.
1๏ธโฃ ๋ค์ ์ก์ : ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง
๋ฒ๋ค ์ต์ ํ๋ ํ ๋ฒ์ ์์
์ผ๋ก ๋๋๋ ๊ฒ์ด ์๋๋ผ ์ง์์ ์ธ ๊ด๋ฆฌ์ ๋ชจ๋ํฐ๋ง์ด ํ์ํด์. ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ํ์๋ ์ฃผ๊ธฐ์ ์ผ๋ก Core Web Vitals ์งํ๋ฅผ ํ์ธํ๊ณ , ๋ฒ๋ค ํฌ๊ธฐ ๋ณํ๋ฅผ ์ถ์ ํ๋ฉฐ ์ถ๊ฐ์ ์ธ ์ต์ ํ ๊ธฐํ๋ฅผ ์ฐพ์๋ณด์ธ์.
์ฌ์ฉ์์๊ฒ ๋ ๋น ๋ฅด๊ณ ์พ์ ํ ๊ฒฝํ์ ์ ๊ณตํ๊ธฐ ์ํ ์ฌ๋ฌ๋ถ์ ๋
ธ๋ ฅ์ ๊ฒฐ์ฝ ํ๋์ง ์์ ๊ฑฐ์์! ๊ถ๊ธํ ์ ์ด ์๋ค๋ฉด ์ธ์ ๋ ์ง ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์๊ฑฐ๋ ๊ด๋ จ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
๐ฎ ์ฐธ๊ณ
- React ๊ณต์ ๋ฌธ์: Code Splitting
- Next.js ๊ณต์ ๋ฌธ์: Dynamic Imports
- MDN Web Docs: import()
- Google Developers: Code-splitting
์ฐ๊ด๋ ํฌ์คํธ
- ๋จ์ด: 1,283๊ฐ15๋ถ
[๐ค] Next.js App Router Edge Runtime: ๊ธ๋ก๋ฒ ์ฑ๋ฅ๊ณผ ๋น์ฉ ํจ์จ์ฑ ๊ทน๋ํ ์ ๋ต
Next.js App Router์์ Edge Runtime์ ํ์ฉํด Route Handler ์ฑ๋ฅ์ ๊ทน๋ํํ๊ณ , ๊ธ๋ก๋ฒ ์ฌ์ฉ์์๊ฒ ๋น ๋ฅธ ์๋ต ์๋๋ฅผ ์ ๊ณตํ๋ฉฐ, ๋น์ฉ ํจ์จ์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด์ํ๋ ์ค์ ์ ๋ต์ ์์ธํ ๋ค๋ค์. Edge Runtime์ ์ฅ์ ๊ณผ ์ ํ์ฌํญ, ๊ทธ๋ฆฌ๊ณ ์ค์ ์ฝ๋ ์์๋ฅผ ํตํด ํจ๊ณผ์ ์ธ ์ ์ฉ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.
- ๋จ์ด: 1,978๊ฐ25๋ถ
[๐ค] Next.js/React์์ ํด๋ฆฐ ์ํคํ ์ฒ์ ์์กด์ฑ ์ญ์ ์์น ์ ์ฉํ๊ธฐ: ํ์ฅ ๊ฐ๋ฅํ ํ๋ฐํธ์๋ ๋ง๋ค๊ธฐ
Next.js์ React ํ๋ก์ ํธ์์ ํด๋ฆฐ ์ํคํ ์ฒ์ ์์กด์ฑ ์ญ์ ์์น(DIP)์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ธต์ ์ผ๋ก ๋ค๋ฃจ์ด์. ๋๋ฉ์ธ, ์ ์ค์ผ์ด์ค, ์ธํ๋ผ ๊ณ์ธต์ ๋ถ๋ฆฌํ์ฌ ์ ์ง๋ณด์์ฑ๊ณผ ํ ์คํธ ์ฉ์ด์ฑ์ ๊ทน๋ํํ๋ ์ค์ฉ์ ์ธ ์ ๋ต์ ๋ฐฐ์๋ณด์ธ์.
- ๋จ์ด: 1,729๊ฐ19๋ถ
[๐ค] Jotai๋ก Next.js App Router ํด๋ผ์ด์ธํธ ์ํ ๊ด๋ฆฌ ์ฌํ: ์ํฐ ํจํด๊ณผ ์ต์ ํ
Next.js App Router ํ๊ฒฝ์์ Jotai ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ์ฌ ํจ์จ์ ์ธ ํด๋ผ์ด์ธํธ ์ํ ๊ด๋ฆฌ ์ ๋ต์ ์์๋ณด์ธ์. ์ํฐ ํจํด์ ์ด์ฉํ ์ํ ๋ถ๋ฆฌ, ์ต์ ํ ๊ธฐ๋ฒ, ๊ทธ๋ฆฌ๊ณ ์ค์ฉ์ ์ธ ์ฝ๋ ์์๋ฅผ ํตํด ๋ณต์กํ UI ์ํ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๋ค๋ฃจ๋ ๋ฐฉ๋ฒ์ ๋ธ๋ฃจ๊ฐ ์์ธํ ์๋ ค๋๋ ค์.
- ๋จ์ด: 1,711๊ฐ18๋ถ
[๐ค] Next.js App Router ์ ์ญ ์ํ ๊ด๋ฆฌ: Server/Client Components ์๋ฒฝ ๊ฐ์ด๋
Next.js App Router ํ๊ฒฝ์์ Server Components์ Client Components ๊ฐ์ ์ ์ญ ์ํ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ํ๊ตฌํด์. Zustand, Recoil, Context API ๋ฑ ๋ค์ํ ์๋ฃจ์ ๊ณผ ์ค์ฉ์ ์ธ ์ ๋ต์ ํตํด ๋ณต์กํ ์ํ ๊ด๋ฆฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด ๋ณด์ธ์.
- ๋จ์ด: 1,783๊ฐ20๋ถ
[๐ค] Atomic Design ํจํด์ผ๋ก React/Next.js ์ปดํฌ๋ํธ ์ํคํ ์ฒ ํ์ฅ์ฑ ๋์ด๊ธฐ
React ๋ฐ Next.js ํ๋ก์ ํธ์์ Atomic Design ํจํด์ ์ ์ฉํ์ฌ ์ปดํฌ๋ํธ์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ํ์ฅ์ฑ์ ๊ทน๋ํํ๋ ๋ฐฉ๋ฒ์ ์ค๋ฌด ์์์ ํจ๊ป ์์ธํ ์๋ ค๋๋ ค์. ํจ์จ์ ์ธ ํ๋ก ํธ์๋ ์ํคํ ์ฒ๋ฅผ ๊ตฌ์ถํด ๋ณด์ธ์.
- ๋จ์ด: 2,149๊ฐ24๋ถ
[๐ค] ์๋ฐ์คํฌ๋ฆฝํธ Web Workers: UI ๋ธ๋กํน ์์ด ๋ฌด๊ฑฐ์ด ์์ ์ฒ๋ฆฌํ๊ธฐ
ํ๋ก ํธ์๋์์ CPU ์ง์ฝ์ ์ธ ์์ ์ UI ๋ธ๋กํน์ ํํ ๋ฌธ์ ์์. ์๋ฐ์คํฌ๋ฆฝํธ Web Workers๋ก ๋ฉ์ธ ์ค๋ ๋๋ฅผ ํด๋ฐฉํ๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ์ต์ ํํ๋ ์ค์ฉ์ ์ธ ๋ฐฉ๋ฒ์ ์ฝ๋ ์์์ ํจ๊ป ์์๋ณด์ธ์. ๋ณต์กํ ๊ณ์ฐ, ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฑ์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์์ ํ๊ฒ ์คํํ๋ ๋ ธํ์ฐ๋ฅผ ๊ณต์ ํด์.
- ๋จ์ด: 1,810๊ฐ20๋ถ
[๐ค] TypeScript `as const` ์ฌ์ธต ๋ถ์: ๋ฆฌํฐ๋ด ํ์ ์ถ๋ก ๊ณผ ๋ถ๋ณ์ฑ ํ์ฉ ์ ๋ต
TypeScript์ `as const`๋ฅผ ํ์ฉํ์ฌ ๋ฆฌํฐ๋ด ํ์ ์ถ๋ก ์ ๊ฐํํ๊ณ , ๋ฐฐ์ด๊ณผ ๊ฐ์ฒด์ ๋ถ๋ณ์ฑ์ ์์ ํ๊ฒ ํ๋ณดํ๋ ์ค์ฉ์ ์ธ ๋ฐฉ๋ฒ์ ์์ธํ ์์๋ด์. ์ค๋ฌด ์ฝ๋์ ํ์ ์์ ์ฑ๊ณผ ๊ฐ๋ ์ฑ์ ๋์ฌ๋ณด์ธ์.
- ๋จ์ด: 1,470๊ฐ17๋ถ
[๐ค] Next.js @next/font๋ฅผ ํ์ฉํ ํฐํธ ์ต์ ํ ๋ฐ CLS ๊ฐ์ ์ ๋ต
Next.js ์ ํ๋ฆฌ์ผ์ด์ ์์ ํฐํธ ๋ก๋ฉ์ผ๋ก ์ธํ Cumulative Layout Shift(CLS)๋ฅผ ์ต์ํํ๊ณ ์น ์ฑ๋ฅ์ ๊ทน๋ํํ๋ @next/font ์ฌ์ฉ๋ฒ๊ณผ ์ค์ฉ์ ์ธ ์ต์ ํ ์ ๋ต์ ์์ธํ ์์๋ด์.
- ๋จ์ด: 1,843๊ฐ21๋ถ
[๐ค] Next.js App Router ๊ตญ์ ํ (i18n) ์๋ฒฝ ๊ฐ์ด๋: ๋ค๊ตญ์ด ์ง์ ๊ตฌํ ์ ๋ต
Next.js 14+ App Router ํ๊ฒฝ์์ ๊ตญ์ ํ(i18n)๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์์ธํ ์๋ ค๋๋ ค์. ๋ฏธ๋ค์จ์ด๋ฅผ ํ์ฉํ ์ธ์ด ๊ฐ์ง๋ถํฐ ํด๋ผ์ด์ธํธ/์๋ฒ ์ปดํฌ๋ํธ์์์ ๋ค๊ตญ์ด ํ ์คํธ ์ฒ๋ฆฌ๊น์ง, ์ค๋ฌด์ ๋ฐ๋ก ์ ์ฉํ ์ ์๋ ๋ค๊ตญ์ด ์ง์ ์ ๋ต์ ๋ธ๋ฃจ๊ฐ ์๋ดํด ๋๋ฆด๊ฒ์.
- ๋จ์ด: 1,322๊ฐ16๋ถ
[์น ์ฑ๋ฅ ์ต์ ํ] Interaction to Next Paint (INP) ๊ฐ์ : ์ฌ์ฉ์ ๊ฒฝํ์ ๊ทน๋ํํ๋ ์ค์ ์ ๋ต
์๋ก์ด Core Web Vitals ์งํ, Interaction to Next Paint(INP)๋ฅผ ๊น์ด ์ดํดํ๊ณ ์ค์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ INP ์ ์๋ฅผ ๊ฐ์ ํ๋ ์ค์ฉ์ ์ธ ์ต์ ํ ์ ๋ต๋ค์ ๋ธ๋ฃจ๊ฐ ์์ธํ ์๋ ค๋๋ ค์. ์ฌ์ฉ์ ์ธํฐ๋์ ์๋ต์ฑ์ ๋์ฌ ์ง์ ํ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ง๋ค์ด ๋ณด์ธ์.
๋จ์ด: 1,654๊ฐ20๋ถ[๐ค] JavaScript Decorator ์ฌ์ธต ๋ถ์: ๋ฉํํ๋ก๊ทธ๋๋ฐ๊ณผ ํ์ ์คํฌ๋ฆฝํธ ํ์ฉ ์ ๋ต
JavaScript Decorator์ ๊ฐ๋ ๋ถํฐ ํ์ ์คํฌ๋ฆฝํธ์์์ ํ์ฉ, ๊ทธ๋ฆฌ๊ณ ๋ฏธ๋ ํ์คํ ๋ฐฉํฅ๊น์ง ์ฌ์ธต์ ์ผ๋ก ๋ค๋ฃจ๋ฉฐ, ์ค๋ฌด์์ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ๊ณผ ๊ฐ๋ ์ฑ์ ๋์ด๋ ๋ฉํํ๋ก๊ทธ๋๋ฐ ํจํด์ ํ์ตํด ๋ณด์ธ์.
- ๋จ์ด: 2,610๊ฐ28๋ถ
[๐ค] JavaScript ํ๋ก๋ฏธ์ค/async-await ์ฌํ: ์ค์ ํจํด๊ณผ ์ฃผ์์ฌํญ
JavaScript์ ํ๋ก๋ฏธ์ค์ async/await๋ฅผ ๊น์ด ์ดํดํ๊ณ , ์ค๋ฌด์์ ๋ง์ฃผํ๋ ๋ณต์กํ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ํฉ์์ ํ์ฉํ ์ ์๋ ๊ณ ๊ธ ํจํด๊ณผ ํํ ๋ฐ์ํ๋ ์ค์๋ฅผ ๋ฐฉ์งํ๋ ๋ฐฉ๋ฒ์ ์์ธํ ์๋ ค๋๋ ค์.
- ๋จ์ด: 1,418๊ฐ16๋ถ
[๐ค] TypeScript 5.2+ `using` ์ ์ธ์ผ๋ก ์์ ์๋ ๊ด๋ฆฌํ๊ธฐ: ๊น๋ํ ๋ฆฌ์์ค ์ ๋ฆฌ์ ์์
TypeScript 5.2์์ ๋์ ๋ `using` ์ ์ธ์ ํ์ฉํ์ฌ ํ์ผ ํธ๋ค, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ๋ฑ ๋ค์ํ ์์์ ์๋์ผ๋ก ๊ด๋ฆฌํ๊ณ ๊น๋ํ๊ฒ ์ ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ค์ฉ์ ์ธ ์์ ์ ํจ๊ป ์์ธํ ์์๋ด์. ๋ ์ด์ `try...finally` ๋ธ๋ก์ผ๋ก ๋ณต์กํ๊ฒ ์์์ ํด์ ํ ํ์ ์์ด์.
- ๋จ์ด: 2,002๊ฐ22๋ถ
[๐ค] Feature-Sliced Design (FSD)์ผ๋ก ํ์ฅ ๊ฐ๋ฅํ ํ๋ก ํธ์๋ ์ํคํ ์ฒ ๊ตฌ์ถํ๊ธฐ
Feature-Sliced Design (FSD)์ ๋๊ท๋ชจ ํ๋ก ํธ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ฅ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ๋์ด๋ ๊ฐ๋ ฅํ ์ํคํ ์ฒ ํจํด์ด์์. FSD์ ํต์ฌ ์์น, ๋ ์ด์ด ๊ตฌ์กฐ, ์ค๋ฌด ์ ์ฉ ๋ฐฉ๋ฒ์ ์ฝ๋ ์์์ ํจ๊ป ์์ธํ ์์๋ด์.
- ๋จ์ด: 1,781๊ฐ21๋ถ
[๐ค] TypeScript `moduleResolution: 'bundler'`์ `verbatimModuleSyntax` ์๋ฒฝ ์ดํด: ๋ชจ๋ ๋ฒ๋ค๋ฌ ์๋์ ํ์ ์คํฌ๋ฆฝํธ ์ค์ ์ต์ ํ
๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ก์ ํธ์์ TypeScript์ `moduleResolution: 'bundler'`์ `verbatimModuleSyntax` ์ต์ ์ด ์ ์ค์ํ์ง, ์ด๋ป๊ฒ ์ฌ๋ฐ๋ฅด๊ฒ ์ค์ ํ๊ณ ํ์ฉํ์ฌ ๊ฐ๋ฐ ๊ฒฝํ๊ณผ ๋ฒ๋ค๋ง ํจ์จ์ ๊ทน๋ํํ๋์ง ์ค๋ฌด ์์์ ํจ๊ป ์์ธํ ์์๋ด์.
- ๋จ์ด: 1,908๊ฐ24๋ถ
[๐ค] ๋ชจ๋ ธ๋ ํฌ ์ํคํ ์ฒ: ํจ์จ์ ์ธ ๋๊ท๋ชจ ํ๋ก์ ํธ ์ค๊ณ๋ฅผ ์ํ ์ค์ ๊ฐ์ด๋
๋๊ท๋ชจ ์น ํ๋ก์ ํธ์์ ๋ชจ๋ ธ๋ ํฌ๋ฅผ ๋์ ํ๋ ์ด์ , ์ฅ๋จ์ , ๊ทธ๋ฆฌ๊ณ ํจ๊ณผ์ ์ธ ๊ตฌ์กฐ ์ค๊ณ ๋ฐ ์ค๋ฌด ์ ์ฉ ์ ๋ต์ ๋ธ๋ฃจ๊ฐ ์์ธํ ์๋ ค๋๋ ค์. ํ ์์ฐ์ฑ ํฅ์๊ณผ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๊ทน๋ํํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.
๋จ์ด: 2,188๊ฐ26๋ถ[๐ค] ์น ์ฑ๋ฅ ์ต์ ํ: ๋ฆฌํ๋ก์ฐ์ ๋ฆฌํ์ธํธ ์ต์ํ ์ ๋ต
๋ธ๋ผ์ฐ์ ๋ ๋๋ง ๊ณผ์ ์ ํต์ฌ์ธ ๋ฆฌํ๋ก์ฐ(Reflow)์ ๋ฆฌํ์ธํธ(Repaint)์ ๋ฐ์ ์๋ฆฌ๋ฅผ ์ดํดํ๊ณ , ์ด๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ค์ฌ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ๊ทน๋ํํ๋ ์ค์ง์ ์ธ ์ ๋ต๊ณผ ์ฝ๋ ์์๋ฅผ ์์ธํ ์๋ ค๋๋ ค์.
- ๋จ์ด: 1,903๊ฐ19๋ถ
[๐ค] Vitest์ React Testing Library๋ก Next.js ์ปดํฌ๋ํธ ์๋ฒฝ ํ ์คํธํ๊ธฐ
Next.js ํ๋ก์ ํธ์์ Vitest์ React Testing Library๋ฅผ ํ์ฉํ์ฌ UI ์ปดํฌ๋ํธ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํ ์คํธํ๋ ๋ฐฉ๋ฒ์ ์ค๋ฌด ์์ ์ ํจ๊ป ์์ธํ ์์๋ด์. ์ค์ ๋ถํฐ Mocking, ์ด๋ฒคํธ ์๋ฎฌ๋ ์ด์ ๊น์ง, ๊ฒฌ๊ณ ํ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์ ์ํ ํ ์คํธ ์ ๋ต์ ์ตํ๋ณด์ธ์.
- ๋จ์ด: 1,542๊ฐ20๋ถ
[๐ค] Tailwind CSS v4 ์ถ์: ๊ฐ๋ฐ์์๊ฒ ์ฐพ์์ฌ ๋ณํ์ ์ต์ ํ ์ ๋ต
Tailwind CSS v4์ ์ฃผ์ ๋ณ๊ฒฝ์ฌํญ๊ณผ ์๋ก์ด ๊ธฐ๋ฅ๋ค์ ๊น์ด ์๊ฒ ๋ถ์ํ๊ณ , ์ค๋ฌด์์ ํจ์จ์ ์ผ๋ก ์ ์ฉํ๋ฉฐ ์ฑ๋ฅ์ ์ต์ ํํ๋ ์ ๋ต์ ๋ธ๋ฃจ๊ฐ ์๋ ค๋๋ ค์.
- ๋จ์ด: 1,566๊ฐ20๋ถ
[๐ค] Next.js Dockerfile ์ต์ ํ: ํ๋ก๋์ ๋ฐฐํฌ๋ฅผ ์ํ ์๋ฒฝ ๊ฐ์ด๋
Next.js ์ ํ๋ฆฌ์ผ์ด์ ์ Docker ์ปจํ ์ด๋๋ก ํจ์จ์ ์ผ๋ก ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์. ๋ฉํฐ์คํ ์ด์ง ๋น๋, ์บ์ฑ ์ ๋ต, ๋ณด์ ์ค์ ๋ฑ ํ๋ก๋์ ํ๊ฒฝ์ ์ต์ ํ๋ Dockerfile ์์ฑ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํด ๋๋ ค์.
- ๋จ์ด: 2,177๊ฐ24๋ถ
[๐ค] CSS Grid ์ฌํ ๊ฐ์ด๋: ์ค์ ๋ ์ด์์ ํจํด๊ณผ ๋ฐ์ํ ๋์์ธ ์ ๋ต
CSS Grid๋ ๊ฐ๋ ฅํ 2์ฐจ์ ๋ ์ด์์ ์์คํ ์ด์์. ์ด ๊ฐ์ด๋์์ Grid์ ํต์ฌ ๊ฐ๋ ๋ถํฐ ์ค์ ๋ ์ด์์ ํจํด, ๋ฐ์ํ ๋์์ธ ์ ๋ต๊น์ง ์ฌ์ธต์ ์ผ๋ก ๋ค๋ฃจ์ด ์ค๋ฌด์ ๋ฐ๋ก ์ ์ฉํ ์ ์๋๋ก ๋์๋๋ ค์.
- ๋จ์ด: 1,718๊ฐ19๋ถ
[๐ค] TypeScript ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ํ์ : ๋ฌธ์์ด ํ์ ์ ๋ง๋ฒ์ฌ๋ก ๋ณ์ ํ๊ธฐ
TypeScript์ ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ํ์ ์ ํ์ฉํ์ฌ ๋ณต์กํ ๋ฌธ์์ด ํจํด์ ์์ ํ๊ฒ ํ์ ์ถ๋ก ํ๊ณ , ๊ฐ๋ ฅํ ์ ํธ๋ฆฌํฐ ํ์ ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์ค๋ฌด ์์ ์ ํจ๊ป ์์ธํ ์์๋ด์. ํ์ ์์ ์ฑ์ ํ ๋จ๊ณ ๋์ฌ ๊ฐ๋ฐ ๊ฒฝํ์ ๊ฐ์ ํด ๋ณด์ธ์.
- ๋จ์ด: 1,918๊ฐ23๋ถ
[๐ค] JavaScript WeakMap๊ณผ WeakSet: ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฉ์ง์ ์ต์ ํ ์ ๋ต
JavaScript์์ WeakMap๊ณผ WeakSet์ ํ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ๊ณ ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ์ค์ฉ์ ์ธ ์์์ ํจ๊ป ์์ธํ ์์๋ด์. ๊ฐ๋น์ง ์ปฌ๋ ์ ๋์ ์๋ฆฌ์ ํจ๊ป ๊ฐ์ฒด ์ฐธ์กฐ ๊ด๋ฆฌ์ ์ค์์ฑ์ ์ดํดํ๊ณ , ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ๋ ์ ๋ต์ ๋ฐฐ์๋ด์.
- ๋จ์ด: 1,455๊ฐ17๋ถ
[๐ค] Next.js/React ํ๋ก์ ํธ๋ฅผ ์ํ ESLint & Prettier ์ค์ ์๋ฒฝ ๊ฐ์ด๋
๋ณต์กํ Next.js ๋ฐ React ํ๋ก์ ํธ์์ ์ผ๊ด๋ ์ฝ๋ ์คํ์ผ๊ณผ ํ์ง์ ์ ์งํ๋ ESLint์ Prettier ์ค์ ๋ฐฉ๋ฒ์ ์์ธํ ์๋ ค๋๋ ค์. ํ ๊ฐ๋ฐ ํ๊ฒฝ์ ์ต์ ํ๋ ์ค์ ์ผ๋ก ๊ฐ๋ฐ ํจ์จ์ ๋์ฌ๋ณด์ธ์.
- ๋จ์ด: 2,022๊ฐ25๋ถ
[๐ค] JavaScript์ ํต์ฌ: ํ๋กํ ํ์ ์ฒด์ธ ์๋ฒฝ ์ดํด์ ํ์ฉ ์ ๋ต
JavaScript์ ์ฌ์ฅ๋ถ, ํ๋กํ ํ์ ์ฒด์ธ์ ๋์ ์๋ฆฌ๋ฅผ ๊น์ด ํ๊ณ ๋ค์ด ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ๊ณผ ์์์ ์๋ฒฝํ๊ฒ ์ดํดํ๊ณ ์ค๋ฌด์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์. ์ฑ๋ฅ ์ต์ ํ ํ๋ ํจ๊ป ๋ค๋ค์.
- ๋จ์ด: 2,118๊ฐ22๋ถ
[๐ค] React ์ปค์คํ ํ : ์ฌ์ฌ์ฉ์ฑ ๋์ด๋ ์ค๊ณ ์์น๊ณผ ํ ์คํธ ์ ๋ต
React ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ๊ทน๋ํํ๋ ์ปค์คํ ํ ์ค๊ณ ์์น, ์ค์ฉ์ ์ธ ํจํด, ๊ทธ๋ฆฌ๊ณ ๊ฒฌ๊ณ ํ ํ ์คํธ ์ ๋ต์ ์๋์ด ๊ฐ๋ฐ์์ ๊ด์ ์์ ์์ธํ ์ค๋ช ํด ๋๋ ค์.
- ๋จ์ด: 2,107๊ฐ23๋ถ
[๐ค] React useRef ํ ์ฌ์ธต ๋ถ์: DOM ๋์ด์ ์ค์ ํ์ฉ ์ ๋ต
React useRef ํ ์ ๊ธฐ๋ณธ ์๋ฆฌ๋ถํฐ DOM ์์ ์ง์ ์ ์ด, ์ปดํฌ๋ํธ ๋ผ์ดํ์ฌ์ดํด ๊ด๋ฆฌ, ๊ทธ๋ฆฌ๊ณ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํ ๋ค์ํ ์ค์ ํ์ฉ ์ ๋ต๊น์ง ์ฌ์ธต์ ์ผ๋ก ๋ค๋ค์. ์ด์ค๊ธ ๊ฐ๋ฐ์๋ฅผ ์ํ useRef ์๋ฒฝ ๊ฐ์ด๋.
- ๋จ์ด: 1,762๊ฐ19๋ถ
[๐ค] Next.js 14/15์์ ๋์ OG ์ด๋ฏธ์ง ์์ฑ: ImageResponse ์๋ฒฝ ๊ฐ์ด๋
Next.js App Router ํ๊ฒฝ์์ ImageResponse๋ฅผ ํ์ฉํ์ฌ ๋์ OG ์ด๋ฏธ์ง๋ฅผ ํจ์จ์ ์ผ๋ก ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์. SEO์ ์์ ๊ณต์ ์ต์ ํ๋ฅผ ์ํ ์ค์ ๊ฐ์ด๋์ ๋๋ค.
- ๋จ์ด: 1,481๊ฐ18๋ถ
[๐ค] Git ๋ธ๋์น ์ ๋ต: Git Flow vs GitHub Flow, ์ค๋ฌด์์ ์ด๋ป๊ฒ ์ ํํ๊ณ ์ด์ํ ๊น์?
๊ฐ๋ฐํ์ ํจ์จ์ ์ธ ํ์ ์ ์ํ Git ๋ธ๋์น ์ ๋ต์ ๊ณ ๋ฏผํ๊ณ ๊ณ์ ๊ฐ์? Git Flow์ GitHub Flow์ ํต์ฌ ๊ฐ๋ ๋ถํฐ ์ฅ๋จ์ , ๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ ํ์ ๋ง๋ ์ ๋ต์ ์ ํํ๊ณ ์ด์ํ๋ ์ค์ง์ ์ธ ํ๊น์ง '๋ธ๋ฃจ'๊ฐ ์๋ ค๋๋ ค์.
- ๋จ์ด: 1,442๊ฐ16๋ถ
[๐ค] TypeScript ํ์ ๊ฐ๋: ๋ฐํ์ ํ์ ์์ ์ฑ์ ์ํ ํ์ ํจํด ์ ๋ณตํด์
TypeScript์์ ๋ฐํ์์ ๋ณ์์ ํ์ ์ ์์ ํ๊ฒ ์ขํ๋(Narrowing) ๋ฐฉ๋ฒ์ธ ํ์ ๊ฐ๋(Type Guard)์ ๋ํด ์์ธํ ์์๋ด์. `typeof`, `instanceof`, `in` ์ฐ์ฐ์๋ถํฐ ์ฌ์ฉ์ ์ ์ ํ์ ๊ฐ๋๊น์ง, ์ค์ฉ์ ์ธ ์์์ ํจ๊ป ๊ฒฌ๊ณ ํ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ตํ๋ด์.
- ๋จ์ด: 2,542๊ฐ28๋ถ
[๐ค] React Query (TanStack Query) ์ฌํ: ๋ฐ์ดํฐ ํ์นญ, ์บ์ฑ, ๋๊ธฐํ ์ ๋ต์ผ๋ก ์น ์ฑ ์ฑ๋ฅ ๊ทน๋ํํด์
React Query (TanStack Query)๋ฅผ ํ์ฉํ์ฌ ๋ณต์กํ ์๋ฒ ์ํ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ , ์ง๋ฅ์ ์ธ ์บ์ฑ๊ณผ ์๋ ๋๊ธฐํ ์ ๋ต์ผ๋ก ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ๊ณผ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ทน๋ํํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ธต์ ์ผ๋ก ๋ค๋ฃจ์ด์. useQuery, useMutation, useInfiniteQuery ๋ฑ ํต์ฌ ํ ๊ณผ ์ค์ ์ต์ ํ ํ์ ๋ฐฐ์๋ณด์ธ์.
- ๋จ์ด: 2,401๊ฐ26๋ถ
[๐ค] React `useTransition`๊ณผ `useDeferredValue`๋ก ์ฌ์ฉ์ ๊ฒฝํ์ ๊ทน๋ํํ๋ ๋ฐฉ๋ฒ
React ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ฌด๊ฑฐ์ด UI ์ ๋ฐ์ดํธ๋ก ์ธํ ๋ฒ๋ฒ ์์ ํด๊ฒฐํ๊ณ , `useTransition`๊ณผ `useDeferredValue` ํ ์ ํ์ฉํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ํ๊ธฐ์ ์ผ๋ก ๊ฐ์ ํ๋ ์ค์ฉ์ ์ธ ์ ๋ต์ ๋ฐฐ์๋ณด์ธ์.
- ๋จ์ด: 1,917๊ฐ22๋ถ
[๐ค] React Suspense์ ErrorBoundary: ๊ฒฌ๊ณ ํ๊ณ ๋ถ๋๋ฌ์ด UI ๊ฒฝํ์ ์ํ ์ค์ ๊ฐ์ด๋
React ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉ์ ๊ฒฝํ์ ํ์ ํ Suspense์ ErrorBoundary์ ๊ฐ๋ ฅํ ์กฐํฉ์ ๊น์ด ์๊ฒ ๋ค๋ค์. ๋ก๋ฉ ์ํ์ ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ์ฐ์ํ๊ฒ ๊ด๋ฆฌํ์ฌ ๋์ฑ ๊ฒฌ๊ณ ํ๊ณ ๋ถ๋๋ฌ์ด UI๋ฅผ ๋ง๋๋ ์ค์ ํ๊ณผ ์ฝ๋ ์์๋ฅผ ํ์ธํด ๋ณด์ธ์.
- ๋จ์ด: 1,302๊ฐ16๋ถ
[๐ค] CSS Container Queries: ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ๋ฐ์ํ ๋์์ธ์ ์๋ก์ด ์งํ
๋ฏธ๋์ด ์ฟผ๋ฆฌ์ ํ๊ณ๋ฅผ ๋์ด, ์ปดํฌ๋ํธ ์์ฒด์ ํฌ๊ธฐ์ ๋ฐ๋ผ ์คํ์ผ์ ์กฐ์ ํ๋ CSS Container Queries๋ฅผ ๊น์ด ์๊ฒ ์์๋ณด๊ณ ์ค๋ฌด ์ ์ฉ ๋ฐฉ๋ฒ์ ์๋ดํด ๋๋ ค์.
- ๋จ์ด: 1,681๊ฐ19๋ถ
[๐ค] Next.js 15 ๊ณ ๊ธ ๋ฐ์ดํฐ ์บ์ฑ ์ ๋ต: fetch์ revalidate ์ฌ์ธต ๋ถ์
Next.js 15์์ `fetch` API์ ๊ฐ๋ ฅํ ์บ์ฑ ๋ฉ์ปค๋์ฆ๊ณผ `revalidate` ์ต์ ์ ํ์ฉํ์ฌ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ์ต์ ํํ๊ณ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ธต์ ์ผ๋ก ๋ค๋ฃจ์ด์. ์ค๋ฌด ์์๋ฅผ ํตํด ์๋ฒ ์ปดํฌ๋ํธ์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์ ์บ์ฑ ์ ๋ต์ ํจ๊ณผ์ ์ผ๋ก ์ ์ฉํ๋ ํ์ ์ ๊ณตํด์.
๋จ์ด: 1,320๊ฐ14๋ถ[๐ค] Next.js App Router: generateStaticParams๋ก ๋์ ๋ผ์ฐํ ๋น๋ ์ต์ ํํ๊ธฐ
Next.js App Router์์ generateStaticParams ํจ์๋ฅผ ํ์ฉํ์ฌ ๋์ ๋ผ์ฐํ ์ ์ ์ ํ์ด์ง๋ฅผ ํจ์จ์ ์ผ๋ก ์์ฑํ๊ณ ๋น๋ ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ์ค์ฉ์ ์ธ ์์์ ํจ๊ป ์์ธํ ์์๋ด์.
๋จ์ด: 1,891๊ฐ22๋ถ[๐ค] React ๋ ๋๋ง ์ต์ ํ: useMemo, useCallback, React.memo ์๋ฒฝ ๊ฐ์ด๋
์ด์ค๊ธ ๊ฐ๋ฐ์๋ฅผ ์ํ React ๋ ๋๋ง ์ต์ ํ ๊ฐ์ด๋. useMemo, useCallback, React.memo์ ์ ํํ ์ฌ์ฉ๋ฒ๊ณผ ์ค๋ฌด์์ ํํ ์ ์ง๋ฅด๋ ์ค์, ๊ทธ๋ฆฌ๊ณ ์ค์ ์ฑ๋ฅ ํฅ์ ์ ๋ต์ ๋ธ๋ฃจ๊ฐ ์๋ ค๋๋ ค์.
๋จ์ด: 2,145๊ฐ24๋ถ[๐ค] JavaScript Proxy์ Reflect ์ฌ์ธต ๋ถ์: ๋ฉํ ํ๋ก๊ทธ๋๋ฐ์ผ๋ก ์ฝ๋ ๊ฐํํ๊ธฐ
JavaScript Proxy์ Reflect API๋ฅผ ํ์ฉํ ๋ฉํ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฒ์ ์ฌ์ธต ๋ถ์ํด์. ๊ฐ์ฒด ์ ๊ทผ ์ ์ด, ์ ํจ์ฑ ๊ฒ์ฌ, ๋ก๊น , ๋ฐ์ํ ์์คํ ๊ตฌํ ๋ฑ ์ค์ฉ์ ์ธ ํ์ฉ ์ฌ๋ก๋ฅผ ํตํด ์ฝ๋์ ์ ์ฐ์ฑ๊ณผ ์์ ์ฑ์ ๋์ด๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.
- ๋จ์ด: 1,770๊ฐ20๋ถ
[๐ค] React์ `useOptimistic` ํ ์ผ๋ก ๋๊ด์ UI ์ ๋ฐ์ดํธ ๊ตฌํํ๊ธฐ: Server Actions์ ํจ๊ป
React 18/19์ `useOptimistic` ํ ์ ํ์ฉํ์ฌ Server Actions์ ์ฐ๋๋๋ ๋๊ด์ UI ์ ๋ฐ์ดํธ๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ค์ฉ์ ์ธ ์์์ ํจ๊ป ์์ธํ ์์๋ด์. ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์์ฑ์ ๋์ด๋ ๋ ธํ์ฐ๋ฅผ ๊ณต์ ํด์.
๋จ์ด: 1,561๊ฐ17๋ถ[๐ค] TypeScript const Type Parameters: ๋ฆฌํฐ๋ด ํ์ ์ถ๋ก ๊ฐํ์ ์ค์ฉ์ ์ธ ํ์ฉ๋ฒ
TypeScript 5.0์ ๋์ ๋ const Type Parameters๋ฅผ ํ์ฉํ์ฌ ์ ๋ค๋ฆญ ํจ์์ ๋ฆฌํฐ๋ด ํ์ ์ถ๋ก ์ ์ ๊ตํ๊ฒ ์ ์ดํ๊ณ , ๋์ฑ ๊ฒฌ๊ณ ํ ํ์ ์์คํ ์ ๊ตฌ์ถํ๋ ์ค์ฉ์ ์ธ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์. as const์์ ์ฐจ์ด์ ๊ณผ ์ค์ ์ฝ๋ ์์๋ฅผ ํตํด ์ด์ค๊ธ ๊ฐ๋ฐ์๋ ์ฝ๊ฒ ์ดํดํ ์ ์๋๋ก ์ค๋ช ํด ๋๋ ค์.
- ๋จ์ด: 2,028๊ฐ22๋ถ
[๐ค] Next.js/React ์ฑ CLS ์ต์ ํ: ์ํํธ ์๋ ์ฌ์ฉ์ ๊ฒฝํ ๋ง๋ค๊ธฐ
Next.js์ React ์ ํ๋ฆฌ์ผ์ด์ ์์ Cumulative Layout Shift(CLS) ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๋ ์ค์ง์ ์ธ ์ ๋ต๊ณผ ์ฝ๋ ์์๋ฅผ ์์ธํ ์์๋ณด์ธ์. ์น ์ฑ๋ฅ ์ต์ ํ์ ํต์ฌ ์์์ธ CLS๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์๋ ค๋๋ ค์.
- ๋จ์ด: 1,740๊ฐ21๋ถ
[๐ค] Next.js SSR, SSG, ISR ๋ ๋๋ง ์ ๋ต: App Router์์ ์ต์ ์ ์ ํ์?
Next.js App Router์์ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR), ์ ์ ์ฌ์ดํธ ์์ฑ(SSG), ์ฆ๋ถ ์ ์ ์ฌ์์ฑ(ISR) ๊ฐ ๋ ๋๋ง ์ ๋ต์ ๋์ ์๋ฆฌ, ์ฅ๋จ์ , ์ค์ ํ์ฉ ๋ฐ ์ต์ ํ ๋ฐฉ๋ฒ์ ๋น๊ต ๋ถ์ํด๋๋ ค์.
- ๋จ์ด: 1,478๊ฐ17๋ถ
[๐ค] React Context API์ Zustand: ์ ์ญ ์ํ ๊ด๋ฆฌ, ์ธ์ ๋ฌด์์ ์จ์ผ ํ ๊น์?
React ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ญ ์ํ ๊ด๋ฆฌ๋ฅผ ๊ณ ๋ฏผํ๊ณ ๊ณ์ ๊ฐ์? Context API์ ๊ฐ๋ฒผ์ด ์ธ๋ถ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ Zustand๋ฅผ ๋น๊ต ๋ถ์ํ๊ณ , ์ค๋ฌด์์ ๊ฐ ๋๊ตฌ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํ๋ ์ ๋ต์ ์ค์ ์ฝ๋ ์์์ ํจ๊ป ์์ธํ ์๋ ค๋๋ ค์.
- ๋จ์ด: 2,004๊ฐ24๋ถ
[๐ค] Turborepo๋ก Next.js ๋ชจ๋ ธ๋ ํฌ ๊ตฌ์ถ: ํจ์จ์ ์ธ ๊ฐ๋ฐ ๋ฐ ์ต์ ํ ์ ๋ต
Turborepo๋ฅผ ํ์ฉํ์ฌ Next.js ํ๋ก์ ํธ๋ฅผ ๋ชจ๋ ธ๋ ํฌ๋ก ๊ตฌ์ฑํ๊ณ , ๊ณต์ ์ปดํฌ๋ํธ, ์ ํธ๋ฆฌํฐ, CI/CD ์ต์ ํ ๋ฐฉ์์ ์ค๋ฌด ์์์ ํจ๊ป ์์ธํ ์ค๋ช ํด ๋๋ ค์.
- ๋จ์ด: 2,338๊ฐ27๋ถ
[๐ค] React useEffect ํ , ์ด์ ํท๊ฐ๋ฆฌ์ง ๋ง์ธ์! (์์กด์ฑ ๋ฐฐ์ด, ํด๋ฆฐ์ ์๋ฒฝ ๊ฐ์ด๋)
React ๊ฐ๋ฐ์์ ํ์์ ์ธ useEffect ํ ์ ๋์ ์๋ฆฌ๋ถํฐ ์์กด์ฑ ๋ฐฐ์ด, ํด๋ฆฐ์ ํจ์ ํ์ฉ๋ฒ, ๊ทธ๋ฆฌ๊ณ ์ค๋ฌด์์ ์์ฃผ ๊ฒช๋ ์ค์์ ์ต์ ํ ์ ๋ต๊น์ง, ์ด์ค๊ธ ๊ฐ๋ฐ์๋ฅผ ์ํ ์๋ฒฝ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํด์.
- ๋จ์ด: 3,284๊ฐ31๋ถ
[๐ค] Next.js Server Actions ์ค์ : ์๋ฌ ์ฒ๋ฆฌ, ์ ํจ์ฑ ๊ฒ์ฌ, ๋๊ด์ UI ์ ๋ฐ์ดํธ
Next.js Server Actions๋ฅผ ์ค๋ฌด์ ์ ์ฉํ ๋ ๋ง์ฃผํ๋ ์๋ฌ ์ฒ๋ฆฌ, ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ, ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค๋ ๋๊ด์ UI ์ ๋ฐ์ดํธ ๊ธฐ๋ฒ์ ์์ธํ ์ฝ๋ ์์์ ํจ๊ป ์์๋ณด์ธ์.
๋จ์ด: 1,983๊ฐ21๋ถ[๐ค] TypeScript ์ ํธ๋ฆฌํฐ ํ์ ์๋ฒฝ ๊ฐ์ด๋: ์ค์ ํ์ฉ ํจํด
TypeScript ์ ํธ๋ฆฌํฐ ํ์ ์ ํต์ฌ ๊ฐ๋ ๊ณผ ์ค์ ํ์ฉ๋ฒ์ ๊น์ด ์๊ฒ ๋ค๋ค์. Pick, Omit, Partial, Required ๋ฑ ์์ฃผ ์ฐ๋ ์ ํธ๋ฆฌํฐ ํ์ ์ผ๋ก ๋ณต์กํ ํ์ ์ ํจ๊ณผ์ ์ผ๋ก ๋ค๋ฃจ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์. ํ์ ์คํฌ๋ฆฝํธ ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ์์ ์ฑ์ ๋์ด๋ ๋ ธํ์ฐ๋ฅผ ๊ณต์ ํด์.
- ๋จ์ด: 1,712๊ฐ20๋ถ
[๐ค] Next.js App Router ๋ฏธ๋ค์จ์ด: ๊ฐ๋ ฅํ ์์ฒญ ์ฒ๋ฆฌ ์ ๋ต๊ณผ ์ค์ ์์
Next.js App Router ํ๊ฒฝ์์ ๋ฏธ๋ค์จ์ด๋ฅผ ํ์ฉํด ์ฌ์ฉ์ ์ธ์ฆ, ๋ฆฌ๋ค์ด๋ ์ , ๊ตญ์ ํ ๋ฑ์ ์์ฒญ ์ฒ๋ฆฌ ๋ก์ง์ ํจ์จ์ ์ผ๋ก ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ค์ ์์ ์ ํจ๊ป ์์ธํ ์์๋ณด์ธ์.
- ๋จ์ด: 1,630๊ฐ19๋ถ
[๐ค] ํ์ ์คํฌ๋ฆฝํธ ์ ๋ค๋ฆญ ์ฌํ: ์ค์ฉ์ ์ธ ํจํด๊ณผ ํํ ์คํด๋ค
ํ์ ์คํฌ๋ฆฝํธ ์ ๋ค๋ฆญ(Generics)์ ๊น์ด ์ดํดํ๊ณ , ์ค๋ฌด์์ ์์ฃผ ์ฌ์ฉ๋๋ ์ ๋ค๋ฆญ ํจํด๊ณผ ํํ ๊ฒช๋ ์คํด๋ค์ ์ค์ ์ฝ๋ ์์์ ํจ๊ป ์ฝ๊ณ ๋ช ํํ๊ฒ ์ค๋ช ํด ๋๋ ค์. ํ์ ์์ ์ฑ๊ณผ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.
๋จ์ด: 1,860๊ฐ18๋ถ[๐ค] Next.js Route Handler: App Router์์ ์์ ํ๊ณ ํจ์จ์ ์ธ API ๊ตฌ์ถํ๊ธฐ (์ธ์ฆ, ์๋ฌ ์ฒ๋ฆฌ ํฌํจ)
Next.js App Router์ Route Handler๋ฅผ ์ฌ์ฉํ์ฌ API ์๋ํฌ์ธํธ๋ฅผ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ ์์ธํ ์์๋ด์. ์ธ์ฆ, ์๋ฌ ์ฒ๋ฆฌ, ๊ทธ๋ฆฌ๊ณ ์บ์ฑ ์ ๋ต์ ํฌํจํ ์ค์ฉ์ ์ธ ํ์ผ๋ก ์์ ํ๊ณ ํจ์จ์ ์ธ ์๋ฒ๋ฆฌ์ค ํจ์๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์ตํ๋ด์.
- ๋จ์ด: 1,934๊ฐ22๋ถ
[๐ค] Next.js Image ์ปดํฌ๋ํธ ์ต์ ํ: Core Web Vitals ๊ฐ์ ๋ถํฐ ์ค์ ํ์ฉ๊น์ง
Next.js์ Image ์ปดํฌ๋ํธ๋ฅผ ํ์ฉํ์ฌ ์น ์ฑ๋ฅ ํต์ฌ ์งํ์ธ Core Web Vitals๋ฅผ ๊ฐ์ ํ๊ณ , ๋ค์ํ ์ต์ ํ ์ต์ ์ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ธ๋ฃจ๊ฐ ์์ธํ ์๋ ค๋๋ ค์.
- ๋จ์ด: 2,187๊ฐ25๋ถ
[๐ค] Next.js 14.1+์ ํ์ : Partial Prerendering (PPR) ์๋ฒฝ ๊ฐ์ด๋์ ์ค์ ์ต์ ํ ์ ๋ต
Next.js 14.1๋ถํฐ ๋์ ๋ Partial Prerendering (PPR)์ ํตํด ์ด๊ธฐ ๋ก๋ฉ ์๋๋ฅผ ๊ทน๋ํํ๊ณ ๋์ ์ฝํ ์ธ ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ ์๊ฒ ๋ค๋ฃจ์ด์. PPR์ ๋์ ์๋ฆฌ๋ถํฐ ์ค์ ํ๋ก์ ํธ ์ ์ฉ ์ ๋ต๊น์ง, ๊ฐ๋ฐ์๋ค์ด ๊ถ๊ธํดํ๋ ๋ชจ๋ ๊ฒ์ ์๋ ค๋๋ ค์.
- ๋จ์ด: 1,792๊ฐ19๋ถ
[๐ค] TypeScript ์กฐ๊ฑด๋ถ ํ์ ๊ณผ infer ํค์๋: ๋ณต์กํ ํ์ ๋ ์์ฝ๊ฒ ๋ค๋ฃจ๋ ๋ฐฉ๋ฒ
TypeScript ๊ฐ๋ฐ์์ ๋ง์ฃผํ๋ ๋ณต์กํ ํ์ ์ถ๋ก ๋ฌธ์ , ์กฐ๊ฑด๋ถ ํ์ ๊ณผ infer ํค์๋๋ฅผ ํ์ฉํ๋ฉด ํจ์ฌ ์ฐ์ํ๊ณ ๊ฐ๋ ฅํ๊ฒ ํด๊ฒฐํ ์ ์์ด์. ์ค์ ์์ ์ ํจ๊ป ๊ทธ ํ์ฉ๋ฒ์ ์ฌ๋ ์๊ฒ ๋ค๋ค๋ด ๋๋ค.
- ๋จ์ด: 1,705๊ฐ21๋ถ
[๐ค] JavaScript ์ด๋ฒคํธ ๋ฃจํ(Event Loop) ์์ ์ ๋ณต: ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ๋ฐํ์ ๋์ ์๋ฆฌ
JavaScript์ ํต์ฌ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๋ฉ์ปค๋์ฆ์ธ ์ด๋ฒคํธ ๋ฃจํ์ ๋์ ์๋ฆฌ๋ฅผ ์ฌ๋ ์๊ฒ ํํค์ณ ๋ด์. ์ฝ ์คํ, ํ์คํฌ ํ, ๋ง์ดํฌ๋กํ์คํฌ ํ์์ ์ํธ์์ฉ์ ์ดํดํ๊ณ , ์ค๋ฌด์์ ๋ง์ฃผ์น๋ ๋น๋๊ธฐ ์ฝ๋์ ๋์์ ๋ช ํํ ์์ธกํ๋ ๋ฐฉ๋ฒ์ ์๋ ค๋๋ ค์.
- ๋จ์ด: 1,964๊ฐ23๋ถ
[๐ค] Next.js Server & Client Components, ์ค์ ์์ ํ๋ช ํ๊ฒ ์ ํํ๋ ๊ฐ์ด๋
Next.js App Router์์ Server Components์ Client Components ์ค ์ด๋ค ๊ฒ์ ์ฌ์ฉํด์ผ ํ ์ง ๊ณ ๋ฏผ์ด์ ๊ฐ์? ์ด ๊ธ์์ ๋ ์ปดํฌ๋ํธ์ ํต์ฌ ์ฐจ์ด์ , ์ฌ์ฉ ์์ , ๊ทธ๋ฆฌ๊ณ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํ ์ค์ ์ ๋ต์ ๋ธ๋ฃจ๊ฐ ์๋ ค๋๋ฆด๊ฒ์.
- ๋จ์ด: 1,879๊ฐ21๋ถ
[๐ค] TypeScript satisfies ์ฐ์ฐ์: ํ์ ์ถ๋ก ๊ณผ ์์ ์ฑ์ ๋์์ ์ก๋ ๋น๋ฒ
TypeScript์ `satisfies` ์ฐ์ฐ์๋ฅผ ํ์ฉํ์ฌ ํ์ ์ถ๋ก ์ ์ ์ฐ์ฑ์ ์ ์งํ๋ฉด์๋ ์๊ฒฉํ ํ์ ์์ ์ฑ์ ํ๋ณดํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์. ์ค์ฉ์ ์ธ ์์๋ฅผ ํตํด ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ๋ ๋ ธํ์ฐ๋ฅผ ๊ณต์ ํฉ๋๋ค.
- ๋จ์ด: 1,211๊ฐ15๋ถ
[๐ค] React 19 ์๋ก์ด ๊ธฐ๋ฅ: use ํ , Actions, ๊ทธ๋ฆฌ๊ณ ์ปดํ์ผ๋ฌ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
React 19์ ํต์ฌ ๋ณ๊ฒฝ ์ฌํญ์ธ use ํ , ์๋ฒ ์ก์ , ๊ทธ๋ฆฌ๊ณ React ์ปดํ์ผ๋ฌ์ ๋์ ๋ฐฐ๊ฒฝ๊ณผ ์ค์ ํ์ฉ ์์๋ฅผ ์ด์ค๊ธ ๊ฐ๋ฐ์ ๋๋์ด์ ๋ง์ถฐ ์์ธํ ์ค๋ช ํฉ๋๋ค. ์ต์ React ์ ๋ฐ์ดํธ๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ๊ณผ ๊ฐ๋ฐ ๊ฒฝํ์ ํฅ์์ํค๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์.
- ๋จ์ด: 1,524๊ฐ16๋ถ
[๐ค] Next.js App Router ์บ์ฑ ์ ๋ต: ๋ฐ์ดํฐ ์ฌ๊ฒ์ฆ (revalidatePath, revalidateTag) ์๋ฒฝ ๊ฐ์ด๋
Next.js 14 App Router์์ ํจ์จ์ ์ธ ๋ฐ์ดํฐ ์บ์ฑ ์ ๋ต๊ณผ revalidatePath, revalidateTag๋ฅผ ์ด์ฉํ ๋ฐ์ดํฐ ์ฌ๊ฒ์ฆ ๋ฐฉ๋ฒ์ ์ค๋ฌด ์์์ ํจ๊ป ์์ธํ ์์๋ณด๊ณ ์น ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.