[๐Ÿค–] TypeScript satisfies ์—ฐ์‚ฐ์ž: ํƒ€์ž… ์ถ”๋ก ๊ณผ ์•ˆ์ •์„ฑ์„ ๋™์‹œ์— ์žก๋Š” ๋น„๋ฒ•

TypeScript์˜ `satisfies` ์—ฐ์‚ฐ์ž๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํƒ€์ž… ์ถ”๋ก ์˜ ์œ ์—ฐ์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ์—„๊ฒฉํ•œ ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ํ™•๋ณดํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์„ธ์š”. ์‹ค์šฉ์ ์ธ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋Š” ๋…ธํ•˜์šฐ๋ฅผ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

21๋ถ„
๋‹จ์–ด: 1,878๊ฐœ
๊ฒŒ์‹œ๊ธ€ ์ธ๋„ค์ผ
์ •๋ณด

๐Ÿค– ์ด ํฌ์ŠคํŒ…์€ Gemini 2.5 Flash AI๊ฐ€ ์ž‘์„ฑํ–ˆ์–ด์š”.
๋‚ด์šฉ์˜ ์ •ํ™•์„ฑ์„ ์œ„ํ•ด ๊ฒ€ํ† ๋ฅผ ๊ฑฐ์ณค์ง€๋งŒ, ์‹ค๋ฌด ์ ์šฉ ์ „ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ•จ๊ป˜ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.

์œ ์šฉํ•œ ํŒ

TypeScript์˜ satisfies ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํƒ€์ž… ์ถ”๋ก ์˜ ์œ ์—ฐ์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ์—„๊ฒฉํ•œ ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ํ™•๋ณดํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‹ค์šฉ์ ์ธ ์˜ˆ์‹œ์™€ ํ•จ๊ป˜ ๋ฐฐ์›Œ๋ด…๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š”! 10๋…„ ์ด์ƒ ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ๋ฅผ ๋„˜๋‚˜๋“ค๋ฉฐ ๊ฐœ๋ฐœํ•ด ์˜จ ์‹œ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž์ž…๋‹ˆ๋‹ค.
์˜ค๋Š˜์€ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋ถ„๋“ค์ด TypeScript๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ํ•œ ๋ฒˆ์ฏค์€ ๊ณ ๋ฏผํ•ด ๋ดค์„ ๋ฒ•ํ•œ ๋ฌธ์ œ, ๋ฐ”๋กœ "ํƒ€์ž… ์ถ”๋ก ์˜ ์œ ์—ฐ์„ฑ๊ณผ ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ๋™์‹œ์— ์žก๋Š” ๋ฐฉ๋ฒ•"์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด ๋ณด๋ ค๊ณ  ํ•ด์š”.
ํŠนํžˆ TypeScript 4.9๋ถ€ํ„ฐ ๋„์ž…๋œ satisfies ์—ฐ์‚ฐ์ž๊ฐ€ ์ด ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ์šฐ์•„ํ•˜๊ฒŒ ํ•ด๊ฒฐํ•ด ์ฃผ๋Š”์ง€ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

0๏ธโƒฃ ํƒ€์ž… ์ถ”๋ก ์˜ ์œ ์—ฐ์„ฑ๊ณผ ํƒ€์ž… ์•ˆ์ •์„ฑ ์‚ฌ์ด์˜ ๋”œ๋ ˆ๋งˆ

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

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ณด์‹œ๊ฒ ์–ด์š”?

type Colors = "red" | "green" | "blue"; interface Palette { primary: Colors; secondary: Colors; } // ๋ฌธ์ œ ์ƒํ™ฉ: Palette ํƒ€์ž…์„ ๋ช…์‹œํ•˜๋ฉด, 'red'๋Š” string์ด ์•„๋‹ˆ๋ผ 'red' ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์ด์–ด์•ผ ํ•˜๋Š”๋ฐ... const myPalette: Palette = { primary: "red", secondary: "green", tertiary: "yellow" // Error: Object literal may only specify known properties }; // myPalette.primary๋Š” 'red' ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์ด ์•„๋‹ˆ๋ผ Colors ํƒ€์ž…์ด ๋˜์–ด๋ฒ„๋ ค์š”. const primaryColor = myPalette.primary; // type: Colors ('red' | 'green' | 'blue') // ๋งŒ์•ฝ 'red' ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด? // const specificColor: "red" = primaryColor; // Error: Type 'Colors' is not assignable to type '"red"'.

