๐Ÿ›ก๏ธ ํƒ€์ž… ๊ฐ€๋“œ: ๋Ÿฐํƒ€์ž„์— ํƒ€์ž… ํ™•์ธํ•˜๊ธฐ ๐Ÿ•ต๏ธโ€โ™€๏ธ

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿ›ก๏ธ ํƒ€์ž… ๊ฐ€๋“œ: ๋Ÿฐํƒ€์ž„์— ํƒ€์ž… ํ™•์ธํ•˜๊ธฐ ๐Ÿ•ต๏ธโ€โ™€๏ธ

 

 

์•ˆ๋…•, ์นœ๊ตฌ๋“ค! ์˜ค๋Š˜์€ TypeScript์˜ ๊ฟ€ํŒ ์ค‘ ํ•˜๋‚˜์ธ 'ํƒ€์ž… ๊ฐ€๋“œ'์— ๋Œ€ํ•ด ์žฌ๋ฐŒ๊ฒŒ ์–˜๊ธฐํ•ด๋ณผ ๊ฑฐ์•ผ. ํƒ€์ž… ๊ฐ€๋“œ๋ผ๋‹ˆ, ๋ญ”๊ฐ€ ๋ฉ‹์ง„ ๊ฒฝํ˜ธ์›์ด ํƒ€์ž…์„ ์ง€์ผœ์ฃผ๋Š” ๊ฒƒ ๊ฐ™์€ ๋Š๋‚Œ์ด ๋“ค์ง€ ์•Š์•„? ๐Ÿ˜Ž ์‚ฌ์‹ค ๊ทธ๋ ‡๊ฒŒ ๋ฉ€์ง€ ์•Š์€ ๊ฐœ๋…์ด์•ผ. ํƒ€์ž… ๊ฐ€๋“œ๋Š” ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ง€์ผœ์ฃผ๋Š” ๋“ ๋“ ํ•œ ์นœ๊ตฌ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์ง€.

๐Ÿ”‘ ํ•ต์‹ฌ ํฌ์ธํŠธ: ํƒ€์ž… ๊ฐ€๋“œ๋Š” ๋Ÿฐํƒ€์ž„์— ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ํ™•์ธํ•˜๊ณ , ํŠน์ • ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ ๊ทธ ํƒ€์ž…์„ ๋ณด์žฅํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด์•ผ.

์ž, ์ด์ œ๋ถ€ํ„ฐ ํƒ€์ž… ๊ฐ€๋“œ์˜ ์„ธ๊ณ„๋กœ ๋น ์ ธ๋ณผ๊นŒ? ์šฐ๋ฆฌ์˜ ์—ฌ์ •์€ ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ํƒํ—˜ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ํฅ๋ฏธ์ง„์ง„ํ•  ๊ฑฐ์•ผ. ๊ทธ๋Ÿผ ์ถœ๋ฐœ~! ๐Ÿš€

๐Ÿค” ํƒ€์ž… ๊ฐ€๋“œ๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 

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

๐Ÿ˜… ๋ฌธ์ œ ์ƒํ™ฉ: ๋ฌธ์ž์—ด์ด๋‚˜ ์ˆซ์ž๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ด. ๋ฌธ์ž์—ด์ด๋ฉด ๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ์ˆซ์ž๋ฉด ์ œ๊ณฑ์„ ํ•ด์•ผ ํ•œ๋‹ค๋ฉด?

์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ ํƒ€์ž… ๊ฐ€๋“œ ์—†์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์ด๋ ‡๊ฒŒ ๋  ๊ฑฐ์•ผ:


function processValue(value: string | number) {
  // ์—๋Ÿฌ! 'value'๊ฐ€ 'string'์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์•„
  // value.toUpperCase();

  // ์—๋Ÿฌ! 'value'๊ฐ€ 'number'์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์•„
  // value * value;
}
  

์Œ... ์ด๊ฑด ์ข€ ๊ณค๋ž€ํ•˜๋„ค. TypeScript ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ "์•ผ, ๊ทธ๊ฑฐ ์•ˆ์ „ํ•˜์ง€ ์•Š์•„!"๋ผ๊ณ  ์†Œ๋ฆฌ์น˜๋Š” ๊ฑธ ๋“ค์„ ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ. ๐Ÿ˜…

์ด๋Ÿด ๋•Œ ํƒ€์ž… ๊ฐ€๋“œ๊ฐ€ ์šฐ๋ฆฌ์˜ ๊ตฌ์›์ž๋กœ ๋“ฑ์žฅํ•˜๋Š” ๊ฑฐ์ง€! ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์–ด. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ํ•„์š”ํ•œ ์žฌ๋Šฅ์„ ์ •ํ™•ํžˆ ์ฐพ์•„๋‚ด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์•ผ. ๐Ÿ‘

๐Ÿ’ก ํƒ€์ž… ๊ฐ€๋“œ์˜ ์—ญํ• : ๋Ÿฐํƒ€์ž„์— ํƒ€์ž…์„ ํ™•์ธํ•˜๊ณ , TypeScript์—๊ฒŒ "์ด ๋ธ”๋ก ์•ˆ์—์„œ๋Š” ์ด ๋ณ€์ˆ˜๊ฐ€ ํ™•์‹คํžˆ ์ด ํƒ€์ž…์ด์•ผ!"๋ผ๊ณ  ์•Œ๋ ค์ฃผ๋Š” ๊ฑฐ์•ผ.

์ž, ์ด์ œ ํƒ€์ž… ๊ฐ€๋“œ์˜ ํ•„์š”์„ฑ์„ ์•Œ์•˜์œผ๋‹ˆ, ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ? ์ค€๋น„๋์–ด? ๋‹ค์Œ ์„น์…˜์—์„œ ๊ณ„์†! ๐Ÿƒโ€โ™‚๏ธ๐Ÿ’จ

