๐Ÿ“˜ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๊ฐœ๋… ์ •๋ฆฌ06

seoyoon_leeยท2026๋…„ 3์›” 29์ผ

TypeScript

๋ชฉ๋ก ๋ณด๊ธฐ
13/21
post-thumbnail

๐Ÿง  1. ํ•ต์‹ฌ ๊ฐœ๋…

โœ” ์„œ๋กœ์†Œ ์œ ๋‹ˆ์˜จ ํƒ€์ž…์ด๋ž€?

๐Ÿ‘‰ ๊ฒน์น˜์ง€ ์•Š๋Š” ์—ฌ๋Ÿฌ ํƒ€์ž…์„ ํ•˜๋‚˜๋กœ ํ•ฉ์นœ ํƒ€์ž…
๋ณดํ†ต ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…(tag, state ๋“ฑ)์„ ์ด์šฉํ•ด ๊ฐ ํƒ€์ž…์„ ๊ตฌ๋ถ„ํ•œ๋‹ค.

์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด:

  • Admin ๐Ÿ‘‰ ๊ด€๋ฆฌ์ž
  • Member ๐Ÿ‘‰ ํšŒ์›
  • Guest ๐Ÿ‘‰ ์†๋‹˜

์ด 3๊ฐœ๋Š” ์ ˆ๋Œ€ ๊ฐ™์€ ์‚ฌ๋žŒ์ด ๋  ์ˆ˜ ์—†์Œ โ†’ ์„œ๋กœ ๊ฒน์น˜์ง€ ์•Š์Œ

๊ทธ๋ž˜์„œ ๐Ÿ‘‰ ์„œ๋กœ์†Œ(disjoint)

โœ” ์™œ tag๋ฅผ ์“ฐ๋ƒ?

type Admin = {
  tag: 'ADMIN';
}

๐Ÿ‘‰ ์ด tag๊ฐ€ ๊ตฌ๋ถ„์ž ์—ญํ•  (์‹๋ณ„์ž)

์ฆ‰,

  • tag๊ฐ€ 'ADMIN'์ด๋ฉด ๐Ÿ‘‰ ๋ฌด์กฐ๊ฑด Admin
  • tag๊ฐ€ 'MEMBER'๋ฉด ๐Ÿ‘‰ ๋ฌด์กฐ๊ฑด Member