์œ„ ์˜ˆ์‹œ์—์„œ myPalette์— Palette ํƒ€์ž…์„ ๋ช…์‹œํ•˜๋ฉด, tertiary ๊ฐ™์€ ์ถ”๊ฐ€ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๋˜ํ•œ, myPalette.primary๋Š” "red"๋ผ๋Š” ๊ตฌ์ฒด์ ์ธ ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์ด ์•„๋‹Œ Colors ์œ ๋‹ˆ์˜จ ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋˜์–ด, ๋‚˜์ค‘์— "red" ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์ด ํ•„์š”ํ•œ ๊ณณ์— ์ง์ ‘ ํ• ๋‹นํ•˜๊ธฐ ์–ด๋ ค์›Œ์ ธ์š”.
์ด๋Š” ํƒ€์ž… ์ถ”๋ก ์˜ ์œ ์—ฐ์„ฑ์„ ์žƒ๊ฒŒ ๋งŒ๋“œ๋Š” ๋Œ€ํ‘œ์ ์ธ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

1๏ธโƒฃ as ํ‚ค์›Œ๋“œ์˜ ํ•œ๊ณ„์™€ ๋ฌธ์ œ์ 

์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋ถ„๋“ค์ด as ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์…จ์„ ๊ฑฐ์˜ˆ์š”.
as ํ‚ค์›Œ๋“œ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ "๋‚ด๊ฐ€ ๋” ์ž˜ ์•„๋‹ˆ, ์ด ํƒ€์ž…์„ ๋ฏฟ์–ด์ค˜"๋ผ๊ณ  ์ง€์‹œํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

type Colors = "red" | "green" | "blue"; interface Palette { primary: Colors; secondary: Colors; } // 'as' ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ ์˜ˆ์‹œ const myPaletteWithAs = { primary: "red", secondary: "green", tertiary: "yellow" // ์ด ๋ถ€๋ถ„์€ ์—๋Ÿฌ๊ฐ€ ๋‚˜์ง€ ์•Š์•„์š” (as Palette๊ฐ€ ์ „์ฒด๋ฅผ ๋ฎ์–ด์”Œ์›€) } as Palette; // ํ•˜์ง€๋งŒ 'tertiary'๋Š” Palette ํƒ€์ž…์— ์—†์œผ๋ฏ€๋กœ ์ ‘๊ทผ ์‹œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด์š”. // console.log(myPaletteWithAs.tertiary); // Error: Property 'tertiary' does not exist on type 'Palette'. // ๋˜ํ•œ, myPaletteWithAs.primary๋Š” ์—ฌ์ „ํžˆ Colors ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค. const primaryColorFromAs = myPaletteWithAs.primary; // type: Colors

as ํ‚ค์›Œ๋“œ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
์ฒซ์งธ, ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์— ์—†๋Š” ํ”„๋กœํผํ‹ฐ๋ฅผ ์ถ”๊ฐ€ํ•ด๋„ ์ปดํŒŒ์ผ ์‹œ์ ์— ์˜ค๋ฅ˜๋ฅผ ์žก์•„์ฃผ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.
as Palette๊ฐ€ ๊ฐ์ฒด ์ „์ฒด์— ์ ์šฉ๋˜๋ฉด์„œ tertiary ํ”„๋กœํผํ‹ฐ์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด์ฃ .
๋‘˜์งธ, ์—ฌ์ „ํžˆ ๊ฐœ๋ณ„ ํ”„๋กœํผํ‹ฐ์˜ ๊ตฌ์ฒด์ ์ธ ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž… ์ •๋ณด๋ฅผ ์žƒ์–ด๋ฒ„๋ฆฌ๊ณ , ๋ช…์‹œ๋œ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ ๋‹ˆ์˜จ ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค.
๊ฒฐ๊ณผ์ ์œผ๋กœ as๋Š” ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ์•ฝํ™”์‹œํ‚ค๊ฑฐ๋‚˜, ์›ํ•˜๋Š” ํƒ€์ž… ์ถ”๋ก ์„ ๋ฐฉํ•ดํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„์š”.