๐Ÿ› ๏ธ ํƒ€์ž… ๊ฐ€๋“œ์˜ ์ข…๋ฅ˜

ํƒ€์ž… ๊ฐ€๋“œ์—๋Š” ์—ฌ๋Ÿฌ ์ข…๋ฅ˜๊ฐ€ ์žˆ์–ด. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ๋งŒ๋‚  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ํƒ€์ž… ๊ฐ€๋“œ๋„ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€. ์ž, ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณผ๊นŒ?

1. typeof ํƒ€์ž… ๊ฐ€๋“œ ๐Ÿ”

typeof ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•œ ํƒ€์ž… ๊ฐ€๋“œ์•ผ. ๊ธฐ๋ณธ ํƒ€์ž…์„ ์ฒดํฌํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•ด.


function processValue(value: string | number) {
  if (typeof value === "string") {
    // ์—ฌ๊ธฐ์„œ๋Š” value๊ฐ€ ํ™•์‹คํžˆ string ํƒ€์ž…์ด์•ผ
    return value.toUpperCase();
  } else {
    // ์—ฌ๊ธฐ์„œ๋Š” value๊ฐ€ ํ™•์‹คํžˆ number ํƒ€์ž…์ด์•ผ
    return value * value;
  }
}
  

์™€! ์ด์ œ ์—๋Ÿฌ ์—†์ด ๊น”๋”ํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์–ด. typeof๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด TypeScript๋Š” ๊ฐ ๋ธ”๋ก ์•ˆ์—์„œ value์˜ ํƒ€์ž…์„ ์ •ํ™•ํžˆ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ๋ผ. coolํ•˜์ง€? ๐Ÿ˜Ž

2. instanceof ํƒ€์ž… ๊ฐ€๋“œ ๐Ÿญ

instanceof ์—ฐ์‚ฐ์ž๋Š” ๊ฐ์ฒด๊ฐ€ ํŠน์ • ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ธ์ง€ ํ™•์ธํ•  ๋•Œ ์‚ฌ์šฉํ•ด.


class Cat {
  meow() {
    console.log("์•ผ์˜น~");
  }
}

class Dog {
  bark() {
    console.log("๋ฉ๋ฉ!");
  }
}

function makeSound(animal: Cat | Dog) {
  if (animal instanceof Cat) {
    animal.meow();  // OK!
  } else {
    animal.bark();  // OK!
  }
}
  

instanceof๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ์ •ํ™•ํžˆ ์•Œ ์ˆ˜ ์žˆ์–ด. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ ๋™๋ฌผ์ด ์ œ๋Œ€๋กœ ๋œ ์†Œ๋ฆฌ๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฑฐ์ง€. ๐Ÿฑ๐Ÿถ

3. in ์—ฐ์‚ฐ์ž ํƒ€์ž… ๊ฐ€๋“œ ๐Ÿ”‘

in ์—ฐ์‚ฐ์ž๋Š” ๊ฐ์ฒด์— ํŠน์ • ํ”„๋กœํผํ‹ฐ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•  ๋•Œ ์‚ฌ์šฉํ•ด.


interface Bird {
  fly(): void;
}

interface Fish {
  swim(): void;
}

function move(pet: Bird | Fish) {
  if ("fly" in pet) {
    pet.fly();  // OK!
  } else {
    pet.swim();  // OK!
  }
}
  

in ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด๊ฐ€ ํŠน์ • ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด. ์ด๋ฅผ ํ†ตํ•ด ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๋Š” ๋”์šฑ ์•ˆ์ „ํ•˜๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•ด์ง€์ง€. ๐Ÿ‘

๐ŸŒŸ ํŒ: ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ์•ˆ์ •์„ฑ์ด ๋†’์•„์ ธ. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๊ฒ€์ฆ๋œ ์ „๋ฌธ๊ฐ€์˜ ์žฌ๋Šฅ์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ํƒ€์ž… ๊ฐ€๋“œ๋Š” ์šฐ๋ฆฌ ์ฝ”๋“œ์˜ ํ’ˆ์งˆ์„ ๋ณด์žฅํ•ด์ฃผ๋Š” ๊ฑฐ์•ผ!

์ž, ์ด์ œ ๊ธฐ๋ณธ์ ์ธ ํƒ€์ž… ๊ฐ€๋“œ๋“ค์„ ์•Œ์•„๋ดค์–ด. ํ•˜์ง€๋งŒ ์ด๊ฒŒ ๋‹ค๊ฐ€ ์•„๋‹ˆ์•ผ! ๋” ๋ฉ‹์ง„ ํƒ€์ž… ๊ฐ€๋“œ ๊ธฐ๋ฒ•๋“ค์ด ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์ง€. ๊ณ„์†ํ•ด์„œ ์•Œ์•„๋ณผ๊นŒ? ๐Ÿš€

๐ŸŽญ ์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž… ๊ฐ€๋“œ

์ž, ์ด์ œ ์ข€ ๋” ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ๊ธฐ์ˆ ๋กœ ๋„˜์–ด๊ฐ€๋ณผ๊นŒ? ๋ฐ”๋กœ '์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž… ๊ฐ€๋“œ'์•ผ. ์ด๋ฆ„๋ถ€ํ„ฐ ๋ฉ‹์ง€์ง€ ์•Š์•„? ๐Ÿ˜Ž

์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž… ๊ฐ€๋“œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ๋งŒ๋“œ๋Š” ํŠน๋ณ„ํ•œ ํ•จ์ˆ˜์•ผ. ์ด ํ•จ์ˆ˜๋Š” boolean์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋ฐ˜ํ™˜ ํƒ€์ž…์— ํŠน๋ณ„ํ•œ ํ˜•ํƒœ์˜ ํƒ€์ž… ์ˆ ์–ด(type predicate)๋ฅผ ์‚ฌ์šฉํ•ด.