๐Ÿ‘‰ ๊ทธ๋ž˜์„œ ํƒ€์ž…์„ ์ž๋™์œผ๋กœ ์ขํ˜€์คŒ (ํƒ€์ž… ์ขํžˆ๊ธฐ

โœ” ์˜ˆ์‹œ

type Admin = {
  tag: 'ADMIN';
  name: string;
  kickCount: number;
};

type Member = {
  tag: 'MEMBER';
  name: string;
  point: number;
};

type Guest = {
  tag: 'GUEST';
  name: string;
  visitCount: number;
};

type User = Admin | Member | Guest;

๐Ÿ”ฅ 2. ํ•ต์‹ฌ ํฌ์ธํŠธ

โœ” TypeScript๊ฐ€ ๋˜‘๋˜‘ํ•ด์ง€๋Š” ์ˆœ๊ฐ„

switch (user.tag) {
case 'ADMIN':

๐Ÿ‘‰ ์ด ์ˆœ๊ฐ„ TypeScript๋Š”
๐Ÿ‘‰ "์•„ ์–˜๋Š” Admin์ด๋„ค?" ๋ผ๊ณ  ํŒ๋‹จ

๊ทธ๋ž˜์„œ โ†“ ๊ฐ€๋Šฅ

user.kickCount

โ— ๋”ฐ๋กœ ํƒ€์ž… ๋‹จ์–ธ ํ•„์š” ์—†์Œ

โŒ ์„œ๋กœ์†Œ ์œ ๋‹ˆ์˜จ ์•ˆ ์“ฐ๋ฉด ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ

type AsyncTask = {
  state: 'LOADING' | 'FAILED' | 'SUCCESS';
  error?: { message: string };
}

๐Ÿ‘‰ ๋ฌธ์ œ:

  • error ์žˆ์„ ์ˆ˜๋„, ์—†์„ ์ˆ˜๋„ ์žˆ์Œ ๐Ÿ˜ฑ

๊ทธ๋ž˜์„œ โ†“ ์ด๋Ÿฐ๊ฑฐ ํ•ด์•ผ๋จ

task.error?.message

๐Ÿ‘‰ ์•ˆ์ „ํ•˜์ง€๋„ ์•Š๊ณ  ๊ท€์ฐฎ์Œ

โœ… ์„œ๋กœ์†Œ ์œ ๋‹ˆ์˜จ ์“ฐ๋ฉด?

type FailedTask = {
  state: 'FAILED';
  error: { message: string };
}

๐Ÿ‘‰ state๊ฐ€ FAILED๋ฉด
๐Ÿ‘‰ error๋Š” ๋ฌด์กฐ๊ฑด ์žˆ์Œ

๊ทธ๋ž˜์„œ โ†“ ๊ฐ€๋Šฅ

task.error.message

โœ” ํƒ€์ž… ์ขํžˆ๊ธฐ (ํ•ต์‹ฌ)

function login(user: User) {
  switch (user.tag) {
    case 'ADMIN':
      console.log(`${user.name}๋‹˜ ${user.kickCount}๋ช… ๊ฐ•ํ‡ด`);
      break;

    case 'MEMBER':
      console.log(`${user.name}๋‹˜ ${user.point} ํฌ์ธํŠธ`);
      break;

    case 'GUEST':
      console.log(`${user.name}๋‹˜ ${user.visitCount} ๋ฐฉ๋ฌธ`);
      break;
  }
}

๐Ÿ‘‰ tag ๊ฐ’์œผ๋กœ ํƒ€์ž…์ด ์ž๋™์œผ๋กœ ์ขํ˜€์ง„๋‹ค.

โœ” ์ž˜๋ชป๋œ ๋ฐฉ์‹ (์„ ํƒ์  ํ”„๋กœํผํ‹ฐ)

type AsyncTask = {
  state: 'LOADING' | 'FAILED' | 'SUCCESS';
  error?: { message: string };
  response?: { data: string };
};

โ— ๋ฌธ์ œ์ 

  • ์–ด๋–ค ๊ฐ’์ด ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Œ
  • ?, ! ํ•„์š” โ†’ ์•ˆ์ „ํ•˜์ง€ ์•Š์Œ

โœ” ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ์‹ (์„œ๋กœ์†Œ ์œ ๋‹ˆ์˜จ)

type LoadingTask = {
  state: 'LOADING';
};

type FailedTask = {
  state: 'FAILED';
  error: { message: string };
};

type SuccessTask = {
  state: 'SUCCESS';
  response: { data: string };
};

type AsyncTask = LoadingTask | FailedTask | SuccessTask;

โœ” ์‚ฌ์šฉ ์˜ˆ

function processResult(task: AsyncTask) {
  switch (task.state) {
    case 'LOADING':
      console.log('๋กœ๋”ฉ ์ค‘');
      break;

    case 'FAILED':
      console.log(task.error.message);
      break;

    case 'SUCCESS':
      console.log(task.response.data);
      break;
  }
}

โœ” ์žฅ์ 

โœ… ํƒ€์ž… ์ž๋™ ์ขํžˆ๊ธฐ ๊ฐ€๋Šฅ
โœ… ๋ถˆํ•„์š”ํ•œ ?, ! ์ œ๊ฑฐ
โœ… ์ฝ”๋“œ ์•ˆ์ •์„ฑ ์ฆ๊ฐ€
โœ… ๊ฐ€๋…์„ฑ ์ข‹์•„์ง

๐Ÿ’ก 3. ๋น„์œ ๋กœ ์ดํ•ดํ•˜๊ธฐ

๐ŸŽซ ํ‹ฐ์ผ“ ๋น„์œ 

  • ADMIN ํ‹ฐ์ผ“ ๐Ÿ‘‰ ๊ด€๋ฆฌ์ž ๊ธฐ๋Šฅ ์žˆ์Œ
  • MEMBER ํ‹ฐ์ผ“ ๐Ÿ‘‰ ํฌ์ธํŠธ ์žˆ์Œ
  • GUEST ํ‹ฐ์ผ“ ๐Ÿ‘‰ ๋ฐฉ๋ฌธ ๊ธฐ๋ก ์žˆ์Œ

๐Ÿ‘‰ ํ‹ฐ์ผ“ ์ข…๋ฅ˜(tag) ๋ณด๋ฉด
๐Ÿ‘‰ ์–ด๋–ค ๊ธฐ๋Šฅ ์žˆ๋Š”์ง€ ๋ฐ”๋กœ ์•Œ ์ˆ˜ ์žˆ์Œ

โš ๏ธ 4.๋งŽ์ด ํ•˜๋Š” ์‹ค์ˆ˜

โŒ ์‹ค์ˆ˜ 1

console.log({user.name})

๐Ÿ‘‰ โŒ ํ‹€๋ฆผ

๐Ÿ‘‰ ${} ์จ์•ผ๋จ

console.log(${user.name})

โŒ ์‹ค์ˆ˜ 2

error?

๐Ÿ‘‰ ๋ฌด์กฐ๊ฑด ์žˆ๋Š” ๊ฐ’์ธ๋ฐ optional๋กœ ๋งŒ๋“ฆ โ†’ ์ž˜๋ชป๋œ ์„ค๊ณ„

โŒ ์‹ค์ˆ˜ 3

if ("error" in task)

๐Ÿ‘‰ ๊ฐ€๋Šฅ์€ ํ•˜์ง€๋งŒ
๐Ÿ‘‰ โ— tag/state ์“ฐ๋Š”๊ฒŒ ํ›จ์”ฌ ๊น”๋”ํ•˜๊ณ  ํ‘œ์ค€์ 

๐ŸŽฏ ํ•œ ์ค„ ์ •๋ฆฌ

๐Ÿ‘‰ "tag ๊ฐ™์€ ๊ฐ’์œผ๋กœ ํƒ€์ž…์„ ๊ตฌ๋ถ„ํ•ด์„œ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด"

profile
Frontend Developer ยท ๊ธฐ๋ก โญ

0๊ฐœ์˜ ๋Œ“๊ธ€