0๏ธโƒฃ satisfies ์—ฐ์‚ฐ์ž๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

TypeScript 4.9๋ถ€ํ„ฐ ๋„์ž…๋œ satisfies ์—ฐ์‚ฐ์ž๋Š” ์ด๋Ÿฌํ•œ ๋”œ๋ ˆ๋งˆ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํƒ„์ƒํ–ˆ์–ด์š”.
satisfies๋Š” "์ด ํ‘œํ˜„์‹์ด ํŠน์ • ํƒ€์ž…์˜ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋˜, ๊ทธ ํ‘œํ˜„์‹์˜ ์›๋ž˜ ์ถ”๋ก ๋œ ํƒ€์ž…์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•ด ์ค˜"๋ผ๊ณ  TypeScript ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค.
์ฆ‰, ํƒ€์ž… ๊ฒ€์‚ฌ๋Š” ์ˆ˜ํ–‰ํ•˜์ง€๋งŒ, ํƒ€์ž… ์ถ”๋ก ์€ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด์ฃ .

์ด๊ฒƒ์€ as ํ‚ค์›Œ๋“œ์™€๋Š” ๋งค์šฐ ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์ด์—์š”.
as๋Š” ๊ฐ•์ œ๋กœ ํƒ€์ž…์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐ˜๋ฉด, satisfies๋Š” ํƒ€์ž…์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๋‹จ์ง€ "ํ™•์ธ"๋งŒ ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

1๏ธโƒฃ as์™€ satisfies์˜ ๊ฒฐ์ •์ ์ธ ์ฐจ์ด

as์™€ satisfies์˜ ์ฐจ์ด๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด์š”.

์ •๋ณด

as Type: "์ด ๊ฐ’์„ Type์œผ๋กœ ๊ฐ„์ฃผํ•ด ์ค˜. ๋‚ด๊ฐ€ Type์ด๋ผ๋Š” ๊ฒƒ์„ ๋ณด์žฅํ• ๊ฒŒ."


-> ํƒ€์ž…์„ ๊ฐ•์ œ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ , ์›๋ž˜์˜ ์„ธ๋ถ€ ํƒ€์ž… ์ •๋ณด๋ฅผ ์žƒ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์–ด์š”.

์œ ์šฉํ•œ ํŒ

satisfies Type: "์ด ๊ฐ’์ด Type์˜ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ํ™•์ธํ•ด ์ค˜. ํ•˜์ง€๋งŒ ์ด ๊ฐ’์˜ ํƒ€์ž…์€ ์›๋ž˜ ์ถ”๋ก ๋œ ํƒ€์ž… ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•ด ์ค˜."


-> ํƒ€์ž… ๊ฒ€์‚ฌ๋งŒ ์ˆ˜ํ–‰ํ•˜๊ณ , ์›๋ž˜์˜ ์„ธ๋ถ€ ํƒ€์ž… ์ •๋ณด๋ฅผ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ๋†’์ด๋ฉด์„œ๋„ ์œ ์—ฐํ•œ ํƒ€์ž… ์ถ”๋ก ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ satisfies๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์œ„์—์„œ ๋ฐœ์ƒํ–ˆ๋˜ ๋ฌธ์ œ๋“ค์ด ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐ๋˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