function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}

function move(pet: Fish | Bird) {
  if (isFish(pet)) {
    pet.swim();  // OK!
  } else {
    pet.fly();  // OK!
  }
}
  

์—ฌ๊ธฐ์„œ pet is Fish๊ฐ€ ๋ฐ”๋กœ ํƒ€์ž… ์ˆ ์–ด์•ผ. ์ด ํ•จ์ˆ˜๊ฐ€ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด, TypeScript๋Š” ํ•ด๋‹น ๋ณ€์ˆ˜๊ฐ€ Fish ํƒ€์ž…์ด๋ผ๊ณ  ์ธ์‹ํ•˜๊ฒŒ ๋ผ.

๐Ÿ’ก ์™œ ์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์“ธ๊นŒ? ๋ณต์žกํ•œ ํƒ€์ž… ์ฒดํฌ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด. ์ฝ”๋“œ๊ฐ€ ๋” ๊น”๋”ํ•ด์ง€๊ณ  ๊ฐ€๋…์„ฑ๋„ ์ข‹์•„์ง€์ง€!

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

๐ŸŽจ ์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž… ๊ฐ€๋“œ ํ™œ์šฉ ์˜ˆ์‹œ

์ข€ ๋” ์‹ค์šฉ์ ์ธ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด๋ณผ๊นŒ? API ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ƒํ™ฉ์„ ์ƒ๊ฐํ•ด๋ณด์ž.


interface SuccessResponse {
  status: 'success';
  data: any;
}

interface ErrorResponse {
  status: 'error';
  message: string;
}

type ApiResponse = SuccessResponse | ErrorResponse;

function isSuccessResponse(response: ApiResponse): response is SuccessResponse {
  return response.status === 'success';
}

function handleApiResponse(response: ApiResponse) {
  if (isSuccessResponse(response)) {
    console.log('์„ฑ๊ณต:', response.data);
  } else {
    console.error('์—๋Ÿฌ:', response.message);
  }
}
  

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด API ์‘๋‹ต์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด. ์„ฑ๊ณต ์‘๋‹ต๊ณผ ์—๋Ÿฌ ์‘๋‹ต์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•˜๊ณ , ๊ฐ๊ฐ์— ๋งž๋Š” ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์ง€.

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

๐ŸŒŸ ํ”„๋กœ ํŒ: ์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ๋งŒ๋“ค ๋•Œ๋Š” ํ•จ์ˆ˜ ์ด๋ฆ„์„ is๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ๊ด€๋ก€์•ผ. ์˜ˆ๋ฅผ ๋“ค๋ฉด isString, isNumber ๊ฐ™์€ ์‹์ด์ง€. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค๋„ ์ด ํ•จ์ˆ˜๊ฐ€ ํƒ€์ž… ๊ฐ€๋“œ๋ผ๋Š” ๊ฑธ ์‰ฝ๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์–ด!

์ž, ์ด์ œ ํƒ€์ž… ๊ฐ€๋“œ์˜ ์„ธ๊ณ„์— ๊นŠ์ด ๋น ์ ธ๋“ค์—ˆ์ง€? ํ•˜์ง€๋งŒ ์•„์ง ๋์ด ์•„๋‹ˆ์•ผ! ๋” ํฅ๋ฏธ๋กœ์šด ๋‚ด์šฉ์ด ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์–ด. ๋‹ค์Œ ์„น์…˜์—์„œ ๊ณ„์† ์•Œ์•„๋ณด์ž๊ณ ! ๐Ÿš€

๐Ÿงฉ ํƒ€์ž… ๊ฐ€๋“œ์™€ Union ํƒ€์ž…

Union ํƒ€์ž…๊ณผ ํƒ€์ž… ๊ฐ€๋“œ๋Š” ์ฐฐ๋–ก๊ถํ•ฉ์ด์•ผ! ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ์กฐํ•ฉํ•ด ๋ฉ‹์ง„ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, Union ํƒ€์ž…๊ณผ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ์ •๋ง ๊ฐ•๋ ฅํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด.

๐Ÿ”€ Union ํƒ€์ž… ๋ณต์Šต

Union ํƒ€์ž…์€ ์—ฌ๋Ÿฌ ํƒ€์ž… ์ค‘ ํ•˜๋‚˜์ผ ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐฉ๋ฒ•์ด์•ผ. ์˜ˆ๋ฅผ ๋“ค์–ด:


type StringOrNumber = string | number;
  

์ด ํƒ€์ž…์˜ ๋ณ€์ˆ˜๋Š” ๋ฌธ์ž์—ด์ด๊ฑฐ๋‚˜ ์ˆซ์ž์ผ ์ˆ˜ ์žˆ์–ด. ๊ทผ๋ฐ ์ด๋Ÿฐ Union ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์ด ์žˆ์–ด.

โš ๏ธ ์ฃผ์˜์ : Union ํƒ€์ž…์˜ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ํƒ€์ž…์— ๊ณตํ†ต๋œ ์†์„ฑ์ด๋‚˜ ๋ฉ”์„œ๋“œ๋งŒ ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด.

์ด๋Ÿด ๋•Œ ํƒ€์ž… ๊ฐ€๋“œ๊ฐ€ ๋“ฑ์žฅํ•˜๋Š” ๊ฑฐ์•ผ! ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŠน์ • ํƒ€์ž…์—๋งŒ ์žˆ๋Š” ์†์„ฑ์ด๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€.

๐Ÿ›ก๏ธ Union ํƒ€์ž…๊ณผ ํƒ€์ž… ๊ฐ€๋“œ ํ™œ์šฉํ•˜๊ธฐ

์‹ค์ œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์‚ดํŽด๋ณผ๊นŒ?


type Shape = Circle | Rectangle | Triangle;

