Pink Bobblehead Bunny TypeScript๊ฐ€ ๋А๋ ค์ง€๋Š” N๊ฐ€์ง€ ์ด์œ : ์ปดํŒŒ์ผ ์„ฑ๋Šฅ ์ตœ์ ํ™” ์‹ค์ „ ๊ฐ€์ด๋“œ
 

TypeScript๊ฐ€ ๋А๋ ค์ง€๋Š” N๊ฐ€์ง€ ์ด์œ : ์ปดํŒŒ์ผ ์„ฑ๋Šฅ ์ตœ์ ํ™” ์‹ค์ „ ๊ฐ€์ด๋“œ

TypeScript ํ”„๋กœ์ ํŠธ์˜ ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๋ฉด์„œ ์–ด๋А ๋‚  ๋ฌธ๋“ ๊นจ๋‹ซ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ €์žฅํ•  ๋•Œ๋งˆ๋‹ค VS Code์˜ ํƒ€์ž… ์ถ”๋ก (IntelliSense)์ด ๋ฒ„๋ฒ…์ด๊ณ , tsc ๋นŒ๋“œ ์‹œ๊ฐ„์€ ํ•˜์—ผ์—†์ด ๋Š˜์–ด๋‚ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋‹จ์ˆœํ•œ ๋ถˆํŽธํ•จ์„ ๋„˜์–ด, ์šฐ๋ฆฌ์˜ ์†Œ์ค‘ํ•œ ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ๊ณผ ํ๋ฆ„์„ ๋Š์–ด๋ฒ„๋ฆฌ๋Š” ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

๋А๋ฆฐ ์ปดํŒŒ์ผ์€ ์™œ ๋ฐœ์ƒํ•˜๋ฉฐ, ์šฐ๋ฆฌ๋Š” ์ด ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

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

1. ์™œ ์ปดํŒŒ์ผ ์„ฑ๋Šฅ์ด ์ค‘์š”ํ•œ๊ฐ€?: ๋‹จ์ˆœํ•œ ์†๋„ ๊ทธ ์ด์ƒ์˜ ๋ฌธ์ œ

๋А๋ฆฐ ์ปดํŒŒ์ผ์€ ๋‹จ์ˆœํžˆ '๊ธฐ๋‹ค๋ฆฌ๋Š” ์‹œ๊ฐ„'์ด ๊ธธ์–ด์ง€๋Š” ๊ฒƒ๋งŒ์„ ์˜๋ฏธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ์ง€์—ฐ๋˜๋Š” ํ”ผ๋“œ๋ฐฑ: ์ฝ”๋“œ ์—๋””ํ„ฐ์—์„œ ํƒ€์ž… ์˜ค๋ฅ˜๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฐ ๋ช‡ ์ดˆ์”ฉ ๊ฑธ๋ฆฐ๋‹ค๋ฉด, ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ๊ฒ€์ฆํ•˜๋Š” TypeScript์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์ด ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
  • ์ธ์ง€ ๋ถ€ํ•˜ ์ฆ๊ฐ€: ์žฆ์€ ๋ฒ„๋ฒ…์ž„์€ ๊ฐœ๋ฐœ์ž์˜ ์ง‘์ค‘๋ ฅ์„ ํฉํŠธ๋ฆฌ๊ณ , ๋ฌธ์ œ ํ•ด๊ฒฐ์˜ ํ๋ฆ„์„ ๋ฐฉํ•ดํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ์ธ์ง€ ๋ถ€ํ•˜๋ฅผ ์œ ๋ฐœํ•ฉ๋‹ˆ๋‹ค.
  • CI/CD ์‹œ๊ฐ„ ์ฆ๊ฐ€: ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์ฝ”๋“œ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ๋ฐฐํฌํ•˜๋Š” CI/CD ํŒŒ์ดํ”„๋ผ์ธ์˜ ์‹œ๊ฐ„๋„ ๊ธธ์–ด์ ธ ์ „์ฒด ํŒ€์˜ ์ƒ์‚ฐ์„ฑ์— ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ ์ปดํŒŒ์ผ ์„ฑ๋Šฅ์€ ๊ณง ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜(DX, Developer Experience) ๊ณผ ์ง๊ฒฐ๋˜๋Š” ํ•ต์‹ฌ์ ์ธ ์š”์†Œ์ž…๋‹ˆ๋‹ค.


2. ์ฃผ๋ฒ” 1: ๊ณผ๋„ํ•˜๊ฒŒ ๋ณต์žกํ•œ ํƒ€์ž… ์—ฐ์‚ฐ