type Colors = "red" | "green" | "blue"; interface Palette { primary: Colors; secondary: Colors; } // satisfies ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ ์˜ˆ์‹œ const myPaletteSatisfies = { primary: "red", secondary: "green", // tertiary: "yellow" // Error: Object literal may only specify known properties. // -> satisfies๋Š” Palette ์ธํ„ฐํŽ˜์ด์Šค์— ์—†๋Š” ํ”„๋กœํผํ‹ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ์š”! } satisfies Palette; // myPaletteSatisfies.primary๋Š” 'red' ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค! const primaryColorFromSatisfies = myPaletteSatisfies.primary; // type: "red" // ์ด์ œ 'red' ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์ด ํ•„์š”ํ•œ ๊ณณ์— ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. const specificColor: "red" = primaryColorFromSatisfies; // No Error! // ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์˜ ๋‹ค๋ฅธ ํ”„๋กœํผํ‹ฐ๋„ ์›๋ž˜์˜ ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค. const secondaryColorFromSatisfies = myPaletteSatisfies.secondary; // type: "green"

๋ณด์‹œ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ satisfies๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Palette ์ธํ„ฐํŽ˜์ด์Šค์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๋ฉด์„œ๋„, primary๊ฐ€ "red" ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ, secondary๊ฐ€ "green" ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์ •ํ™•ํ•˜๊ฒŒ ์ถ”๋ก ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๊ฒƒ์ด ๋ฐ”๋กœ satisfies ์—ฐ์‚ฐ์ž์˜ ํ•ต์‹ฌ์ ์ธ ๊ฐ•์ ์ด์—์š”!

satisfies ์—ฐ์‚ฐ์ž๋Š” ๋‹ค์–‘ํ•œ ์‹ค์ „ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ๋งค์šฐ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉ๋  ์ˆ˜ ์žˆ์–ด์š”.
๋ช‡ ๊ฐ€์ง€ ์‹ค์ œ ๊ฐœ๋ฐœ์—์„œ ๋งˆ์ฃผํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ๊ทธ ๊ฐ•๋ ฅํ•จ์„ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

0๏ธโƒฃ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์—์„œ ์„ธ๋ถ€ ํ”„๋กœํผํ‹ฐ ํƒ€์ž… ์œ ์ง€ํ•˜๊ธฐ

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

type LogLevel = "info" | "warn" | "error" | "debug"; interface LoggerConfig { level: LogLevel; format: string; } // ๊ฐ ํ™˜๊ฒฝ๋ณ„ ์„ค์ •์„ ์ •์˜ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค. const appConfigs = { development: { level: "debug", format: "[%level%] %message%", }, production: { level: "info", format: "[%level%] %timestamp% %message%", // maxFileSize: 1024 // Error: Object literal may only specify known properties. // -> LoggerConfig์— ์—†๋Š” ์†์„ฑ์€ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. }, test: { level: "error", format: "[%level%] %message%", }, } satisfies Record<string, LoggerConfig>; // Record<string, LoggerConfig>๋ฅผ ๋งŒ์กฑํ•˜๋Š”์ง€ ํ™•์ธ! // ์ด์ œ appConfigs.development.level์€ "debug" ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค. const devLogLevel = appConfigs.development.level; // type: "debug" // ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์˜ ํฌ๋งท์„ ๊ฐ€์ ธ์™€๋„ string ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์ด ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. const prodFormat = appConfigs.production.format; // type: "[%level%] %timestamp% %message%" // ๋”ฐ๋ผ์„œ ์˜คํƒ€ ๋ฐฉ์ง€ ๋ฐ ์ž๋™ ์™„์„ฑ์—๋„ ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. if (devLogLevel === "debug") { console.log("๋””๋ฒ„๊ทธ ๋ชจ๋“œ์ž…๋‹ˆ๋‹ค."); } // ๋งŒ์•ฝ satisfies๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด devLogLevel์€ LogLevel ํƒ€์ž…์ด ๋˜์—ˆ์„ ๊ฑฐ์˜ˆ์š”. // const devLogLevelWithoutSatisfies: LogLevel = appConfigs.development.level; // type: LogLevel