interface Circle {
  kind: "circle";
  radius: number;
}

interface Rectangle {
  kind: "rectangle";
  width: number;
  height: number;
}

interface Triangle {
  kind: "triangle";
  base: number;
  height: number;
}

function calculateArea(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "rectangle":
      return shape.width * shape.height;
    case "triangle":
      return 0.5 * shape.base * shape.height;
  }
}
  

์—ฌ๊ธฐ์„œ shape.kind๋ฅผ ์ฒดํฌํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ํƒ€์ž… ๊ฐ€๋“œ ์—ญํ• ์„ ํ•˜๊ณ  ์žˆ์–ด. TypeScript๋Š” ๊ฐ case ๋ธ”๋ก ์•ˆ์—์„œ shape์˜ ์ •ํ™•ํ•œ ํƒ€์ž…์„ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฑฐ์ง€.

์ด๋Ÿฐ ๋ฐฉ์‹์„ '์‹๋ณ„ ๊ฐ€๋Šฅํ•œ Union(Discriminated Union)'์ด๋ผ๊ณ  ๋ถˆ๋Ÿฌ. ๊ฐ ํƒ€์ž…๋งˆ๋‹ค ๊ณตํ†ต๋œ ์†์„ฑ(์—ฌ๊ธฐ์„œ๋Š” 'kind')์„ ๋‘๊ณ , ์ด๋ฅผ ํ†ตํ•ด ํƒ€์ž…์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฑฐ์•ผ.

๐Ÿ’ก ํŒ: ์‹๋ณ„ ๊ฐ€๋Šฅํ•œ Union์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ์•ˆ์ •์„ฑ๊ณผ ๊ฐ€๋…์„ฑ์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋ผ. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๊ฐ ๋ถ„์•ผ์˜ ์ „๋ฌธ๊ฐ€๋ฅผ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•˜๊ณ  ๊ทธ๋“ค์˜ ์žฌ๋Šฅ์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„!

๐ŸŽญ ํƒ€์ž… ๊ฐ€๋“œ์™€ ์ œ๋„ค๋ฆญ

์ œ๋„ค๋ฆญ๊ณผ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ๋”์šฑ ๊ฐ•๋ ฅํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด. ํ•œ๋ฒˆ ๋ณผ๊นŒ?


function isArray<T>(value: T | T[]): value is T[] {
  return Array.isArray(value);
}

function processValues<T>(value: T | T[]) {
  if (isArray(value)) {
    // ์—ฌ๊ธฐ์„œ value๋Š” T[] ํƒ€์ž…
    value.forEach(item => console.log(item));
  } else {
    // ์—ฌ๊ธฐ์„œ value๋Š” T ํƒ€์ž…
    console.log(value);
  }
}
  

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์–ด๋–ค ํƒ€์ž…์ด๋“  ๋‹จ์ผ ๊ฐ’์ธ์ง€ ๋ฐฐ์—ด์ธ์ง€ ์•ˆ์ „ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์–ด. ์ œ๋„ค๋ฆญ์˜ ์œ ์—ฐ์„ฑ๊ณผ ํƒ€์ž… ๊ฐ€๋“œ์˜ ์•ˆ์ „์„ฑ์ด ๋งŒ๋‚˜ ์ •๋ง ๋ฉ‹์ง„ ์ฝ”๋“œ๊ฐ€ ํƒ„์ƒํ•œ ๊ฑฐ์ง€!

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

์ž, ์ด์ œ ํƒ€์ž… ๊ฐ€๋“œ์˜ ์„ธ๊ณ„์— ๊นŠ์ด ๋น ์ ธ๋“ค์—ˆ์ง€? ํ•˜์ง€๋งŒ ์•„์ง ๋” ์žฌ๋ฏธ์žˆ๋Š” ๋‚ด์šฉ์ด ๋‚จ์•„์žˆ์–ด. ๋‹ค์Œ ์„น์…˜์—์„œ ๊ณ„์† ์•Œ์•„๋ณด์ž๊ณ ! ๐Ÿš€

๐ŸŽญ ๊ณ ๊ธ‰ ํƒ€์ž… ๊ฐ€๋“œ ํ…Œํฌ๋‹‰

์ž, ์ด์ œ ํƒ€์ž… ๊ฐ€๋“œ์˜ ๊ณ ๊ธ‰ ๊ธฐ์ˆ ์„ ๋ฐฐ์›Œ๋ณผ ์‹œ๊ฐ„์ด์•ผ! ๐Ÿš€ ์ด ๊ธฐ์ˆ ๋“ค์„ ๋งˆ์Šคํ„ฐํ•˜๋ฉด ๋„ˆ์˜ TypeScript ์‹ค๋ ฅ์€ ํ•œ์ธต ๋” ์—…๊ทธ๋ ˆ์ด๋“œ๋  ๊ฑฐ์•ผ. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๊ณ ๊ธ‰ ๊ธฐ์ˆ ์„ ๊ฐ€์ง„ ์ „๋ฌธ๊ฐ€์ฒ˜๋Ÿผ ๋ง์ด์ง€! ๐Ÿ˜Ž

1. ํƒ€์ž… ๊ฐ€๋“œ์™€ ํƒ€์ž… ๋‹จ์–ธ(Type Assertion) ์กฐํ•ฉํ•˜๊ธฐ

๋•Œ๋กœ๋Š” ํƒ€์ž… ๊ฐ€๋“œ๋งŒ์œผ๋กœ๋Š” ๋ถ€์กฑํ•  ๋•Œ๊ฐ€ ์žˆ์–ด. ์ด๋Ÿด ๋•Œ ํƒ€์ž… ๋‹จ์–ธ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ๋” ๊ฐ•๋ ฅํ•ด์งˆ ์ˆ˜ ์žˆ์ง€.


interface Cat {
  meow(): void;
}

