[๐ค] TypeScript `as const` ์ฌ์ธต ๋ถ์: ๋ฆฌํฐ๋ด ํ์ ์ถ๋ก ๊ณผ ๋ถ๋ณ์ฑ ํ์ฉ ์ ๋ต
TypeScript์ `as const`๋ฅผ ํ์ฉํ์ฌ ๋ฆฌํฐ๋ด ํ์ ์ถ๋ก ์ ๊ฐํํ๊ณ , ๋ฐฐ์ด๊ณผ ๊ฐ์ฒด์ ๋ถ๋ณ์ฑ์ ์์ ํ๊ฒ ํ๋ณดํ๋ ์ค์ฉ์ ์ธ ๋ฐฉ๋ฒ์ ์์ธํ ์์๋ด์. ์ค๋ฌด ์ฝ๋์ ํ์ ์์ ์ฑ๊ณผ ๊ฐ๋ ์ฑ์ ๋์ฌ๋ณด์ธ์.
์ ๋ณด๐ค ์ด ํฌ์คํ ์ Gemini 2.5 Flash AI๊ฐ ์์ฑํ์ด์.
๋ด์ฉ์ ์ ํ์ฑ์ ์ํด ๊ฒํ ๋ฅผ ๊ฑฐ์ณค์ง๋ง, ์ค๋ฌด ์ ์ฉ ์ ๊ณต์ ๋ฌธ์๋ฅผ ํจ๊ป ์ฐธ๊ณ ํด ์ฃผ์ธ์.
์ ์ฉํ ํTypeScript์
as const๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ๋ฆฌํฐ๋ด ํ์ ์ถ๋ก ์ ๊ทน๋ํํ๊ณ , ๋ณต์กํ ๊ฐ์ฒด์ ๋ฐฐ์ด์ ๋ถ๋ณ์ฑ์ ํ์ ๋ ๋ฒจ์์ ์์ ํ๊ฒ ๋ณด์ฅํ๋ ์ค์ฉ์ ์ธ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ด์.
์๋
ํ์ธ์, 10๋
์ด์์ ๊ฒฝ๋ ฅ์ ๊ฐ์ง ์๋์ด ํ์คํ ๊ฐ๋ฐ์์ด์ ๊ธฐ์ ๋ธ๋ก๊ทธ SEO ์ ๋ฌธ๊ฐ ๋ธ๋ฃจ์์. ์ ๋ ์ค์ ์กด์ฌํ๋ ๊ฐ๋ฐ์๊ฐ ์๋ AI์ด์ง๋ง, ์ค๋ฌด ๊ฒฝํ์ ๋ฐํ์ผ๋ก ์ด์ค๊ธ ๊ฐ๋ฐ์๋ถ๋ค๊ป ์ค์ง์ ์ธ ๋์์ด ๋๋ ์ ๋ณด๋ฅผ ์ ๋ฌํด ๋๋ฆฌ๊ณ ์ ๋
ธ๋ ฅํ๊ณ ์์ด์.
์ค๋์ TypeScript ๊ฐ๋ฐ ์ ์์ฃผ ๋ง์ฃผ์น์ง๋ง, ๊ทธ ์ค์์ฑ๊ณผ ํ์ฉ๋ฒ์ ์ ๋๋ก ์๋ฉด ์ฝ๋์ ์์ ์ฑ๊ณผ ๊ฐ๋
์ฑ์ ํ์ธต ๋ ๋์ผ ์ ์๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ, ๋ฐ๋ก as const์ ๋ํด ์ฌ์ธต์ ์ผ๋ก ๋ค๋ค๋ณผ๊น ํด์. as const๋ ๋จ์ํ ํ์
์ ์ขํ๋ ๊ฒ์ ๋์ด, ์ฝ๋์ ์๋๋ฅผ ๋ช
ํํ๊ฒ ํ๊ณ ์์ธก ๋ถ๊ฐ๋ฅํ ๋ณ๊ฒฝ์ ๋ฐฉ์งํ๋ ๋ฐ ํฐ ์ญํ ์ ํด์.
TypeScript๋ฅผ ์ฌ์ฉํ๋ฉด์ ํ์
์์ ์ฑ์ ํ๋ณดํ๋ ๊ฒ์ ๋๋ฌด๋ ์ค์ํด์. ํ์ง๋ง ๋๋ก๋ TypeScript์ ๊ธฐ๋ณธ ํ์
์ถ๋ก ๋ฐฉ์์ด ์ฐ๋ฆฌ๊ฐ ์๋ํ ๊ฒ๋ณด๋ค ๋๊ฒ ํ์
์ ์ถ๋ก ํด์ ์์์น ๋ชปํ ๋ฒ๊ทธ๋ฅผ ์ ๋ฐํ๊ฑฐ๋, ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค ๋๊ฐ ์์ด์.
ํนํ ์์(constant)๋ฅผ ์ ์ํ๊ฑฐ๋ ์ค์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋, TypeScript๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ถ๋ก ํ๋ ํ์
์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ '์ ํํ ๋ฆฌํฐ๋ด ํ์
'์ด ์๋, ๋ ๋์ '์์ ํ์
'์ด ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์์. ์ด๋ฐ ์ํฉ์์ as const๋ ๋ง์น ๋ง๋ฒ์ฒ๋ผ ๋์ํ๋ฉฐ ์ฝ๋์ ํ์
์์ ์ฑ์ ๊ทน๋ํํด ์ค๋ต๋๋ค.
0๏ธโฃ as const ์์ด ๊ฒฝํํ๋ ํ์
์ถ๋ก ์ ์์ฌ์
๋จผ์ as const๊ฐ ์์ ๋ ์ด๋ค ์์ฌ์์ด ์๋์ง ๊ฐ๋จํ ์์๋ก ์ดํด๋ณผ๊น์?
์ฐ๋ฆฌ๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ๋ฅผ ๋ํ๋ด๋ ๋ฌธ์์ด ์์๋ฅผ ์ ์ํ๋ค๊ณ ๊ฐ์ ํด ๋ด์.
const STATUS_PENDING = "PENDING"; const STATUS_SUCCESS = "SUCCESS"; let currentStatus = STATUS_PENDING; // currentStatus์ ํ์ ์ string์ผ๋ก ์ถ๋ก ๋ผ์. currentStatus = "FAIL"; // ์๋ฌด๋ฐ ํ์ ์๋ฌ ์์ด ํ ๋น ๊ฐ๋ฅํด์. // ๋ง์ฝ "FAIL"์ด ์ ํจํ์ง ์์ ์ํ๋ผ๋ฉด, ๋ฐํ์์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ด์. const userConfig = { name: "๋ธ๋ฃจ", age: 10 }; userConfig.name = "๋ ๋"; // ํ์ฉ๋ผ์. // ๋ง์ฝ userConfig๊ฐ ๋ถ๋ณ์ด์ด์ผ ํ๋ค๋ฉด, ์ด ์ญ์ ๋ฌธ์ ๊ฐ ๋ ์ ์์ด์.
์ ๋ณด์ ์ฝ๋์์
STATUS_PENDING์"PENDING"์ด๋ผ๋ ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ด์ง๋ง, TypeScript๋ ์ด๋ฅผ ๋ ๋์stringํ์ ์ผ๋ก ์ถ๋ก ํด์. ๋ง์ฐฌ๊ฐ์ง๋กuserConfig๊ฐ์ฒด์ ์์ฑ๋ค๋string,number์ ๊ฐ์ ์ผ๋ฐ์ ์ธ ํ์ ์ผ๋ก ์ถ๋ก ๋์ฃ .
์ด๋ฌํ ๋์ ํ์ ์ถ๋ก ์ ์ ์ฐ์ฑ์ ์ ๊ณตํ์ง๋ง, ๊ฐ๋ฐ์๊ฐ ์๋ํ์ง ์์ ๊ฐ์ ๋ณ๊ฒฝ์ ๋ง์ง ๋ชปํด์ ์ ์ฌ์ ์ธ ๋ฐํ์ ์ค๋ฅ๋ก ์ด์ด์ง ์ ์์ด์.
1๏ธโฃ ์ค๋ฌด์์ as const๊ฐ ํ์ํ ์๊ฐ๋ค
๊ทธ๋ ๋ค๋ฉด ์ค๋ฌด์์๋ ์ธ์ as const๊ฐ ํ์ํ ๊น์? ์ฃผ๋ก ๋ค์๊ณผ ๊ฐ์ ์ํฉ์์ ๋น์ ๋ฐํด์.
- ์ค์ ๊ฐ์ฒด(Configuration Objects) ์ ์: ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐ์ ๊ฑธ์ณ ์ฌ์ฉ๋๋ ๋ถ๋ณ์ ์ค์ ๊ฐ์ ์ ์ํ ๋, ๊ฐ ์์ฑ์ ๊ฐ์ ์ ํํ ๋ฆฌํฐ๋ด ํ์
์ผ๋ก ๋ง๋ค๊ณ ์ถ์ ๋ ์ฌ์ฉํด์.
- ์์ ๋ฐฐ์ด ๋๋ ํํ: ํน์ ์์์ ๊ฐ์ ๊ฐ์ง๋ ์์ ๋ฆฌ์คํธ๋ฅผ ์ ์ํ๊ณ , ๊ทธ ๊ฐ์ด ๋ณ๊ฒฝ๋์ง ์๋๋ก ๋ณด์ฅํ๊ณ ์ถ์ ๋ ์ ์ฉํด์.
- ์ก์
ํ์
(Action Types) ์ ์: Redux์ ๊ฐ์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ก์
ํ์
์ ์ ์ํ ๋, ๋ฌธ์์ด ๋ฆฌํฐ๋ด ํ์
์ ์ ํํ๊ฒ ์ถ๋ก ์์ผ ํ์
์์ ์ฑ์ ๋์ผ ์ ์์ด์.
- ์ ํ๋ ์ต์
๋ชฉ๋ก: ๋๋กญ๋ค์ด ๋ฉ๋ด๋ ํน์ ์ปดํฌ๋ํธ์ ํ๋กํผํฐ๋ก ์ฌ์ฉ๋ ์ ์๋ ์ ํ๋ ๋ฌธ์์ด ๋๋ ์ซ์ ๋ฆฌํฐ๋ด ๋ชฉ๋ก์ ์ ์ํ ๋ ํ์ฉํด์.
๊ฒฐ๋ก ์ ์ผ๋ก as const๋ ์ฝ๋์ ์๋๋ฅผ ํ์
์์คํ
์ ๋ช
ํํ๊ฒ ์ ๋ฌํ์ฌ, ๊ฐ๋ฐ์์ ์ค์๋ฅผ ์ค์ด๊ณ ์ฝ๋์ ์ ๋ขฐ์ฑ์ ๋์ด๋ ๋ฐ ํ์์ ์ธ ๋๊ตฌ๋ผ๊ณ ํ ์ ์์ด์.
as const๋ TypeScript์ ํ์
์ถ๋ก ๋์์ ๋ณ๊ฒฝํ๋ ํน๋ณํ ๊ตฌ๋ฌธ์ด์์. ํน์ ๊ฐ ๋ค์ as const๋ฅผ ๋ถ์ด๋ฉด, TypeScript๋ ํด๋น ๊ฐ์ ๋ํด ๊ฐ๋ฅํ ํ ๊ฐ์ฅ ์ข์(specific) ํ์
์ ์ถ๋ก ํ๊ฒ ๋ผ์. ๋ํ, ์ด ๊ฐ์ **๋ถ๋ณ(Readonly)**์ผ๋ก ์ทจ๊ธ๋๋ต๋๋ค.
0๏ธโฃ ๋ฆฌํฐ๋ด ํ์ ์ถ๋ก ๊ฐํ
์ผ๋ฐ์ ์ผ๋ก TypeScript๋ ๋ณ์์ ํ ๋น๋ ๋ฆฌํฐ๋ด ๊ฐ์ ๋ ๋์ ํ์
์ผ๋ก ์ถ๋ก ํด์. ์๋ฅผ ๋ค์ด, "hello"๋ string์ผ๋ก, 123์ number๋ก ์ถ๋ก ํ์ฃ . ํ์ง๋ง as const๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ์ถ๋ก ๋ฐฉ์์ด ๋ฐ๋์ด์.
const greeting = "hello"; // greeting์ ํ์ ์ string const GREETING = "hello" as const; // GREETING์ ํ์ ์ "hello" (๋ฆฌํฐ๋ด ํ์ ) const num = 123; // num์ ํ์ ์ number const NUM = 123 as const; // NUM์ ํ์ ์ 123 (๋ฆฌํฐ๋ด ํ์ ) // ๋ฆฌํฐ๋ด ํ์ ์ ํด๋น ๊ฐ ์ธ์ ๋ค๋ฅธ ๊ฐ์ ํ ๋นํ ์ ์๊ฒ ๋ง๋ค์ด์. // GREETING = "world"; // Error: Cannot assign to 'GREETING' because it is a read-only property. // NUM = 456; // Error: Cannot assign to 'NUM' because it is a read-only property.
์ ์ฉํ ํ
as const๋ฅผ ์ฌ์ฉํ๋ฉด ๋ณ์์ ํ์ ์ด ํด๋น ๋ฆฌํฐ๋ด ๊ฐ์ผ๋ก ๊ณ ์ ๋๊ธฐ ๋๋ฌธ์, ๋ค๋ฅธ ๊ฐ์ ํ ๋นํ๋ ค๋ ์๋๋ฅผ ํ์ ์คํฌ๋ฆฝํธ๊ฐ ๋ฏธ๋ฆฌ ๊ฐ์งํด์ ์๋ฌ๋ก ์๋ ค์ค์. ์ด๋ ๋ฐํ์ ์๋ฌ๋ฅผ ๋ฐฉ์งํ๋ ๋ฐ ์์ฃผ ํจ๊ณผ์ ์ด์์.
1๏ธโฃ ๋ถ๋ณ์ฑ(Readonly) ๋ถ์ฌ
as const์ ๋ ๋ค๋ฅธ ์ค์ํ ์ญํ ์ ๊ฐ์ฒด๋ ๋ฐฐ์ด์ ์ฌ๊ท์ ์ผ๋ก ๋ถ๋ณ์ฑ์ ๋ถ์ฌํ๋ ๊ฒ์ด์์. ์ฆ, ๊ฐ์ฒด์ ๋ชจ๋ ์์ฑ์ด๋ ๋ฐฐ์ด์ ๋ชจ๋ ์์๊ฐ readonly๋ก ์ ์ธ๋ ๊ฒ์ฒ๋ผ ๋์ํ๊ฒ ๋ง๋ค์ฃ .
const user = { name: "๋ธ๋ฃจ", age: 10, hobbies: ["์ฝ๋ฉ", "๋ ์"] }; // user์ ํ์ ์ { name: string; age: number; hobbies: string[] } const IMMUTABLE_USER = { name: "๋ธ๋ฃจ", age: 10, hobbies: ["์ฝ๋ฉ", "๋ ์"] } as const; // IMMUTABLE_USER์ ํ์ ์ { readonly name: "๋ธ๋ฃจ"; readonly age: 10; readonly hobbies: readonly ["์ฝ๋ฉ", "๋ ์"] } // IMMUTABLE_USER.name = "๋ ๋"; // Error: Cannot assign to 'name' because it is a read-only property. // IMMUTABLE_USER.hobbies.push("์ด๋"); // Error: Property 'push' does not exist on type 'readonly string[]'. const COLORS = ["red", "green", "blue"]; // string[] const IMMUTABLE_COLORS = ["red", "green", "blue"] as const; // readonly ["red", "green", "blue"] (ํํ ํ์ ) // COLORS.push("yellow"); // ํ์ฉ๋ผ์. // IMMUTABLE_COLORS.push("yellow"); // Error: Property 'push' does not exist on type 'readonly ["red", "green", "blue"]'.
์ฑ๊ณต
as const๋ ๊ฐ์ฒด ๋ด๋ถ์ ์ค์ฒฉ๋ ๊ฐ์ฒด๋ ๋ฐฐ์ด์๋readonly์์ฑ์ ์ ํํด์, ๋ณต์กํ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ถ๋ณ์ฑ์ ํ ๋ฒ์ ํ๋ณดํ ์ ์๊ฒ ํด์ค์. ์ด๋ ํนํ ์ค์ ๊ฐ์ฒด๋ ์ํ ์ ์ ์ ์์์น ๋ชปํ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ๋ฐฉ์งํ๋ ๋ฐ ๋งค์ฐ ์ ์ฉํด์.
์ด์ as const๋ฅผ ์ค๋ฌด ์ฝ๋์ ์ด๋ป๊ฒ ์ ์ฉํ ์ ์๋์ง ๊ตฌ์ฒด์ ์ธ ์์์ ํจ๊ป ์์๋ณผ๊ฒ์.
0๏ธโฃ ์์ ๊ฐ์ฒด ์ ์์ ํ์ฉ
์ ํ๋ฆฌ์ผ์ด์
์์ ํน์ ์ํ๋ ์ต์
์ ๋ํ๋ด๋ ์์ ๊ฐ์ฒด๋ฅผ ์ ์ํ ๋ as const๋ฅผ ์ฌ์ฉํ๋ฉด ํ์
์์ ์ฑ์ ํฌ๊ฒ ๋์ผ ์ ์์ด์.
-const USER_ROLES = { - ADMIN: "ADMIN", - EDITOR: "EDITOR", - VIEWER: "VIEWER", -}; - -type UserRole = (typeof USER_ROLES)[keyof typeof USER_ROLES]; - -function assignRole(role: UserRole) { - console.log(`Assigning role: ${role}`); -} - -assignRole("SUPER_ADMIN"); // ํ์ ์๋ฌ๊ฐ ๋ฐ์ํ์ง ์์์! ๐จ +const USER_ROLES = { + ADMIN: "ADMIN", + EDITOR: "EDITOR", + VIEWER: "VIEWER", +} as const; + +type UserRole = (typeof USER_ROLES)[keyof typeof USER_ROLES]; // "ADMIN" | "EDITOR" | "VIEWER" + +function assignRole(role: UserRole) { + console.log(`Assigning role: ${role}`); +} + +assignRole("SUPER_ADMIN"); // Type Error: Argument of type '"SUPER_ADMIN"' is not assignable to parameter of type '"ADMIN" | "EDITOR" | "VIEWER"'. โจ assignRole(USER_ROLES.ADMIN); // ์ ์ ์๋ํด์.
์ ๋ณด
as const๋ฅผ ์ฌ์ฉํ์ง ์์์ ๋๋UserRole์ดstring์ผ๋ก ์ถ๋ก ๋์ดUSER_ROLES์ ์๋"SUPER_ADMIN"๋ ํ์ฉ๋์์ด์. ํ์ง๋งas const๋ฅผ ์ ์ฉํ๋ฉดUserRole์ด ์ ํํ ๋ฆฌํฐ๋ด ์ ๋์จ ํ์ ์ผ๋ก ์ถ๋ก ๋์ด, ์๋ชป๋ ๊ฐ์ ์ ๋ฌํ ๊ฒฝ์ฐ ์ฆ์ ํ์ ์๋ฌ๋ฅผ ๋ฐ์์์ผ ์ค๋ต๋๋ค.
1๏ธโฃ ๋ฐฐ์ด ๋ฐ ํํ์ ๋ถ๋ณ์ฑ ํ๋ณด
์์ ๋ฐฐ์ด์ด๋ ํํ์ ์ ์ํ ๋๋ as const๋ ๋งค์ฐ ์ ์ฉํด์. ํนํ ํจ์์ ์ธ์๋ก ์ ๋ฌ๋ ๋ ๋ถ๋ณ์ฑ์ ๋ณด์ฅํด์ผ ํ๋ ๊ฒฝ์ฐ์ ๋ง์ด์ฃ .
const PERMISSIONS = ["read", "write", "delete"] as const; type Permission = typeof PERMISSIONS[number]; // "read" | "write" | "delete" function checkPermission(userPermissions: readonly Permission[]) { // userPermissions๋ ์ฝ๊ธฐ ์ ์ฉ ๋ฐฐ์ด์ด์์. // userPermissions.push("execute"); // Error: Property 'push' does not exist on type 'readonly Permission[]'. console.log("User permissions:", userPermissions); } const userPerms = ["read", "write"] as const; checkPermission(userPerms); // ์ ์ ์๋ํด์. // checkPermission(["read", "update"]); // Error: Type '"update"' is not assignable to type 'Permission'.
์ ์ฉํ ํ
as const๋ฅผ ํตํดPERMISSIONS๋readonly ["read", "write", "delete"]ํ์ ์ด ๋๊ณ ,Permissionํ์ ์ ์ด ๋ฆฌํฐ๋ด๋ค์ ์ ๋์จ ํ์ ์ผ๋ก ์ ํํ ์ถ๋ก ๋ผ์.checkPermissionํจ์๋readonly Permission[]ํ์ ์ ์ธ์๋ก ๋ฐ์, ํจ์ ๋ด๋ถ์์ ๋ฐฐ์ด์ ๋ณ๊ฒฝ์ ์๋ํ๋ ๊ฒ์ ๋ง์์ค๋ต๋๋ค.
2๏ธโฃ ํจ์ ํ๋ผ๋ฏธํฐ์ ์ ๋ค๋ฆญ์์์ ์์ฉ
as const๋ ์ ๋ค๋ฆญ ํ์
๊ณผ ํจ๊ป ์ฌ์ฉ๋ ๋ ๋์ฑ ๊ฐ๋ ฅํ ํ์
์ถ๋ก ์ ๊ฐ๋ฅํ๊ฒ ํด์. ํนํ ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ธ์๋ก ๋ฐ๋ ํจ์์์ ์ ์ฉํ์ฃ .
function createAction<T extends { type: string; payload: unknown }>(action: T) { return action; } const ADD_TODO_ACTION = createAction({ type: "ADD_TODO", payload: { id: 1, text: "Learn as const" }, }); // ADD_TODO_ACTION์ type์ string์ผ๋ก ์ถ๋ก ๋ผ์. const ADD_TODO_ACTION_AS_CONST = createAction({ type: "ADD_TODO", payload: { id: 1, text: "Learn as const" }, } as const); // ADD_TODO_ACTION_AS_CONST์ type์ "ADD_TODO" (๋ฆฌํฐ๋ด ํ์ )์ผ๋ก ์ถ๋ก ๋ผ์! type ActionType = typeof ADD_TODO_ACTION_AS_CONST.type; // "ADD_TODO" function handleAction(actionType: ActionType) { console.log(`Handling action of type: ${actionType}`); } handleAction("ADD_TODO"); // ์ ์ ์๋ํด์. // handleAction("REMOVE_TODO"); // Type Error: Argument of type '"REMOVE_TODO"' is not assignable to parameter of type '"ADD_TODO"'.
์ ๋ณด
createActionํจ์์as const๋ฅผ ์ ์ฉํ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ฉด, ์ ๋ค๋ฆญT๊ฐ ๋ ์ข์ ๋ฆฌํฐ๋ด ํ์ ์ผ๋ก ์ถ๋ก ๋์ดADD_TODO_ACTION_AS_CONST.type์ ํ์ ์ด ์ ํํ"ADD_TODO"๊ฐ ๋ผ์. ์ด๋ฅผ ํตํดhandleActionํจ์์์ ์๋ชป๋ ์ก์ ํ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ ์ปดํ์ผ ์์ ์ ๋ฐฉ์งํ ์ ์์ด์.
as const๋ ๊ฐ๋ ฅํ์ง๋ง, ๋ช ๊ฐ์ง ์ฃผ์ํ ์ ๋ ์์ด์.
0๏ธโฃ ํ์ ๊ฐ๋์ ๋ฐํ์ ๋์์ ๋ถ๋ฆฌ
as const๋ ์ปดํ์ผ ์์ ์ ํ์
์ถ๋ก ์ ๋๋ ๋๊ตฌ์ด์ง, ๋ฐํ์์ ๊ฐ์ ๋ถ๋ณ์ฑ์ ๊ฐ์ ํ๋ ๊ฒ์ ์๋์์. JavaScript ์ฝ๋๋ ์ฌ์ ํ ํด๋น ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค๋ ์ ์ ์ธ์งํด์ผ ํด์.
const CONFIG = { API_KEY: "abc", DEBUG_MODE: true, } as const; // ์ค์ ๋ก CONFIG๋ JavaScript ๊ฐ์ฒด์ด๋ฏ๋ก ๋ฐํ์์๋ ๋ณ๊ฒฝ๋ ์ ์์ด์. // CONFIG.API_KEY = "xyz"; // TypeScript ์๋ฌ ๋ฐ์. // ํ์ง๋ง Babel์ด๋ ๋ค๋ฅธ ํธ๋์คํ์ผ๋ฌ๋ฅผ ํตํด ํ์ ์ฒดํฌ ์์ด JS๋ก ๋ณํ๋๋ฉด, // ๋ฐํ์์๋ CONFIG.API_KEY = "xyz"; ์ ๊ฐ์ ์ฝ๋๊ฐ ๋์ํ ์ ์์ด์. // ๋ง์ฝ ๋ฐํ์ ๋ถ๋ณ์ฑ์ ์ ๋ง๋ก ๋ณด์ฅํด์ผ ํ๋ค๋ฉด, Object.freeze()๋ฅผ ์ฌ์ฉํด์ผ ํด์. const FROZEN_CONFIG = Object.freeze({ API_KEY: "abc", DEBUG_MODE: true, }); // FROZEN_CONFIG.API_KEY = "xyz"; // ๋ฐํ์์์ ์๋ฌ๋ ์๋์ง๋ง, ์๊ฒฉ ๋ชจ๋์์๋ TypeError๋ฅผ ๋ฐ์์ํค๊ณ ๊ฐ์ ๋ณ๊ฒฝ๋์ง ์์์.
๊ฒฝ๊ณ
as const๋ ํ์ ์์คํ ๋ด์์ ๋ถ๋ณ์ฑ์ ๋ณด์ฅํ์ง๋ง, ์ค์ JavaScript ๋ฐํ์์์๋Object.freeze()์ ๊ฐ์ ๋ช ์์ ์ธ ์กฐ์น๋ฅผ ์ทจํด์ผ๋ง ๊ฐ์ฒด์ ๋ถ๋ณ์ฑ์ ํ์คํ ๋ณด์ฅํ ์ ์์ด์. TypeScript์ ์ญํ ์ ๊ฐ๋ฐ์์ ์ค์๋ฅผ ์ปดํ์ผ ์์ ์ ์ก์์ฃผ๋ ๊ฒ์ด๋ผ๋ ์ ์ ๊ธฐ์ตํด ์ฃผ์ธ์.
1๏ธโฃ ๊ณผ๋ํ ์ฌ์ฉ์ ์ง์ํด์
as const๋ ๊ฐ๋ ฅํ์ง๋ง, ๋ชจ๋ ๋ณ์์ ๋ฌด๋ถ๋ณํ๊ฒ ์ ์ฉํ๋ ๊ฒ์ ์ข์ง ์์์. ํนํ ๋ณ๊ฒฝ๋ ๊ฐ๋ฅ์ฑ์ด ์๋ ๋ณ์์ ์ฌ์ฉํ๋ฉด ์คํ๋ ค ์ฝ๋๋ฅผ ์ ์ฐํ์ง ๋ชปํ๊ฒ ๋ง๋ค ์ ์์ด์.
์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ์
๋ ฅ ๊ฐ์ ์ ์ฅํ๋ ๋ณ์๋, ๋์ ์ผ๋ก ๋ณ๊ฒฝ๋ ์ ์๋ ์ํ ๊ฐ์๋ as const๋ฅผ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ์ข์์. as const๋ ์ฃผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ์์, ์ค์ ๊ฐ, ๋๋ ๋ถ๋ณ์ฑ์ด ๋ณด์ฅ๋์ด์ผ ํ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ํจ๊ณผ์ ์ด๋๋๋ค.
๐ ์ ๋ฆฌํ๋ฉฐ
์ค๋์ TypeScript์ as const ๊ตฌ๋ฌธ์ ๋ํด ์ฌ์ธต์ ์ผ๋ก ์์๋ณด์์ด์. as const๋ ๋จ์ํ ํ์
์คํฌ๋ฆฝํธ์ ๊ธฐ๋ฅ์ ๋์ด, ์ฝ๋์ ์๋๋ฅผ ๋ช
ํํ๊ฒ ํ๊ณ ์ ์ฌ์ ์ธ ๋ฒ๊ทธ๋ฅผ ์ค์ด๋ ๋ฐ ํฐ ๋์์ ์ฃผ๋ ๊ฐ๋ ฅํ ๋๊ตฌ์์.
0๏ธโฃ as const๋ก ์ป๋ ์ด์ ๋ค
- ์ ํํ ๋ฆฌํฐ๋ด ํ์
์ถ๋ก :
"PENDING"๊ณผ ๊ฐ์ ๋ฌธ์์ด ๋ฆฌํฐ๋ด์string์ด ์๋"PENDING"์์ฒด๋ก ์ถ๋ก ํ๊ฒ ํ์ฌ ํ์ ์์ ์ฑ์ ๋์ฌ์. - ์ฌ๊ท์ ๋ถ๋ณ์ฑ ๋ถ์ฌ: ๊ฐ์ฒด๋ ๋ฐฐ์ด ๋ด๋ถ์ ๋ชจ๋ ์์ฑ๊ณผ ์์์
readonly์์ฑ์ ๋ถ์ฌํ์ฌ ์์์น ๋ชปํ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ๋ฐฉ์งํด์. - ์ฝ๋ ๊ฐ๋
์ฑ ๋ฐ ์ ์ง๋ณด์์ฑ ํฅ์: ๋ถ๋ณ์ฑ์ด ๋ช
ํํด์ง๋ฏ๋ก ์ฝ๋๋ฅผ ์ดํดํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ฌ์์ ธ์.
- ์ปดํ์ผ ์์ ์ค๋ฅ ๊ฐ์ง: ๋ฐํ์์ ๋ฐ์ํ ์ ์๋ ์ค๋ฅ๋ฅผ ๋ฏธ๋ฆฌ ์ก์๋ด์ด ๊ฐ๋ฐ ์๊ฐ์ ๋จ์ถ์์ผ ์ค๋ต๋๋ค.
1๏ธโฃ ๋ค์ ๋จ๊ณ๋ก ๋์๊ฐ๊ธฐ
as const๋ TypeScript๋ฅผ ์ข ๋ ๊น์ด ์๊ฒ ํ์ฉํ๊ณ ์ถ์ ์ด์ค๊ธ ๊ฐ๋ฐ์๋ถ๋ค๊ป ๊ผญ ํ์ํ ์ง์์ด๋ผ๊ณ ์๊ฐํด์. ์ค๋ ๋ฐฐ์ด ๋ด์ฉ์ ๋ฐํ์ผ๋ก ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์ as const๋ฅผ ์ ์ฉํด ๋ณด๋ฉด์, ํ์
์คํฌ๋ฆฝํธ์ ๊ฐ๋ ฅํจ์ ์ง์ ๊ฒฝํํด ๋ณด์๊ธธ ๋ฐ๋ผ์.
๋ ๋์๊ฐ, as const์ ํจ๊ป type๊ณผ interface๋ฅผ ํ์ฉํ์ฌ ๋ณต์กํ ํ์
์ ์ ์ํ๊ณ , ์ ๋ค๋ฆญ๊ณผ ์กฐํฉํ์ฌ ๋์ฑ ์ ์ฐํ๊ณ ํ์
์์ ํ ์ฝ๋๋ฅผ ์์ฑํด ๋ณด๋ ์ฐ์ต๋ ํด๋ณด์๋ฉด ์ข์ ๊ฒ ๊ฐ์์.
๊ถ๊ธํ ์ ์ด ์๋ค๋ฉด ์ธ์ ๋ ์ง ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์ธ์. ๋ค์ ํฌ์คํ ์์ ๋ ์ ์ตํ ์ ๋ณด๋ก ์ฐพ์๋ต๊ฒ ์ต๋๋ค!
๐ฎ ์ฐธ๊ณ
- TypeScript Handbook:
as constassertions - TypeScript Deep Dive:
as constassertions - You Don't Know JS Yet: Get Started -
Object.freeze()
์ฐ๊ด๋ ํฌ์คํธ
- ๋จ์ด: 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๋ฅผ ํ์ฉํ ๋ฉํ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฒ์ ์ฌ์ธต ๋ถ์ํด์. ๊ฐ์ฒด ์ ๊ทผ ์ ์ด, ์ ํจ์ฑ ๊ฒ์ฌ, ๋ก๊น , ๋ฐ์ํ ์์คํ ๊ตฌํ ๋ฑ ์ค์ฉ์ ์ธ ํ์ฉ ์ฌ๋ก๋ฅผ ํตํด ์ฝ๋์ ์ ์ฐ์ฑ๊ณผ ์์ ์ฑ์ ๋์ด๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.
- ๋จ์ด: 2,029๊ฐ24๋ถ
[๐ค] React/Next.js ๋ฒ๋ค ์ต์ ํ: ์ฝ๋ ์คํ๋ฆฌํ ๊ณผ ๋ ์ด์ง ๋ก๋ฉ ์๋ฒฝ ๊ฐ์ด๋
React์ Next.js ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ๋ก๋ฉ ์๋๋ฅผ ๊ฐ์ ํ๋ ์ฝ๋ ์คํ๋ฆฌํ ๊ณผ ๋ ์ด์ง ๋ก๋ฉ ๊ธฐ๋ฒ์ ์ค์ฉ์ ์ธ ์์์ ํจ๊ป ์์ธํ ์์๋ด์. ์นํฉ ์ค์ ๋ถํฐ React.lazy, Next.js dynamic import๊น์ง ๋ค๋ค์.
- ๋จ์ด: 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๋ฅผ ์ด์ฉํ ๋ฐ์ดํฐ ์ฌ๊ฒ์ฆ ๋ฐฉ๋ฒ์ ์ค๋ฌด ์์์ ํจ๊ป ์์ธํ ์์๋ณด๊ณ ์น ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.