Record<string, LoggerConfig>๋ฅผ satisfies ํ•˜๋ฉด, appConfigs ๊ฐ์ฒด ์ „์ฒด๊ฐ€ LoggerConfig์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค.
๋™์‹œ์— appConfigs.development.level๊ณผ ๊ฐ™์€ ๊ฐœ๋ณ„ ํ”„๋กœํผํ‹ฐ๋Š” 'debug'์™€ ๊ฐ™์€ ๊ตฌ์ฒด์ ์ธ ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋˜์–ด IntelliSense์™€ ํƒ€์ž… ์•ˆ์ •์„ฑ ๋ชจ๋‘๋ฅผ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์–ด์š”.

1๏ธโƒฃ CSS ์†์„ฑ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๋ฐ ์ž๋™ ์™„์„ฑ ํ™œ์šฉ

CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ์Šคํƒ€์ผ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃฐ ๋•Œ satisfies ์—ฐ์‚ฐ์ž๋Š” ๋น›์„ ๋ฐœํ•ฉ๋‹ˆ๋‹ค.
ํŠน์ • CSS ์†์„ฑ ์ง‘ํ•ฉ์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ฉด์„œ๋„, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ •์˜ํ•œ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•ด์š”.

import React from 'react'; type CSSProperties = React.CSSProperties; // ์œ ํšจํ•œ ์ƒ‰์ƒ ์ฝ”๋“œ๋งŒ ํ—ˆ์šฉํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž… (์˜ˆ์‹œ) type HexColor = `#${string}`; type ValidColor = HexColor | "currentColor" | "transparent" | "inherit"; interface MyComponentStyle { container: CSSProperties & { backgroundColor?: ValidColor }; button: CSSProperties & { color?: ValidColor }; } const styles = { container: { display: "flex", padding: "16px", backgroundColor: "#f0f0f0", // HexColor๋ฅผ ๋งŒ์กฑํ•˜๋Š”์ง€ ๊ฒ€์‚ฌ // invalidColor: "not-a-color" // Error: Object literal may only specify known properties }, button: { color: "currentColor", fontSize: "16px", fontWeight: "bold", // hoverColor: "#123" // Error: Object literal may only specify known properties }, } satisfies MyComponentStyle; // styles.container.backgroundColor๋Š” "#f0f0f0" ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค. const containerBg = styles.container.backgroundColor; // type: "#f0f0f0" // ์ด๋ฅผ ํ†ตํ•ด ์ •ํ™•ํ•œ ํƒ€์ž… ์ •๋ณด๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. const specificBg: "#f0f0f0" = containerBg; // No Error! // ๋งŒ์•ฝ ์˜คํƒ€๊ฐ€ ์žˆ๋‹ค๋ฉด ์ฆ‰์‹œ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ์š”. // styles.container.backgroundColour; // Error: Property 'backgroundColour' does not exist on type '{ display: string; padding: string; backgroundColor: "#f0f0f0"; }'.

styles ๊ฐ์ฒด๊ฐ€ MyComponentStyle์„ satisfies ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•จ์œผ๋กœ์จ, ์ž˜๋ชป๋œ CSS ์†์„ฑ์ด๋‚˜ ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒ‰์ƒ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋™์‹œ์— backgroundColor์™€ ๊ฐ™์€ ์†์„ฑ๋“ค์€ "#f0f0f0"์™€ ๊ฐ™์€ ๊ตฌ์ฒด์ ์ธ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋˜์–ด, ๋‚˜์ค‘์— ์ด ๊ฐ’์„ ํ™œ์šฉํ•  ๋•Œ ๋” ์ •ํ™•ํ•œ ํƒ€์ž… ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์–ด์š”.

2๏ธโƒฃ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋˜๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ํƒ€์ž… ์•ˆ์ „ํ•˜๊ฒŒ ์ •์˜ํ•˜๊ธฐ

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