interface Dog {
  bark(): void;
}

function makeNoise(animal: Cat | Dog) {
  if ('meow' in animal) {
    (animal as Cat).meow();
  } else {
    (animal as Dog).bark();
  }
}
  

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

โš ๏ธ ์ฃผ์˜: ํƒ€์ž… ๋‹จ์–ธ์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ๋‚จ์šฉํ•˜๋ฉด ์œ„ํ—˜ํ•  ์ˆ˜ ์žˆ์–ด. ๊ผญ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์•„!

2. ํƒ€์ž… ๊ฐ€๋“œ์™€ ์ œ๋„ค๋ฆญ ์ œ์•ฝ์กฐ๊ฑด(Generic Constraints) ํ™œ์šฉํ•˜๊ธฐ

์ œ๋„ค๋ฆญ๊ณผ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๋•Œ, ์ œ์•ฝ์กฐ๊ฑด์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋” ์ •๊ตํ•œ ํƒ€์ž… ์ฒดํฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ ธ.


interface Lengthwise {
  length: number;
}

function logLength<T extends Lengthwise>(value: T) {
  console.log(value.length);
}

function ensureArray<T>(value: T | T[]): T[] {
  if (Array.isArray(value)) {
    return value;
  } else {
    return [value];
  }
}

// ์‚ฌ์šฉ ์˜ˆ
logLength("Hello");  // OK
logLength([1, 2, 3]);  // OK
// logLength(123);  // Error: number doesn't have a length property

const result = ensureArray("Hello");  // Type: string[]
console.log(result.length);  // OK
  

์—ฌ๊ธฐ์„œ <T extends Lengthwise>๋Š” ์ œ๋„ค๋ฆญ ์ œ์•ฝ์กฐ๊ฑด์ด์•ผ. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด length ์†์„ฑ์ด ์žˆ๋Š” ํƒ€์ž…๋งŒ ํ—ˆ์šฉํ•˜๊ฒŒ ๋ผ. ํƒ€์ž… ๊ฐ€๋“œ์™€ ๊ฒฐํ•ฉํ•˜๋ฉด ๋”์šฑ ์•ˆ์ „ํ•˜๊ณ  ์œ ์—ฐํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์ง€!

3. ์กฐ๊ฑด๋ถ€ ํƒ€์ž…(Conditional Types)๊ณผ ํƒ€์ž… ๊ฐ€๋“œ

์กฐ๊ฑด๋ถ€ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ๋” ๋ณต์žกํ•œ ํƒ€์ž… ๋กœ์ง์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด. ํƒ€์ž… ๊ฐ€๋“œ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์ •๋ง ๊ฐ•๋ ฅํ•ด์ ธ!


type TypeName<T> =
  T extends string ? "string" :
  T extends number ? "number" :
  T extends boolean ? "boolean" :
  T extends undefined ? "undefined" :
  T extends Function ? "function" :
  "object";

function getTypeName<T>(value: T): TypeName<T> {
  if (typeof value === "string") return "string";
  if (typeof value === "number") return "number";
  if (typeof value === "boolean") return "boolean";
  if (typeof value === "undefined") return "undefined";
  if (typeof value === "function") return "function";
  return "object";
}

// ์‚ฌ์šฉ ์˜ˆ
const stringType = getTypeName("hello");  // Type: "string"
const numberType = getTypeName(123);  // Type: "number"
const objectType = getTypeName({});  // Type: "object"
  

์ด ์˜ˆ์ œ์—์„œ TypeName์€ ์กฐ๊ฑด๋ถ€ ํƒ€์ž…์ด๊ณ , getTypeName ํ•จ์ˆ˜๋Š” ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์‚ฌ์šฉํ•ด. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋Ÿฐํƒ€์ž„์— ํƒ€์ž…์„ ์ •ํ™•ํžˆ ํŒ๋ณ„ํ•˜๋ฉด์„œ๋„, ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ •ํ™•ํ•œ ํƒ€์ž… ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์ง€.

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

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

์ž, ์ด์ œ ํƒ€์ž… ๊ฐ€๋“œ์˜ ๊ณ ๊ธ‰ ์„ธ๊ณ„๋ฅผ ํƒํ—˜ํ•ด๋ดค์–ด. ์–ด๋•Œ, ์žฌ๋ฏธ์žˆ์ง€? ๐ŸŽข ํ•˜์ง€๋งŒ ์•„์ง ๋์ด ์•„๋‹ˆ์•ผ! ๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ ๊ฑฐ์•ผ. ์ค€๋น„๋๋‹ˆ? ๊ฐ€์ฆˆ์•„~! ๐Ÿš€

๐Ÿš€ ์‹ค์ „์—์„œ์˜ ํƒ€์ž… ๊ฐ€๋“œ ํ™œ์šฉ

์ž, ์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ๋ฐฐ์šด ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณผ ์ฐจ๋ก€์•ผ! ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๋ฐฐ์šด ๊ธฐ์ˆ ์„ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์•ผ. ๐Ÿ˜Ž

1. API ์‘๋‹ต ์ฒ˜๋ฆฌํ•˜๊ธฐ

์›น ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด API ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ์ผ์ด ์ •๋ง ๋งŽ์ง€? ์ด๋•Œ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์•„์ฃผ ์œ ์šฉํ•ด!


interface SuccessResponse {
  status: 'success';
  data: any;
}

interface ErrorResponse {
  status: 'error';
  message: string;
}

type ApiResponse = SuccessResponse | ErrorResponse;

function handleApiResponse(response: ApiResponse) {
  if (response.status === 'success') {
    // ์—ฌ๊ธฐ์„œ response๋Š” SuccessResponse ํƒ€์ž…
    console.log('๋ฐ์ดํ„ฐ:', response.data);
  } else {
    // ์—ฌ๊ธฐ์„œ response๋Š” ErrorResponse ํƒ€์ž…
    console.error('์—๋Ÿฌ:', response.message);
  }
}