์ปดํŒŒ์ผ ์„ฑ๋Šฅ ์ €ํ•˜์˜ ๊ฐ€์žฅ ํ”ํ•œ ์›์ธ์€ ํ•„์š” ์ด์ƒ์œผ๋กœ ๋ณต์žกํ•˜๊ณ  ๊ด‘๋ฒ”์œ„ํ•œ ํƒ€์ž… ์—ฐ์‚ฐ์ž…๋‹ˆ๋‹ค.

๊ฐ€. ๊ฑฐ๋Œ€ํ•œ ์œ ๋‹ˆ์˜จ๊ณผ Mapped Types์˜ ํ•จ์ •

Mapped Types๋Š” ๋งค์šฐ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ์ˆ˜์ฒœ ๊ฐœ์˜ ํ‚ค๋ฅผ ๊ฐ€์ง„ ๊ฑฐ๋Œ€ํ•œ ๊ฐ์ฒด ํƒ€์ž…์— ์ง์ ‘ ์ ์šฉํ•˜๋Š” ์ˆœ๊ฐ„ ์ปดํŒŒ์ผ๋Ÿฌ์˜ ์•…๋ชฝ์ด ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

๐Ÿ˜ฉ Bad: ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•˜๋Š” ์ ‘๊ทผ๋ฒ•

์ˆ˜๋ฐฑ ๊ฐœ์˜ ์•„์ด์ฝ˜ ์ •๋ณด๋ฅผ ๋‹ด์€ ๊ฐ์ฒด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ, ๋ชจ๋“  ์•„์ด์ฝ˜์„ boolean prop์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” Icon ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค.

// icons.ts - 500+๊ฐœ์˜ ์•„์ด์ฝ˜์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •
export const ICONS = {
  add: '<svg>...</svg>',
  arrowDown: '<svg>...</svg>',
  // ...
  wallet: '<svg>...</svg>',
};
export type IconName = keyof typeof ICONS; // "add" | "arrowDown" | ...

// Bad: 500๊ฐœ ์ด์ƒ์˜ ์œ ๋‹ˆ์˜จ์— ๋Œ€ํ•ด Mapped Type์„ ์‹คํ–‰
// ์ปดํŒŒ์ผ๋Ÿฌ๋Š” Icon ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ์šฉ๋  ๋•Œ๋งˆ๋‹ค ์ด ๊ฑฐ๋Œ€ํ•œ ํƒ€์ž…์„ ๊ณ„์‚ฐํ•ด์•ผ ํ•œ๋‹ค.
type IconProps = {
  [K in IconName]?: boolean; // 500๋ฒˆ ์ด์ƒ์˜ ์—ฐ์‚ฐ ๋ฐœ์ƒ
};

function Icon(props: IconProps) {
  // ...
}

์ด ๋ฐฉ์‹์€ Icon ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ์šฉ๋  ๋•Œ๋งˆ๋‹ค 500๊ฐœ๊ฐ€ ๋„˜๋Š” ์˜ต์…”๋„ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง„ ๊ฑฐ๋Œ€ํ•œ ํƒ€์ž…์„ ๊ณ„์‚ฐํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” ํ•œ๋‘ ๊ฐœ์˜ ์•„์ด์ฝ˜๋งŒ ์‚ฌ์šฉํ•˜๋Š”๋ฐ๋„ ๋ง์ด์ฃ .

๐Ÿ˜Š Good: ์ œ๋„ค๋ฆญ์„ ํ†ตํ•œ '์ง€์—ฐ' ๋ฐ '์ถ”๋ก ' ํ™œ์šฉ

๋” ๋‚˜์€ ์ ‘๊ทผ๋ฒ•์€ ์‚ฌ์šฉ ์‹œ์ ์— ํ•„์š”ํ•œ ๋งŒํผ๋งŒ ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๋„๋ก ์ œ๋„ค๋ฆญ์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํƒ€์ž… ๊ณ„์‚ฐ์˜ ์‹œ์ ์„ '๋ฏธ๋ฆฌ'์—์„œ 'ํ•„์š”ํ•  ๋•Œ'๋กœ ๋ฏธ๋ฃจ๋Š” ์ „๋žต์ž…๋‹ˆ๋‹ค.

// Good: ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•ด ์‹ค์ œ ์ „๋‹ฌ๋œ props๋งŒ ํƒ€์ž…์œผ๋กœ ์ถ”๋ก 
type IconProps<T extends IconName> = {
  [K in T]?: boolean;
};