type EventName = "click" | "hover" | "focus"; interface EventHandler { (event: { type: EventName; target: HTMLElement }): void; } const eventHandlers = { handleClick: (event) => { // event.type์€ "click" ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค! if (event.type === "click") { console.log("ํด๋ฆญ ์ด๋ฒคํŠธ ๋ฐœ์ƒ:", event.target); } }, handleHover: (event) => { // event.type์€ "hover" ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค! console.log("ํ˜ธ๋ฒ„ ์ด๋ฒคํŠธ ๋ฐœ์ƒ:", event.target.tagName); // event.target.focus(); // Error: Property 'focus' does not exist on type 'HTMLElement'. // -> HTMLElement์— focus๊ฐ€ ์—†์œผ๋ฉด ์—๋Ÿฌ ๋ฐœ์ƒ (ํƒ€์ž… ์•ˆ์ •์„ฑ ๋ณด์žฅ) }, } satisfies Record<string, EventHandler>; // eventHandlers.handleClick์˜ event ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์€ { type: "click"; target: HTMLElement }๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค. // ์ด๋Š” Record<string, EventHandler>์˜ ์ œ์•ฝ์„ ๋งŒ์กฑํ•˜๋ฉด์„œ๋„, ๊ฐ ํ•ธ๋“ค๋Ÿฌ์˜ ๊ตฌ์ฒด์ ์ธ ํƒ€์ž… ์ •๋ณด๋ฅผ ์œ ์ง€ํ•˜๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. // ์ด ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋„ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๋ˆ„๋ฆด ์ˆ˜ ์žˆ์–ด์š”. const myButton = document.createElement('button'); myButton.addEventListener('click', (e) => { eventHandlers.handleClick({ type: "click", target: e.currentTarget as HTMLElement }); });

์—ฌ๊ธฐ์„œ eventHandlers ๊ฐ์ฒด๊ฐ€ Record<string, EventHandler>๋ฅผ satisfies ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•จ์œผ๋กœ์จ, ๋ชจ๋“  ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๊ฐ€ EventHandler ์ธํ„ฐํŽ˜์ด์Šค์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
๋™์‹œ์— handleClick ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ event.type์€ "click" ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ, handleHover ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ event.type์€ "hover" ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์ •ํ™•ํ•˜๊ฒŒ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค.
์ด๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ๊ฐ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ๋กœ์ง์„ ์ž‘์„ฑํ•  ๋•Œ ๋” ๊ตฌ์ฒด์ ์ธ ํƒ€์ž… ์ •๋ณด๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์–ด ์ƒ์‚ฐ์„ฑ๊ณผ ์•ˆ์ •์„ฑ ๋ชจ๋‘๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ์–ด์š”.

0๏ธโƒฃ ์ฃผ์š” ์žฅ์ 

satisfies ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์žฅ์ ๋“ค์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํƒ€์ž… ์•ˆ์ •์„ฑ ํ™•๋ณด: ํŠน์ • ํƒ€์ž…์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ์ปดํŒŒ์ผ ์‹œ์ ์— ๊ฒ€์‚ฌํ•˜์—ฌ ์ž ์žฌ์ ์ธ ์˜ค๋ฅ˜๋ฅผ ๋ฐฉ์ง€ํ•ด์š”.
    ์˜ˆ๋ฅผ ๋“ค์–ด, Palette ์˜ˆ์‹œ์—์„œ tertiary ๊ฐ™์€ ๋ถˆํ•„์š”ํ•œ ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€๋ฅผ ๋ง‰์•„์ค๋‹ˆ๋‹ค.
  • ํƒ€์ž… ์ถ”๋ก  ์œ ์—ฐ์„ฑ ์œ ์ง€: ๊ฐ’์˜ ์›๋ž˜ ์ถ”๋ก ๋œ ํƒ€์ž…์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜์—ฌ, ๋” ๊ตฌ์ฒด์ ์ธ ํƒ€์ž… ์ •๋ณด๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
    "red"์™€ ๊ฐ™์€ ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์„ ์žƒ์ง€ ์•Š์•„ IntelliSense์™€ ์ฝ”๋“œ์˜ ์ •ํ™•์„ฑ์„ ๋†’์—ฌ์ค๋‹ˆ๋‹ค.
  • ๋ถˆํ•„์š”ํ•œ ํƒ€์ž… ๋‹จ์–ธ(as) ๊ฐ์†Œ: as ํ‚ค์›Œ๋“œ๋ฅผ ๋‚จ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์–ด ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ด๊ณ , as๋กœ ์ธํ•œ ์ž ์žฌ์ ์ธ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜๋ฅผ ์ค„์—ฌ์ค๋‹ˆ๋‹ค.
  • ์ž๋™ ์™„์„ฑ ๋ฐ ๋ฆฌํŒฉํ† ๋ง ์šฉ์ด: ๊ตฌ์ฒด์ ์ธ ํƒ€์ž… ์ •๋ณด๊ฐ€ ์œ ์ง€๋˜๋ฏ€๋กœ ๊ฐœ๋ฐœ ๋„๊ตฌ์˜ ์ž๋™ ์™„์„ฑ ๊ธฐ๋Šฅ์ด ๋”์šฑ ๊ฐ•๋ ฅํ•ด์ง€๊ณ , ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง ์‹œ์—๋„ ํƒ€์ž… ์˜ค๋ฅ˜๋ฅผ ์‰ฝ๊ฒŒ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์–ด์š”.

1๏ธโƒฃ ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•  ์ 

satisfies ์—ฐ์‚ฐ์ž๋Š” ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ์ฃผ์˜ํ•  ์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  • TypeScript 4.9 ์ด์ƒ์—์„œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ: satisfies๋Š” TypeScript 4.9 ๋ฒ„์ „๋ถ€ํ„ฐ ๋„์ž…๋œ ๊ธฐ๋Šฅ์ด๋ฏ€๋กœ, ํ”„๋กœ์ ํŠธ์˜ TypeScript ๋ฒ„์ „์„ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    ๊ตฌํ˜• ๋ฒ„์ „์—์„œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์–ด์š”.
  • ์˜ค๋ฒ„ํ—ค๋“œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ: ๋งค์šฐ ๋ณต์žกํ•œ ํƒ€์ž… ์ •์˜์™€ ๋Œ€๊ทœ๋ชจ ๊ฐ์ฒด์— satisfies๋ฅผ ๊ณผ๋„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ์•ฝ๊ฐ„ ๋Š˜์–ด๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์„ฑ๋Šฅ ์ €ํ•˜๋Š” ๋ฏธ๋ฏธํ•˜๋ฉฐ, ์–ป๋Š” ์ด์ ์ด ํ›จ์”ฌ ์ปค์š”.
  • as์˜ ๋Œ€์ฒด์žฌ๋Š” ์•„๋‹˜: satisfies๊ฐ€ as์˜ ๋งŽ์€ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, as๋Š” ์—ฌ์ „ํžˆ ํŠน์ • ์ƒํ™ฉ(์˜ˆ: ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์šฐํšŒํ•ด์•ผ ํ•˜๋Š” ๋“œ๋ฌธ ๊ฒฝ์šฐ)์—์„œ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ๊ฐ ํ‚ค์›Œ๋“œ์˜ ๋ชฉ์ ์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ  ์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด์š”.

๐Ÿ“ ์ •๋ฆฌํ•˜๋ฉฐ

0๏ธโƒฃ ํ•ต์‹ฌ ์š”์•ฝ

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

as ํ‚ค์›Œ๋“œ๊ฐ€ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์ž ์žฌ์ ์ธ ์œ„ํ—˜์„ ํšŒํ”ผํ•˜๊ณ , ๋” ์•ˆ์ „ํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ํƒ€์ž… ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ satisfies ์—ฐ์‚ฐ์ž๊ฐ€ ํฐ ๋„์›€์ด ๋  ๊ฑฐ์˜ˆ์š”.

1๏ธโƒฃ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋‚˜์•„๊ฐ€๊ธฐ

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

๐Ÿ“ฎ ์ฐธ๊ณ 

์—ฐ๊ด€๋œ ํฌ์ŠคํŠธ