// ์‚ฌ์šฉ ์˜ˆ
const successResponse: ApiResponse = { status: 'success', data: { name: 'John' } };
const errorResponse: ApiResponse = { status: 'error', message: '์„œ๋ฒ„ ์—๋Ÿฌ' };

handleApiResponse(successResponse);
handleApiResponse(errorResponse);
  

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด API ์‘๋‹ต์˜ ํƒ€์ž…์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์–ด. ํƒ€์ž… ์•ˆ์ „์„ฑ๋„ ํ™•๋ณด๋˜๊ณ , ์ฝ”๋“œ๋„ ๊น”๋”ํ•ด์ง€์ง€!

2. ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ์˜ ํ™œ์šฉ

๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ํ™œ์šฉํ•ด ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ๋” ์•ˆ์ „ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด.


interface LoadingState {
  status: 'loading';
}

interface SuccessState {
  status: 'success';
  data: string[];
}

interface ErrorState {
  status: 'error';
  error: string;
}

type State = LoadingState | SuccessState | ErrorState;

function MyComponent({ state }: { state: State }) {
  if (state.status === 'loading') {
    return <div>๋กœ๋”ฉ ์ค‘...</div>;
  } else if (state.status === 'success') {
    return (
      <ul>
        {state.data.map(item => <li key={item}>{item}</li>)}
      </ul>
    );
  } else {
    return <div>์—๋Ÿฌ: {state.error}</div>;
  }
}
  

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ ์ƒํƒœ์— ๋”ฐ๋ฅธ UI๋ฅผ ํƒ€์ž… ์•ˆ์ „ํ•˜๊ฒŒ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ์–ด. ์‹ค์ˆ˜๋กœ ์ž˜๋ชป๋œ ์†์„ฑ์— ์ ‘๊ทผํ•˜๋Š” ์ผ์ด ์—†์–ด์ง€์ง€!

3. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง

๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ๋„ ํƒ€์ž… ๊ฐ€๋“œ๊ฐ€ ์œ ์šฉํ•ด. ํŠนํžˆ ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ์ด๋ฒคํŠธ๋ฅผ ํ•˜๋‚˜์˜ ํ•ธ๋“ค๋Ÿฌ๋กœ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋ง์ด์•ผ.


function handleEvent(event: MouseEvent | KeyboardEvent) {
  if (event instanceof MouseEvent) {
    console.log(`๋งˆ์šฐ์Šค ์œ„์น˜: (${event.clientX}, ${event.clientY})`);
  } else {
    console.log(`๋ˆŒ๋ฆฐ ํ‚ค: ${event.key}`);
  }
}

// ์‚ฌ์šฉ ์˜ˆ
document.addEventListener('click', handleEvent);
document.addEventListener('keydown', handleEvent);
  

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด๋ฒคํŠธ์˜ ํƒ€์ž…์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์–ด. ์ฝ”๋“œ๋„ ๊น”๋”ํ•˜๊ณ  ํƒ€์ž… ์•ˆ์ „์„ฑ๋„ ํ™•๋ณด๋˜์ง€!

๐Ÿ’ก ํ”„๋กœ ํŒ: ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํ•ญ์ƒ ๋ชจ๋“  ์ผ€์ด์Šค๋ฅผ ์ปค๋ฒ„ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด!

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

์ž, ์ด์ œ ํƒ€์ž… ๊ฐ€๋“œ์˜ ์‹ค์ „ ํ™œ์šฉ๋ฒ•๊นŒ์ง€ ๋ฐฐ์› ์–ด. ์–ด๋•Œ, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋” ์žฌ๋ฏธ์žˆ์–ด ๋ณด์ด์ง€ ์•Š์•„? ๐ŸŽ‰ ํ•˜์ง€๋งŒ ์•„์ง ์šฐ๋ฆฌ์˜ ์—ฌ์ •์€ ๋๋‚˜์ง€ ์•Š์•˜์–ด. ๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ๋“ค์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ๊ฑฐ์•ผ. ์ค€๋น„๋๋‹ˆ? ๊ฐ€์ฆˆ์•„~! ๐Ÿš€

โš ๏ธ ํƒ€์ž… ๊ฐ€๋“œ ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์‚ฌํ•ญ

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

1. ๊ณผ๋„ํ•œ ์‚ฌ์šฉ ์ฃผ์˜

ํƒ€์ž… ๊ฐ€๋“œ๋Š” ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ๋„ˆ๋ฌด ๋งŽ์ด ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์–ด.


// ์ข‹์ง€ ์•Š์€ ์˜ˆ
function processValue(value: string | number | boolean | object) {
  if (typeof value === 'string') {
    // string ์ฒ˜๋ฆฌ
  } else if (typeof value === 'number') {
    // number ์ฒ˜๋ฆฌ
  } else if (typeof value === 'boolean') {
    // boolean ์ฒ˜๋ฆฌ
  } else {
    // object ์ฒ˜๋ฆฌ
  }
}

// ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•
type ValueType = 'string' | 'number' | 'boolean' | 'object';

function processValue(value: any, type: ValueType) {
  switch (type) {
    case 'string':
      // string ์ฒ˜๋ฆฌ
      break;
    case 'number':
      // number ์ฒ˜๋ฆฌ
      break;
    // ... ๊ธฐํƒ€ ์ผ€์ด์Šค
  }
}
  

ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ๋„ˆ๋ฌด ๋งŽ์ด ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์–ด. ๊ฐ€๋Šฅํ•˜๋ฉด ํƒ€์ž…์„ ๋‹จ์ˆœํ™”ํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•ด๋ด.

2. ๋ถ€์ •ํ™•ํ•œ ํƒ€์ž… ๊ฐ€๋“œ