function Icon<T extends IconName>(props: IconProps<T>) {
  // ...
}

// ์‚ฌ์šฉ ์‹œ์ ์—๋Š” "add", "wallet" ๋‘ ๊ฐœ์˜ ํ‚ค์— ๋Œ€ํ•ด์„œ๋งŒ ํƒ€์ž… ์—ฐ์‚ฐ์ด ์ผ์–ด๋‚œ๋‹ค.
<Icon add wallet />;

์ด์ฒ˜๋Ÿผ ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๋ฉด, TypeScript๋Š” Icon ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‹ค์ œ๋กœ ์‚ฌ์šฉ๋  ๋•Œ ์ „๋‹ฌ๋œ ํ”„๋กญ(add, wallet)๋งŒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํƒ€์ž…์„ ๊ณ„์‚ฐํ•˜๋ฏ€๋กœ ์ปดํŒŒ์ผ ๋ถ€๋‹ด์ด ๊ทน์ ์œผ๋กœ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

๋‚˜. ์กฐ๊ฑด๋ถ€ ํƒ€์ž…(Conditional Types)์˜ ์˜๋„์น˜ ์•Š์€ ๋ถ„๋ฐฐ

์กฐ๊ฑด๋ถ€ ํƒ€์ž…์ด ์ œ๋„ค๋ฆญ ์œ ๋‹ˆ์˜จ ํƒ€์ž…์„ ๋งŒ๋‚˜๋ฉด, ๊ฐ ์œ ๋‹ˆ์˜จ ๋ฉค๋ฒ„์— ๋Œ€ํ•ด ๊ฐœ๋ณ„์ ์œผ๋กœ ํƒ€์ž…์„ ๊ณ„์‚ฐํ•˜๋Š” ๋ถ„๋ฐฐ ๋ฒ•์น™(Distributive Conditional Types) ์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋•Œ๋กœ ์„ฑ๋Šฅ ์ €ํ•˜์™€ ์˜๋„์น˜ ์•Š์€ ๊ฒฐ๊ณผ๋ฅผ ์ดˆ๋ž˜ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ˜ฉ Bad: ๋ถ„๋ฐฐ ๋ฒ•์น™์œผ๋กœ ์ธํ•ด ํƒ€์ž…์ด ๋„ˆ๋ฌด ๋„“์–ด์ง€๋Š” ๊ฒฝ์šฐ

API ๋ผ์šฐํŠธ ๊ฒฝ๋กœ("/users", "/users/:id") ์ค‘ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํฌํ•จ๋œ ๊ฒฝ๋กœ๋งŒ ์ถ”์ถœํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์„ ๋งŒ๋“ ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค.

type Routes = "/users" | "/users/:id" | "/posts" | "/posts/:id";

// `:id`๊ฐ€ string์˜ ์„œ๋ธŒํƒ€์ž…์ด๋ฏ€๋กœ ๋ชจ๋“  Routes๊ฐ€ string์œผ๋กœ ๋ณ€ํ™˜๋˜์–ด ๋ฒ„๋ฆฐ๋‹ค.
type RoutesWithParams<T> = T extends `/${string}/:id` ? T : never;

// ์˜๋„: "/users/:id" | "/posts/:id"
// ์‹ค์ œ ๊ฒฐ๊ณผ: string
// ์™œ? ("users" extends `...`) | ("/users/:id" extends `...`) | ... ๋กœ ๋ถ„๋ฐฐ๋˜์–ด
// ์˜๋„์™€ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋ฉฐ ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
type DynamicRoutes = RoutesWithParams<Routes>;

๐Ÿ˜Š Good: []๋กœ ๋ถ„๋ฐฐ ๋ฐฉ์ง€ํ•˜๊ธฐ

์œ ๋‹ˆ์˜จ ํƒ€์ž… ์ž์ฒด๋ฅผ ํ•˜๋‚˜์˜ ๋‹จ์œ„๋กœ ๊ฒ€์‚ฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ํƒ€์ž…์„ ๋Œ€๊ด„ํ˜ธ([])๋กœ ๊ฐ์‹ธ ํŠœํ”Œ๋กœ ๋งŒ๋“ค์–ด ๋ถ„๋ฐฐ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// Good: [T] extends [U] ํ˜•ํƒœ๋กœ ๊ฐ์‹ธ ๋ถ„๋ฐฐ๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค.
type RoutesWithParams<T> = [T] extends [`/${string}/:id`] ? T : never;