ํƒ€์ž… ๊ฐ€๋“œ๊ฐ€ ๋ชจ๋“  ์ผ€์ด์Šค๋ฅผ ์ •ํ™•ํžˆ ์ปค๋ฒ„ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์–ด.


function isArray(value: any): value is any[] {
  return Array.isArray(value);
}

function processItems(items: string | string[]) {
  if (isArray(items)) {
    items.forEach(item => console.log(item.toUpperCase()));
  } else {
    console.log(items.toUpperCase());
  }
}

// ๋ฌธ์ œ ๋ฐœ์ƒ!
processItems([1, 2, 3] as any);  // ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ: 1.toUpperCase is not a function
  

์ด ์˜ˆ์ œ์—์„œ isArray ํƒ€์ž… ๊ฐ€๋“œ๋Š” ๋ฐฐ์—ด์˜ ์š”์†Œ ํƒ€์ž…์„ ์ฒดํฌํ•˜์ง€ ์•Š์•„. ๊ทธ๋ž˜์„œ ์ˆซ์ž ๋ฐฐ์—ด์„ ๋„ฃ์œผ๋ฉด ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด.

3. ๋ถ€์ž‘์šฉ์ด ์žˆ๋Š” ํƒ€์ž… ๊ฐ€๋“œ

ํƒ€์ž… ๊ฐ€๋“œ ํ•จ์ˆ˜์— ๋ถ€์ž‘์šฉ์ด ์žˆ์œผ๋ฉด ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด.


let count = 0;

function isString(value: any): value is string {
  count++;  // ๋ถ€์ž‘์šฉ!
  return typeof value === 'string';
}

function processValue(value: string | number) {
  if (isString(value)) {
    console.log(value.toUpperCase());
  } else {
    console.log(value.toFixed(2));
  }
}

processValue('hello');
console.log(count);  // 1
processValue(42);
console.log(count);  // 2
  

ํƒ€์ž… ๊ฐ€๋“œ ํ•จ์ˆ˜์— ๋ถ€์ž‘์šฉ์ด ์žˆ์œผ๋ฉด, ํƒ€์ž… ์ฒดํฌ๋งŒ ํ•˜๋ ค๊ณ  ํ•ด๋„ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์ƒํƒœ ๋ณ€ํ™”๊ฐ€ ์ผ์–ด๋‚  ์ˆ˜ ์žˆ์–ด.

๐Ÿ’ก ํ”„๋กœ ํŒ: ํƒ€์ž… ๊ฐ€๋“œ ํ•จ์ˆ˜๋Š” ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค์–ด. ์ฆ‰, ํƒ€์ž… ์ฒดํฌ ์™ธ์˜ ๋‹ค๋ฅธ ์ผ์€ ํ•˜์ง€ ์•Š๋„๋ก ํ•ด!

4. ํƒ€์ž… ๋‹จ์–ธ(Type Assertion)์˜ ๊ณผ๋„ํ•œ ์‚ฌ์šฉ

ํƒ€์ž… ๊ฐ€๋“œ ๋Œ€์‹  ํƒ€์ž… ๋‹จ์–ธ์„ ๊ณผ๋„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์–ด.


function processValue(value: string | number) {
  // ์ข‹์ง€ ์•Š์€ ๋ฐฉ๋ฒ•
  console.log((value as string).toUpperCase());

  // ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•
  if (typeof value === 'string') {
    console.log(value.toUpperCase());
  } else {
    console.log(value.toFixed(2));
  }
}
  

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

์ด๋Ÿฐ ์ฃผ์˜์‚ฌํ•ญ๋“ค์„ ์ž˜ ๊ธฐ์–ตํ•˜๊ณ  ์žˆ์œผ๋ฉด, ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ๋”์šฑ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ์ „๋ฌธ๊ฐ€์˜ ์กฐ์–ธ์„ ์ž˜ ํ™œ์šฉํ•ด ํ”„๋กœ์ ํŠธ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๋งˆ๋ฌด๋ฆฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์•ผ!

์ž, ์ด์ œ ํƒ€์ž… ๊ฐ€๋“œ์˜ ์ฃผ์˜์‚ฌํ•ญ๊นŒ์ง€ ์•Œ์•„๋ดค์–ด. ์–ด๋•Œ, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๋งˆ์Šคํ„ฐ๊ฐ€ ๋œ ๊ฒƒ ๊ฐ™์ง€ ์•Š์•„? ๐Ÿ† ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ์˜ ์—ฌ์ •์€ ์•„์ง ๋๋‚˜์ง€ ์•Š์•˜์–ด. ๋งˆ์ง€๋ง‰์œผ๋กœ ํƒ€์ž… ๊ฐ€๋“œ์˜ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž๊ณ . ์ค€๋น„๋๋‹ˆ? ๋งˆ์ง€๋ง‰ ์ŠคํผํŠธ๋‹ค! ๐Ÿ

๐ŸŒŸ ํƒ€์ž… ๊ฐ€๋“œ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค

์ž, ์ด์ œ ์šฐ๋ฆฌ์˜ ํƒ€์ž… ๊ฐ€๋“œ ์—ฌ์ •์˜ ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์•ผ! ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ, ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ๊ฐ€์žฅ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ์ตœ๊ณ ์˜ ์ „๋ฌธ๊ฐ€๋“ค์ด ๊ณต์œ ํ•˜๋Š” ๋…ธํ•˜์šฐ๋ฅผ ๋ฐฐ์šฐ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์•ผ! ๐Ÿ˜Ž

1. ๋ช…ํ™•ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•œ ํƒ€์ž… ๊ฐ€๋“œ ์ž‘์„ฑํ•˜๊ธฐ

ํƒ€์ž… ๊ฐ€๋“œ๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ๋ช…ํ™•ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑํ•ด์•ผ ํ•ด. ๋ณต์žกํ•œ ๋กœ์ง์€ ํ”ผํ•˜๊ณ , ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ํƒ€์ž…๋งŒ ์ฒดํฌํ•˜๋Š” ๊ฒŒ ์ข‹์•„.


// ์ข‹์€ ์˜ˆ
function isString(value: unknown): value is string {
  return typeof value === 'string';
}

function isNumber(value: unknown): value is number {
  return typeof value === 'number';
}

// ์‚ฌ์šฉ ์˜ˆ
function processValue(value: unknown) {
  if (isString(value)) {
    console.log(value.toUpperCase());
  } else if (isNumber(value)) {
    console.log(value.toFixed(2));
  } else {
    console.log('Unknown type');
  }
}
  

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ ํƒ€์ž… ๊ฐ€๋“œ์˜ ์—ญํ• ์ด ๋ช…ํ™•ํ•ด์ง€๊ณ , ์žฌ์‚ฌ์šฉ์„ฑ๋„ ๋†’์•„์ ธ.

2. ์œ ๋‹ˆ์˜จ ํƒ€์ž…๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ

ํƒ€์ž… ๊ฐ€๋“œ๋Š” ์œ ๋‹ˆ์˜จ ํƒ€์ž…๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๋•Œ ์ง„๊ฐ€๋ฅผ ๋ฐœํœ˜ํ•ด. ๋ณต์žกํ•œ ํƒ€์ž…์„ ๋‹ค๋ฃฐ ๋•Œ ํŠนํžˆ ์œ ์šฉํ•˜์ง€.


type Shape = Circle | Rectangle | Triangle;

interface Circle {
  kind: 'circle';
  radius: number;
}

interface Rectangle {
  kind: 'rectangle';
  width: number;
  height: number;
}

interface Triangle {
  kind: 'triangle';
  base: number;
  height: number;
}

function calculateArea(shape: Shape): number {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius ** 2;
    case 'rectangle':
      return shape.width * shape.height;
    case 'triangle':
      return 0.5 * shape.base * shape.height;
  }
}
  

์ด๋Ÿฐ ์‹์œผ๋กœ ์œ ๋‹ˆ์˜จ ํƒ€์ž…๊ณผ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด, ๋ณต์žกํ•œ ํƒ€์ž…๋„ ์•ˆ์ „ํ•˜๊ฒŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์–ด.

3. ์ œ๋„ค๋ฆญ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ

์ œ๋„ค๋ฆญ๊ณผ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์กฐํ•ฉํ•˜๋ฉด ๋”์šฑ ์œ ์—ฐํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด.


function isArrayOfType<T>(value: unknown, typeGuard: (item: unknown) => item is T): value is T[] {
  return Array.isArray(value) && value.every(typeGuard);
}

// ์‚ฌ์šฉ ์˜ˆ
const numbers = [1, 2, 3, 4, 5];
if (isArrayOfType(numbers, isNumber)) {
  console.log(numbers.reduce((a, b) => a + b, 0));
}
  

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์–ด๋–ค ํƒ€์ž…์˜ ๋ฐฐ์—ด์ด๋“  ์•ˆ์ „ํ•˜๊ฒŒ ์ฒดํฌํ•  ์ˆ˜ ์žˆ์–ด. ์ •๋ง ๊ฐ•๋ ฅํ•˜์ง€?

4. ํƒ€์ž… ๊ฐ€๋“œ์™€ early return ํŒจํ„ด

ํƒ€์ž… ๊ฐ€๋“œ์™€ early return ํŒจํ„ด์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์–ด.


function processValue(value: string | number | boolean) {
  if (typeof value === 'string') {
    console.log(value.toUpperCase());
    return;
  }
  
  if (typeof value === 'number') {
    console.log(value.toFixed(2));
    return;
  }
  
  console.log(value ? 'True' : 'False');
}
  

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ ํƒ€์ž…์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„๋˜๊ณ , ์ค‘์ฒฉ๋œ if๋ฌธ์„ ํ”ผํ•  ์ˆ˜ ์žˆ์–ด.

๐Ÿ’ก ํ”„๋กœ ํŒ: ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š” ํ•ญ์ƒ ๊ฐ€๋…์„ฑ๊ณผ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๊ณ ๋ คํ•ด. ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค๋„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์•ผ ํ•ด!

์ด๋ ‡๊ฒŒ ํƒ€์ž… ๊ฐ€๋“œ์˜ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค๋ฅผ ์ ์šฉํ•˜๋ฉด, ๋„ˆ์˜ TypeScript ์ฝ”๋“œ๋Š” ํ•œ์ธต ๋” ์•ˆ์ „ํ•˜๊ณ  ์ฝ๊ธฐ ์‰ฌ์›Œ์งˆ ๊ฑฐ์•ผ. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ์ตœ๊ณ ์˜ ์ „๋ฌธ๊ฐ€๋“ค์˜ ์กฐ์–ธ์„ ๋ชจ๋‘ ์ ์šฉํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์•ผ!

์ž, ์ด์ œ ์šฐ๋ฆฌ์˜ ํƒ€์ž… ๊ฐ€๋“œ ์—ฌ์ •์ด ๋๋‚ฌ์–ด. ์–ด๋•Œ, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์˜ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ ํ•˜๋‚˜๋ฅผ ์™„์ „ํžˆ ๋งˆ์Šคํ„ฐํ•œ ๊ฒƒ ๊ฐ™์ง€ ์•Š์•„? ๐ŸŽ‰ ์ด์ œ ๋„ˆ๋Š” ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์ž์œ ์ž์žฌ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” TypeScript ๋งˆ์Šคํ„ฐ์•ผ! ์•ž์œผ๋กœ ๋” ๋ฉ‹์ง„ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ. ํ™”์ดํŒ…! ๐Ÿ’ช