// ์ด์ œ ์œ ๋‹ˆ์˜จ ์ „์ฒด๊ฐ€ ํ•˜๋‚˜์˜ ๋‹จ์œ„๋กœ ์ทจ๊ธ‰๋˜์–ด ์˜๋„๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค.
// ์ด๋Ÿฐ ๊ฒฝ์šฐ์—” ๋‹ค๋ฅธ ์ ‘๊ทผ์ด ํ•„์š”ํ•˜์ง€๋งŒ, ๋ถ„๋ฐฐ ๋ฐฉ์ง€ ์›๋ฆฌ๋Š” ๋™์ผํ•˜๋‹ค.

// ๋” ์ ์ ˆํ•œ ๋ถ„๋ฐฐ ๋ฐฉ์ง€ ์˜ˆ์‹œ
type Wrap<T> = [T] extends [any] ? T[] : T;
type T1 = Wrap<string | number>; // ๊ฒฐ๊ณผ: (string | number)[] -> ๋ถ„๋ฐฐ๋˜์ง€ ์•Š์Œ

๋ถ„๋ฐฐ ๋ฒ•์น™์„ ์ดํ•ดํ•˜๊ณ  ์ œ์–ดํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ๋ณต์žกํ•œ ํƒ€์ž…์˜ ์—ฐ์‚ฐ ํšŸ์ˆ˜๋ฅผ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค. ์žฌ๊ท€ ํƒ€์ž…(Recursive Types)์˜ ๋ฌดํ•œ ๋ฃจํ”„

์ž๊ธฐ ์ž์‹ ์„ ์ฐธ์กฐํ•˜๋Š” ์žฌ๊ท€ ํƒ€์ž…์€ ๋งค์šฐ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ์ข…๋ฃŒ ์กฐ๊ฑด์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š์œผ๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ๋ฌดํ•œ ๋ฃจํ”„์— ๋น ๋œจ๋ ค "Type instantiation is excessively deep and possibly infinite." ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

๐Ÿ˜ฉ Bad: ์ข…๋ฃŒ ์กฐ๊ฑด ์—†๋Š” ๋ฌดํ•œ ์žฌ๊ท€

// Bad: ๊นŠ์ด๊ฐ€ ๊นŠ์–ด์ง€๋ฉด ๋ฌดํ•œ ๋ฃจํ”„์— ๋น ์งˆ ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…
type DeepFlatten<T> = T extends object ? DeepFlatten<T[keyof T]> : T;

๐Ÿ˜Š Good: ์žฌ๊ท€ ๊นŠ์ด ์ œํ•œ ์žฅ์น˜ ์ถ”๊ฐ€ํ•˜๊ธฐ

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

// Good: ์žฌ๊ท€ ๊นŠ์ด๋ฅผ ์ถ”์ ํ•˜๋Š” Depth ํŒŒ๋ผ๋ฏธํ„ฐ ์ถ”๊ฐ€
type DeepFlatten<T, Depth extends any[] = []> = Depth['length'] extends 10 // ์ตœ๋Œ€ ๊นŠ์ด 10์œผ๋กœ ์ œํ•œ
  ? T
  : T extends object
  ? DeepFlatten<T[keyof T], [...Depth, any]>
  : T;

3. ๋ฐฉ์–ด์„  ๊ตฌ์ถ•: tsconfig.json๊ณผ ํ”„๋กœ์ ํŠธ ์„ค์ •

๋ณต์žกํ•œ ํƒ€์ž…์„ ์ˆ˜์ •ํ•˜๊ธฐ ์ „์—, ๊ฐ„๋‹จํ•œ ์„ค์ • ๋ณ€๊ฒฝ๋งŒ์œผ๋กœ๋„ ํฐ ํšจ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ€. incremental: true

์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋งˆ์ง€๋ง‰ ์ปดํŒŒ์ผ ์ƒํƒœ๋ฅผ .tsbuildinfo ํŒŒ์ผ์— ์ €์žฅํ•ด๋‘๊ณ , ๋‹ค์Œ ์ปดํŒŒ์ผ ์‹œ ๋ณ€๊ฒฝ๋œ ํŒŒ์ผ๋งŒ ๋‹ค์‹œ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ ํ•„์ˆ˜์ ์ธ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

// tsconfig.json
{
  "compilerOptions": {
    "incremental": true
  }
}

๋‚˜. skipLibCheck: true

node_modules์— ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์˜ ํƒ€์ž… ์„ ์–ธ ํŒŒ์ผ(.d.ts)์— ๋Œ€ํ•œ ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํƒ€์ž…์€ ์ด๋ฏธ ๊ฒ€์ฆ๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์—ฌ ์ „์ฒด ์ปดํŒŒ์ผ ์‹œ๊ฐ„์„ ํฌ๊ฒŒ ๋‹จ์ถ•์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// tsconfig.json
{
  "compilerOptions": {
    "skipLibCheck": true
  }
}

๋‹ค. ํ”„๋กœ์ ํŠธ ๋ถ„๋ฆฌ๋ฅผ ํ†ตํ•œ ํšจ๊ณผ์ ์ธ ๊ด€๋ฆฌ (references)

๊ฑฐ๋Œ€ํ•œ ๋ชจ๋…ธ๋ ˆํฌ(Monorepo) ํ”„๋กœ์ ํŠธ์˜ ๊ฒฝ์šฐ, TypeScript์˜ ํ”„๋กœ์ ํŠธ ๋ ˆํผ๋Ÿฐ์Šค(Project References) ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์€ ํ•˜์œ„ ํ”„๋กœ์ ํŠธ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด tsc --build ๋ช…๋ น์„ ํ†ตํ•ด ๋ณ€๊ฒฝ๋œ ํ•˜์œ„ ํ”„๋กœ์ ํŠธ์™€ ๊ทธ์— ์˜์กดํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋งŒ ์ง€๋Šฅ์ ์œผ๋กœ ์žฌ๋นŒ๋“œํ•˜์—ฌ ์ „์ฒด ๋นŒ๋“œ ์‹œ๊ฐ„์„ ํš๊ธฐ์ ์œผ๋กœ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๊ฒฐ๋ก : ์„ฑ๋Šฅ์€ ์ง€์†์ ์ธ ๊ด€์‹ฌ์˜ ๋Œ€์ƒ

TypeScript ์ปดํŒŒ์ผ ์„ฑ๋Šฅ์€ ํ•œ๋ฒˆ ํ•ด๊ฒฐํ•˜๊ณ  ๋๋‚˜๋Š” ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ, ํ”„๋กœ์ ํŠธ๊ฐ€ ์„ฑ์žฅํ•จ์— ๋”ฐ๋ผ ์ง€์†์ ์œผ๋กœ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๋Œ€์ƒ์ž…๋‹ˆ๋‹ค.

๋А๋ฆฐ ์ปดํŒŒ์ผ ์†๋„๋กœ ๊ณ ํ†ต๋ฐ›๊ณ  ์žˆ๋‹ค๋ฉด, ๋‹ค์Œ์˜ ์ฒดํฌ๋ฆฌ์ŠคํŠธ๋ฅผ ๋”ฐ๋ผ ํ”„๋กœ์ ํŠธ๋ฅผ ์ ๊ฒ€ํ•ด ๋ณด์„ธ์š”.

  • โœ… ๊ฑฐ๋Œ€ ์œ ๋‹ˆ์˜จ์— Mapped Type์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง„ ์•Š์€๊ฐ€? -> ์ œ๋„ค๋ฆญ์œผ๋กœ ์ง€์—ฐ์‹œํ‚ค์„ธ์š”.
  • โœ… Conditional Type์ด ์˜๋„์น˜ ์•Š๊ฒŒ ๋ถ„๋ฐฐ๋˜์–ด ๋ณต์žกํ•œ ์—ฐ์‚ฐ์„ ์œ ๋ฐœํ•˜๋Š”๊ฐ€? -> [T]๋กœ ๊ฐ์‹ธ ๋ถ„๋ฐฐ๋ฅผ ๋ฐฉ์ง€ํ•˜์„ธ์š”.
  • โœ… ์ข…๋ฃŒ ์กฐ๊ฑด์ด ๋ถˆ๋ถ„๋ช…ํ•œ Recursive Type์ด ์žˆ๋Š”๊ฐ€? -> ์žฌ๊ท€ ๊นŠ์ด ์ œํ•œ ์žฅ์น˜๋ฅผ ์ถ”๊ฐ€ํ•˜์„ธ์š”.
  • โœ… tsconfig.json์— "incremental": true ์™€ "skipLibCheck": true ๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ๋Š”๊ฐ€?
  • โœ… ๋ชจ๋…ธ๋ ˆํฌ๋ผ๋ฉด ํ”„๋กœ์ ํŠธ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ํ™œ์šฉํ•ด ํ”„๋กœ์ ํŠธ๋ฅผ ๋ถ„๋ฆฌํ–ˆ๋Š”๊ฐ€?

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