TypeScriptλ₯Ό μ¬μ©νμ¬ μν°νλΌμ΄μ¦ μ ν리μΌμ΄μ μμ μ°Έμ‘° λ°μ΄ν°λ₯Ό ν¨κ³Όμ μΌλ‘ κ΄λ¦¬νλ λ°©λ²μ λ°°μλλ€. μ΄ ν¬κ΄μ μΈ κ°μ΄λμμλ λ°μ΄ν° λ¬΄κ²°μ± λ° νμ μμ μ μν enum, const assertions, κ³ κΈ ν¨ν΄μ λ€λ£Ήλλ€.
TypeScript λ§μ€ν° λ°μ΄ν° κ΄λ¦¬: μ°Έμ‘° λ°μ΄ν° νμ ꡬν κ°μ΄λ
볡μ‘ν μν°νλΌμ΄μ¦ μννΈμ¨μ΄ κ°λ° μΈκ³μμ λ°μ΄ν°λ λͺ¨λ μ ν리μΌμ΄μ μ μλͺ μ μ λλ€. μ΄ λ°μ΄ν°λ₯Ό κ΄λ¦¬, μ μ₯ λ° νμ©νλ λ°©λ²μ μμ€ν μ κ²¬κ³ μ±, μ μ§ κ΄λ¦¬ μ©μ΄μ± λ° νμ₯μ±μ μ§μ μ μΈ μν₯μ λ―ΈμΉ©λλ€. μ΄ λ°μ΄ν°μ μ€μν νμ μ§ν©μ λΉμ¦λμ€μ ν΅μ¬μ μΈ λΉκ±°λμ  μν°ν°μΈ λ§μ€ν° λ°μ΄ν°μ λλ€. μ΄ μμ λ΄μμ μ°Έμ‘° λ°μ΄ν°λ κΈ°μ΄μ μΈ κΈ°λ₯μΌλ‘ λλλ¬μ§λλ€. μ΄ κΈ°μ¬λ κ°λ°μμ μ€κ³μκ° TypeScriptλ₯Ό μ¬μ©νμ¬ μ°Έμ‘° λ°μ΄ν° μ νμ ꡬννκ³ κ΄λ¦¬νλ λ°©λ²μ λν ν¬κ΄μ μΈ κ°μ΄λλ₯Ό μ 곡νμ¬ μΌλ°μ μΈ λ²κ·Έ λ° λΆμΌμΉ μμ€λ₯Ό νμ μμ  λ¬΄κ²°μ±μ μμλ‘ λ³νν©λλ€.
νλ μ ν리μΌμ΄μ μμ μ°Έμ‘° λ°μ΄ν° κ΄λ¦¬κ° μ€μν μ΄μ
μ½λμ λ°μ΄λ€κΈ° μ μ ν΅μ¬ κ°λ μ λν λͺ νν μ΄ν΄λ₯Ό νλ¦½ν΄ λ³΄κ² μ΅λλ€.
λ§μ€ν° λ°μ΄ν° κ΄λ¦¬(MDM)λ λΉμ¦λμ€μ ITκ° νλ ₯νμ¬ μν°νλΌμ΄μ¦μ 곡μ 곡μ λ§μ€ν° λ°μ΄ν° μμ°μ κ· μΌμ±, μ νμ±, κ΄λ¦¬, μλ―Έλ‘ μ  μΌκ΄μ± λ° μ± μμ 보μ₯νλ κΈ°μ μ§μ λΆμΌμ λλ€. λ§μ€ν° λ°μ΄ν°λ κ³ κ°, μ ν, μ§μ λ° μμΉμ κ°μ λΉμ¦λμ€μ 'λͺ μ¬'λ₯Ό λνλ λλ€.
μ°Έμ‘° λ°μ΄ν°λ λ€λ₯Έ λ°μ΄ν°λ₯Ό λΆλ₯νκ±°λ λ²μ£Όννλ λ° μ¬μ©λλ νΉμ  μ νμ λ§μ€ν° λ°μ΄ν°μ λλ€. μΌλ°μ μΌλ‘ μ μ μ΄κ±°λ μκ°μ΄ μ§λ¨μ λ°λΌ λ§€μ° λλ¦¬κ² λ³κ²½λ©λλ€. νΉμ  νλκ° κ°μ§ μ μλ 미리 μ μλ κ° μ§ν©μ΄λΌκ³ μκ°νμμμ€. μ  μΈκ³μ μΌλ°μ μΈ μλ λ€μκ³Ό κ°μ΅λλ€.
- κ΅κ° λͺ©λ‘(μ: λ―Έκ΅, λ μΌ, μΌλ³Έ)
 - ν΅ν μ½λ(USD, EUR, JPY)
 - μ£Όλ¬Έ μν(보λ₯ μ€, μ²λ¦¬ μ€, λ°°μ‘λ¨, λ°°λ¬λ¨, μ·¨μλ¨)
 - μ¬μ©μ μν (κ΄λ¦¬μ, νΈμ§μ, λ·°μ΄)
 - μ ν μΉ΄ν κ³ λ¦¬(μ μ μ ν, μλ₯, μμ )
 
μ°Έμ‘° λ°μ΄ν°μ λ¬Έμ λ 볡μ‘μ±μ΄ μλλΌ λ리 νΌμ Έ μλ€λ κ²μ λλ€. λ°μ΄ν°λ² μ΄μ€, API νμ΄λ‘λ, λΉμ¦λμ€ λ‘μ§ λ° μ¬μ©μ μΈν°νμ΄μ€ λ± λͺ¨λ κ³³μ λνλ©λλ€. μ λλ‘ κ΄λ¦¬νμ§ λͺ»νλ©΄ λ°μ΄ν° λΆμΌμΉ, λ°νμ μ€λ₯, μ μ§ κ΄λ¦¬ λ° λ¦¬ν©ν°λ§νκΈ° μ΄λ €μ΄ μ½λλ² μ΄μ€μ κ°μ λ¬Έμ κ° λ°μν©λλ€. κ°λ ₯ν μ μ  νμ΄ν μμ€ν μ κ°μΆ TypeScriptλ κ°λ° λ¨κ³μμ λ°μ΄ν° κ±°λ²λμ€λ₯Ό μννλ λ° μμ΄μλ μ λ λκ΅¬κ° λ©λλ€.
ν΅μ¬ λ¬Έμ : "λ§€μ§ μ€νΈλ§"μ μνμ±
μΌλ°μ μΈ μλ리μ€μΈ κ΅μ  μ μ μκ±°λ νλ«νΌμΌλ‘ λ¬Έμ λ₯Ό μ€λͺ ν΄ λ³΄κ² μ΅λλ€. μμ€ν μ μ£Όλ¬Έ μνλ₯Ό μΆμ ν΄μΌ ν©λλ€. μμ§ν ꡬνμ μ½λμμ μμ λ¬Έμμ΄μ μ§μ  μ¬μ©νλ κ²μ ν¬ν¨ν μ μμ΅λλ€.
            
function processOrder(orderId: number, newStatus: string) {
  if (newStatus === 'shipped') {
    // Logic for shipping
    console.log(`Order ${orderId} has been shipped.`);
  } else if (newStatus === 'delivered') {
    // Logic for delivery confirmation
    console.log(`Order ${orderId} confirmed as delivered.`);
  } else if (newStatus === 'pending') {
    // ...and so on
  }
}
// Somewhere else in the application...
processOrder(12345, 'Shipped'); // Uh oh, a typo!
            
          
        μ’ μ’ "λ§€μ§ μ€νΈλ§"μ΄λΌκ³ λΆλ¦¬λ κ²μ μμ‘΄νλ μ΄ μ κ·Ό λ°©μμ μνμΌλ‘ κ°λ μ°¨ μμ΅λλ€.
- μ€ν: μμμ λ³Ό μ μλ―μ΄ `shipped` λ `Shipped`λ κ°μ§νκΈ° μ΄λ €μ΄ λ―Έλ¬ν λ²κ·Έλ₯Ό μΌμΌν¬ μ μμ΅λλ€. μ»΄νμΌλ¬λ λμμ μ 곡νμ§ μμ΅λλ€.
 - λ°κ²¬ κ°λ₯μ± λΆμ‘±: μλ‘μ΄ κ°λ°μλ μ ν¨ν μνκ° λ¬΄μμΈμ§ μ½κ² μ μ μμ΅λλ€. κ°λ₯ν λͺ¨λ λ¬Έμμ΄ κ°μ μ°ΎκΈ° μν΄ μ 체 μ½λλ² μ΄μ€λ₯Ό κ²μν΄μΌ ν©λλ€.
 - μ μ§ κ΄λ¦¬ μ λͺ½: λΉμ¦λμ€μμ 'shipped'λ₯Ό 'dispatched'λ‘ λ³κ²½νκΈ°λ‘ κ²°μ νλ©΄ μ΄λ»κ² λ κΉμ? μΈμ€ν΄μ€λ₯Ό λμΉκ±°λ μ€μλ‘ κ΄λ ¨ μλ νλͺ©μ λ³κ²½νμ§ μλλ‘ μνν νλ‘μ νΈ μ 체 κ²μ λ° λ°κΎΈκΈ°λ₯Ό μνν΄μΌ ν©λλ€.
 - λ¨μΌ μμ€ μ§μ€ μμ: μ ν¨ν κ°μ μ ν리μΌμ΄μ  μ 체μ ν©μ΄μ Έ μμ΄ νλ°νΈμλ, λ°±μλ λ° λ°μ΄ν°λ² μ΄μ€ κ°μ μ μ¬μ μΈ λΆμΌμΉκ° λ°μν©λλ€.
 
μ°λ¦¬μ λͺ©νλ μ°Έμ‘° λ°μ΄ν°μ λν λ¨μΌν κΆμ μλ μμ€λ₯Ό λ§λ€κ³ TypeScriptμ νμ μμ€ν μ νμ©νμ¬ μ¬λ°λ₯Έ μ¬μ©λ²μ λͺ¨λ κ³³μμ μ μ©νμ¬ μ΄λ¬ν λ¬Έμ λ₯Ό μ κ±°νλ κ²μ λλ€.
μ°Έμ‘° λ°μ΄ν°λ₯Ό μν κΈ°λ³Έμ μΈ TypeScript ν¨ν΄
TypeScriptλ μ°Έμ‘° λ°μ΄ν°λ₯Ό κ΄λ¦¬νκΈ° μν μ¬λ¬ κ°μ§ νλ₯ν ν¨ν΄μ μ 곡νλ©°, κ° ν¨ν΄μλ κ³ μ ν μ₯λ¨μ μ΄ μμ΅λλ€. κ³ μ μ μΈ κ²λΆν° νλμ μΈ λͺ¨λ² μ¬λ‘κΉμ§ κ°μ₯ μΌλ°μ μΈ ν¨ν΄μ μ΄ν΄λ³΄κ² μ΅λλ€.
μ κ·Ό λ°©μ 1: κ³ μ μ μΈ `enum`
Java λλ C#κ³Ό κ°μ μΈμ΄μμ μ¨ λ§μ κ°λ°μμκ² `enum`μ μ΄ μμ μ κ°μ₯ μ΅μν λꡬμ λλ€. μ΄λ₯Ό ν΅ν΄ λͺ λͺ λ μμ μ§ν©μ μ μν μ μμ΅λλ€.
            
export enum OrderStatus {
  Pending = 'PENDING',
  Processing = 'PROCESSING',
  Shipped = 'SHIPPED',
  Delivered = 'DELIVERED',
  Cancelled = 'CANCELLED',
}
function processOrder(orderId: number, newStatus: OrderStatus) {
  if (newStatus === OrderStatus.Shipped) {
    console.log(`Order ${orderId} has been shipped.`);
  }
}
processOrder(123, OrderStatus.Shipped); // Correct and type-safe
// processOrder(123, 'SHIPPED'); // Compile-time error! Great!
            
          
        μ₯μ :
- λͺ νν μλ: κ΄λ ¨ μμ μ§ν©μ μ μνκ³ μμμ λͺ μμ μΌλ‘ λνλ λλ€. `OrderStatus` μ΄λ¦μ λ§€μ° μ€λͺ μ μ λλ€.
 - λͺ λͺ© νμ΄ν: `OrderStatus.Shipped`λ λ¨μν λ¬Έμμ΄ 'SHIPPED'κ° μλλλ€. `OrderStatus` μ νμ λλ€. μ΄λ μΌλΆ μλ리μ€μμ λ κ°λ ₯ν νμ κ²μ¬λ₯Ό μ 곡ν μ μμ΅λλ€.
 - κ°λ μ±: `OrderStatus.Shipped`λ μ’ μ’ μμ λ¬Έμμ΄λ³΄λ€ λ μ½κΈ° μ¬μ΄ κ²μΌλ‘ κ°μ£Όλ©λλ€.
 
λ¨μ :
- JavaScript ννλ¦°νΈ: TypeScript enumsλ λ¨μν μ»΄νμΌ μκ° κ΅¬μ± μμκ° μλλλ€. μ»΄νμΌλ μΆλ ₯μμ JavaScript κ°μ²΄(μ¦μ νΈμΆ ν¨μ ννμ λλ IIFE)λ₯Ό μμ±νμ¬ λ²λ€ ν¬κΈ°λ₯Ό λ립λλ€.
 - μ«μ Enumsμ 볡μ‘μ±: μ¬κΈ°μ λ¬Έμμ΄ enumsλ₯Ό μ¬μ©νμ§λ§(κΆμ₯λλ λ°©λ²) TypeScriptμ κΈ°λ³Έ μ«μ enumsλ νΌλμ€λ¬μ΄ μλ§€ν λμμ κ°μ§ μ μμ΅λλ€.
 - λ μ μ°ν¨: μΆκ° μμ μμ΄ enumsμμ μ λμ¨ νμ μ νμνκ±°λ λ 볡μ‘ν λ°μ΄ν° ꡬ쑰μ μ¬μ©νλ κ²μ΄ λ μ΄λ ΅μ΅λλ€.
 
μ κ·Ό λ°©μ 2: κ²½λ λ¬Έμμ΄ λ¦¬ν°λ΄ μ λμ¨
λ κ°λ³κ³ μμνκ² νμ μμ€ μ κ·Ό λ°©μμ λ¬Έμμ΄ λ¦¬ν°λ΄μ μ λμ¨μ μ¬μ©νλ κ²μ λλ€. μ΄ ν¨ν΄μ νΉμ  λ¬Έμμ΄ μ§ν© μ€ νλλ§ λ μ μλ νμ μ μ μν©λλ€.
            
export type OrderStatus =
  | 'PENDING'
  | 'PROCESSING'
  | 'SHIPPED'
  | 'DELIVERED'
  | 'CANCELLED';
function processOrder(orderId: number, newStatus: OrderStatus) {
  if (newStatus === 'SHIPPED') {
    console.log(`Order ${orderId} has been shipped.`);
  }
}
processOrder(123, 'SHIPPED'); // Correct and type-safe
// processOrder(123, 'shipped'); // Compile-time error! Awesome!
            
          
        μ₯μ :
- μ λ‘ JavaScript ννλ¦°νΈ: `type` μ μλ μ»΄νμΌ μ€μ μμ ν μ§μμ§λλ€. TypeScript μ»΄νμΌλ¬μλ§ μ‘΄μ¬νλ―λ‘ λ κΉ¨λνκ³ μμ JavaScriptκ° μμ±λ©λλ€.
 - λ¨μμ±: ꡬ문μ κ°λ¨νκ³ μ΄ν΄νκΈ° μ½μ΅λλ€.
 - λ°μ΄λ μλ μμ±: μ½λ νΈμ§κΈ°λ μ΄ νμ μ λ³μμ λν΄ λ°μ΄λ μλ μμ±μ μ 곡ν©λλ€.
 
λ¨μ :
- λ°νμ μν°ν©νΈ μμ: μ΄λ μ₯μ μ΄μ λ¨μ μ λλ€. νμ μΌ λΏμ΄λ―λ‘ λ°νμμ κ°λ₯ν κ°μ λ°λ³΅ν μ μμ΅λλ€(μ: λλ‘λ€μ΄ λ©λ΄λ₯Ό μ±μ°κΈ° μν΄). λ³λμ μμ λ°°μ΄μ μ μν΄μΌ νλ―λ‘ μ λ³΄κ° μ€λ³΅λ©λλ€.
 
            
// Duplication of values
export type OrderStatus = 'PENDING' | 'PROCESSING' | 'SHIPPED';
export const ALL_ORDER_STATUSES = ['PENDING', 'PROCESSING', 'SHIPPED'];
            
          
        μ΄λ¬ν μ€λ³΅μ DRY(Don't Repeat Yourself) μμΉμ λͺ λ°±ν μλ°νλ κ²μ΄λ©° νμ κ³Ό λ°°μ΄μ΄ λκΈ°νλμ§ μμΌλ©΄ μ μ¬μ μΈ λ²κ·Έμ μμΈμ΄ λ©λλ€. μ΄λ‘ μΈν΄ νλμ μ΄κ³ μ νΈλλ μ κ·Ό λ°©μμΌλ‘ μ΄μ΄μ§λλ€.
μ κ·Ό λ°©μ 3: `const` μ΄μ€μ  νμ νλ μ΄(골λ μ€ν λ€λ)
TypeScript 3.4μ λμ λ `as const` μ΄μ€μ μ μλ²½ν μ루μ μ μ 곡ν©λλ€. λ°νμμ μ‘΄μ¬νλ λ¨μΌ μμ€ μ§μ€κ³Ό μ»΄νμΌ μκ°μ μ‘΄μ¬νλ μλ²½νκ² νμ μ΄ μ§μ λ νμ μ λμ¨μ΄λΌλ λ κ°μ§ μ₯μ μ κ²°ν©ν©λλ€.
ν¨ν΄μ λ€μκ³Ό κ°μ΅λλ€.
            
// 1. Define the runtime data with 'as const'
export const ORDER_STATUSES = [
  'PENDING',
  'PROCESSING',
  'SHIPPED',
  'DELIVERED',
  'CANCELLED',
] as const;
// 2. Derive the type from the runtime data
export type OrderStatus = typeof ORDER_STATUSES[number];
//   ^? type OrderStatus = "PENDING" | "PROCESSING" | "SHIPPED" | "DELIVERED" | "CANCELLED"
// 3. Use it in your functions
function processOrder(orderId: number, newStatus: OrderStatus) {
  if (newStatus === 'SHIPPED') {
    console.log(`Order ${orderId} has been shipped.`);
  }
}
// 4. Use it at runtime AND compile time
processOrder(123, 'SHIPPED'); // Type-safe!
// And you can easily iterate over it for UIs!
function getStatusOptions() {
  return ORDER_STATUSES.map(status => ({ value: status, label: status.toLowerCase() }));
}
            
          
        μ΄κ²μ΄ μ κ·Έλ κ² κ°λ ₯νμ§ λΆμν΄ λ³΄κ² μ΅λλ€.
- `as const`λ TypeScriptμκ² κ°λ₯ν κ°μ₯ ꡬ체μ μΈ νμ μ μΆλ‘ νλλ‘ μ§μν©λλ€. `string[]` λμ νμ μ `readonly ['PENDING', 'PROCESSING', ...]`λ‘ μΆλ‘ ν©λλ€. `readonly` μμ μλ λ°°μ΄μ μ°λ°μ μΈ μμ μ λ°©μ§ν©λλ€.
 - `typeof ORDER_STATUSES[number]`λ νμ μ νμμν€λ λ§λ²μ λλ€. μ΄λ "`ORDER_STATUSES` λ°°μ΄ λ΄λΆ μμμ νμ μ μλ €μ£ΌμΈμ"λΌκ³ λ§ν©λλ€. TypeScriptλ νΉμ  λ¬Έμμ΄ λ¦¬ν°λ΄μ λ³Ό λ§νΌ λλνκ³ μ΄λ₯Ό ν΅ν΄ μ λμ¨ νμ μ λ§λλλ€.
 - λ¨μΌ μμ€ μ§μ€(SSOT): `ORDER_STATUSES` λ°°μ΄μ μ΄λ¬ν κ°μ΄ μ μλ μ μΌν μ₯μμ λλ€. νμ μ μλμΌλ‘ νμλ©λλ€. λ°°μ΄μ μ μνλ₯Ό μΆκ°νλ©΄ `OrderStatus` νμ μ΄ μλμΌλ‘ μ λ°μ΄νΈλ©λλ€. μ΄λ₯Ό ν΅ν΄ νμ κ³Ό λ°νμ κ°μ΄ λκΈ°νλμ§ μμ κ°λ₯μ±μ μ κ±°ν©λλ€.
 
μ΄ ν¨ν΄μ TypeScriptμμ κ°λ¨ν μ°Έμ‘° λ°μ΄ν°λ₯Ό μ²λ¦¬νλ νλμ μ΄κ³ κ΄μ©μ μ΄λ©° κ°λ ₯ν λ°©λ²μ λλ€.
κ³ κΈ κ΅¬ν: 볡μ‘ν μ°Έμ‘° λ°μ΄ν° ꡬ쑰ν
μ°Έμ‘° λ°μ΄ν°λ μ’ μ’ λ¨μν λ¬Έμμ΄ λͺ©λ‘λ³΄λ€ λ 볡μ‘ν©λλ€. λ°°μ‘ μμμ λν κ΅κ° λͺ©λ‘μ κ΄λ¦¬νλ κ²μ κ³ λ €νμμμ€. κ° κ΅κ°μλ μ΄λ¦, λ κΈμ ISO μ½λ λ° μ ν μ μ μ½λκ° μμ΅λλ€. `as const` ν¨ν΄μ μ΄λ₯Ό μν΄ μλ¦λ΅κ² νμ₯λ©λλ€.
λ°μ΄ν° 컬λ μ  μ μ λ° μ μ₯
λ¨Όμ  λ¨μΌ μμ€ μ§μ€μΈ κ°μ²΄ λ°°μ΄μ λ§λλλ€. `as const`λ₯Ό μ μ©νμ¬ μ 체 ꡬ쑰λ₯Ό κΉμ΄ μ½κΈ° μ μ©μΌλ‘ λ§λ€κ³ μ νν νμ μΆλ‘ μ νμ©ν©λλ€.
            
export const COUNTRIES = [
  {
    code: 'US',
    name: 'United States of America',
    dial: '+1',
    continent: 'North America',
  },
  {
    code: 'DE',
    name: 'Germany',
    dial: '+49',
    continent: 'Europe',
  },
  {
    code: 'IN',
    name: 'India',
    dial: '+91',
    continent: 'Asia',
  },
  {
    code: 'BR',
    name: 'Brazil',
    dial: '+55',
    continent: 'South America',
  },
] as const;
            
          
        컬λ μ μμ μ νν νμ νμ
μ΄μ  μ΄ λ°μ΄ν° ꡬ쑰μμ μ§μ  λ§€μ° μ μ©νκ³ κ΅¬μ²΄μ μΈ νμ μ νμν μ μμ΅λλ€.
            
// Derive the type for a single country object
export type Country = typeof COUNTRIES[number];
/*
  ^? type Country = {
      readonly code: "US";
      readonly name: "United States of America";
      readonly dial: "+1";
      readonly continent: "North America";
  } | {
      readonly code: "DE";
      ...
  }
*/
// Derive a union type of all valid country codes
export type CountryCode = Country['code']; // or `typeof COUNTRIES[number]['code']`
//   ^? type CountryCode = "US" | "DE" | "IN" | "BR"
// Derive a union type of all continents
export type Continent = Country['continent'];
//   ^? type Continent = "North America" | "Europe" | "Asia" | "South America"
            
          
        μ΄κ²μ λ§€μ° κ°λ ₯ν©λλ€. λ¨ ν μ€μ μ€λ³΅ νμ μ μλ₯Ό μμ±νμ§ μκ³ λ€μμ λ§λ€μμ΅λλ€.
- κ΅κ° κ°μ²΄μ λͺ¨μμ λνλ΄λ `Country` νμ
 - λ³μ λλ ν¨μ λ§€κ°λ³μκ° μ ν¨νκ³ μ‘΄μ¬νλ κ΅κ° μ½λ μ€ νλλ§ λ μ μλλ‘ νλ `CountryCode` νμ
 - κ΅κ°λ₯Ό λΆλ₯νλ `Continent` νμ
 
`COUNTRIES` λ°°μ΄μ μ κ΅κ°λ₯Ό μΆκ°νλ©΄ μ΄λ¬ν λͺ¨λ νμ μ΄ μλμΌλ‘ μ λ°μ΄νΈλ©λλ€. μ΄λ μ»΄νμΌλ¬μ μν΄ μνλλ λ°μ΄ν° 무결μ±μ λλ€.
μ€μ μ§μ€μ μ°Έμ‘° λ°μ΄ν° μλΉμ€ ꡬμΆ
μ ν리μΌμ΄μ μ΄ μ»€μ§μ λ°λΌ μ΄ μ°Έμ‘° λ°μ΄ν°μ λν μ‘μΈμ€λ₯Ό μ€μ μ§μ€ννλ κ²μ΄ κ°μ₯ μ’μ΅λλ€. μ΄λ κ°λ¨ν λͺ¨λ λλ λ 곡μμ μΈ μλΉμ€ ν΄λμ€λ₯Ό ν΅ν΄ μνν μ μμΌλ©°, μ’ μ’ μ±κΈν€ ν¨ν΄μ μ¬μ©νμ¬ μ ν리μΌμ΄μ  μ 체μμ λ¨μΌ μΈμ€ν΄μ€λ₯Ό 보μ₯ν©λλ€.
λͺ¨λ κΈ°λ° μ κ·Ό λ°©μ
λλΆλΆμ μ ν리μΌμ΄μ μμ λ°μ΄ν°μ μΌλΆ μ νΈλ¦¬ν° ν¨μλ₯Ό λ΄λ³΄λ΄λ κ°λ¨ν λͺ¨λμ΄ μΆ©λΆνκ³ μ°μν©λλ€.
            
// file: src/services/referenceData.ts
// ... (our COUNTRIES constant and derived types from above)
export const getCountries = () => COUNTRIES;
export const getCountryByCode = (code: CountryCode): Country | undefined => {
  // The 'find' method is perfectly type-safe here
  return COUNTRIES.find(country => country.code === code);
};
export const getCountriesByContinent = (continent: Continent): Country[] => {
  return COUNTRIES.filter(country => country.continent === continent);
};
// You can also export the raw data and types if needed
export { COUNTRIES, Country, CountryCode, Continent };
            
          
        μ΄ μ κ·Ό λ°©μμ κΉλνκ³ ν μ€νΈ κ°λ₯νλ©° ES λͺ¨λμ νμ©νμ¬ μμ°μ€λ¬μ΄ μ±κΈν€κ³Ό κ°μ λμμ μ 곡ν©λλ€. μ ν리μΌμ΄μ μ λͺ¨λ λΆλΆμμ μ΄λ¬ν ν¨μλ₯Ό κ°μ Έμ μ°Έμ‘° λ°μ΄ν°μ λν μΌκ΄λκ³ νμ μμ ν μ‘μΈμ€λ₯Ό μ»μ μ μμ΅λλ€.
λΉλκΈ°μ μΌλ‘ λ‘λλ μ°Έμ‘° λ°μ΄ν° μ²λ¦¬
λ§μ μ€μ  μν°νλΌμ΄μ¦ μμ€ν μμ μ°Έμ‘° λ°μ΄ν°λ νλ°νΈμλμ νλ μ½λ©λμ§ μμ΅λλ€. λͺ¨λ ν΄λΌμ΄μΈνΈμμ νμ μ΅μ μνλ₯Ό μ μ§νκΈ° μν΄ λ°±μλ APIμμ κ°μ Έμ΅λλ€. TypeScript ν¨ν΄μ μ΄λ₯Ό μμ©ν΄μΌ ν©λλ€.
ν΅μ¬μ μμλλ API μλ΅κ³Ό μΌμΉνλλ‘ ν΄λΌμ΄μΈνΈ μΈ‘μμ νμ μ μ μνλ κ²μ λλ€. κ·Έλ° λ€μ Zod λλ io-tsμ κ°μ λ°νμ μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ API μλ΅μ΄ μ€μ λ‘ λ°νμμ νμ κ³Ό μΌμΉνλμ§ νμΈνμ¬ APIμ λμ  νΉμ±κ³Ό TypeScriptμ μ μ  μΈκ³ μ¬μ΄μ κ°κ²©μ μ’ν μ μμ΅λλ€.
            
import { z } from 'zod';
// 1. Define the schema for a single country using Zod
const CountrySchema = z.object({
  code: z.string().length(2),
  name: z.string(),
  dial: z.string(),
  continent: z.string(),
});
// 2. Define the schema for the API response (an array of countries)
const CountriesApiResponseSchema = z.array(CountrySchema);
// 3. Infer the TypeScript type from the Zod schema
export type Country = z.infer;
// We can still get a code type, but it will be 'string' since we don't know the values ahead of time.
// If the list is small and fixed, you can use z.enum(['US', 'DE', ...]) for more specific types.
export type CountryCode = Country['code'];
// 4. A service to fetch and cache the data
class ReferenceDataService {
  private countries: Country[] | null = null;
  async fetchAndCacheCountries(): Promise {
    if (this.countries) {
      return this.countries;
    }
    const response = await fetch('/api/v1/countries');
    const jsonData = await response.json();
    // Runtime validation!
    const validationResult = CountriesApiResponseSchema.safeParse(jsonData);
    if (!validationResult.success) {
      console.error('Invalid country data from API:', validationResult.error);
      throw new Error('Failed to load reference data.');
    }
    this.countries = validationResult.data;
    return this.countries;
  }
}
export const referenceDataService = new ReferenceDataService();
  
            
          
        μ΄ μ κ·Ό λ°©μμ λ§€μ° κ°λ ₯ν©λλ€. μΆλ‘ λ TypeScript νμ μ ν΅ν΄ μ»΄νμΌ μκ° μμ μ±μ μ 곡νκ³ μΈλΆ μμ€μμ μ€λ λ°μ΄ν°κ° μμλλ λͺ¨μκ³Ό μΌμΉνλμ§ μ ν¨μ±μ κ²μ¬νμ¬ λ°νμ μμ μ±μ μ 곡ν©λλ€. μ ν리μΌμ΄μ μ μμ μ `referenceDataService.fetchAndCacheCountries()`λ₯Ό νΈμΆνμ¬ νμν λ λ°μ΄ν°λ₯Ό μ¬μ©ν μ μλλ‘ ν μ μμ΅λλ€.
μ ν리μΌμ΄μ μ μ°Έμ‘° λ°μ΄ν° ν΅ν©
κ²¬κ³ ν κΈ°λ°μ ν΅ν΄ μ΄ νμ μμ ν μ°Έμ‘° λ°μ΄ν°λ₯Ό μ ν리μΌμ΄μ  μ 체μμ μ¬μ©νλ κ²μ΄ κ°λ¨νκ³ μ°μν΄μ§λλ€.
UI μ»΄ν¬λνΈμμ (μ: React)
κ΅κ°λ₯Ό μ ννκΈ° μν λλ‘λ€μ΄ μ»΄ν¬λνΈλ₯Ό κ³ λ €νμμμ€. μμμ νμν νμ μ μ¬μ©νλ©΄ μ»΄ν¬λνΈμ propsκ° λͺ μμ μ΄κ³ μμ ν΄μ§λλ€.
            
import React from 'react';
import { COUNTRIES, CountryCode } from '../services/referenceData';
interface CountrySelectorProps {
  selectedValue: CountryCode | null;
  onChange: (newCode: CountryCode) => void;
}
export const CountrySelector: React.FC = ({ selectedValue, onChange }) => {
  return (
    
  );
};
 
            
          
        μ¬κΈ°μ TypeScriptλ `selectedValue`κ° μ ν¨ν `CountryCode`μ¬μΌ νκ³ `onChange` μ½λ°±μ΄ νμ μ ν¨ν `CountryCode`λ₯Ό μμ νλλ‘ λ³΄μ₯ν©λλ€.
λΉμ¦λμ€ λ‘μ§ λ° API λ μ΄μ΄μμ
νμ μ μ ν¨νμ§ μμ λ°μ΄ν°κ° μμ€ν μ ν΅ν΄ μ νλλ κ²μ λ°©μ§ν©λλ€. μ΄ λ°μ΄ν°μ λν΄ μλνλ λͺ¨λ ν¨μλ μΆκ°λ μμ μ±μ μ΄μ μ λ릴 μ μμ΅λλ€.
            
import { OrderStatus } from '../services/referenceData';
interface Order {
  id: string;
  status: OrderStatus;
  items: any[];
}
// This function can only be called with a valid status.
function canCancelOrder(order: Order): boolean {
  // No need to check for typos like 'pendng' or 'Procesing'
  return order.status === 'PENDING' || order.status === 'PROCESSING';
}
const myOrder: Order = { id: 'xyz', status: 'SHIPPED', items: [] };
if (canCancelOrder(myOrder)) {
  // This block is correctly (and safely) not executed.
}
            
          
        κ΅μ ν(i18n)μ κ²½μ°
μ°Έμ‘° λ°μ΄ν°λ μ’ μ’ κ΅μ νμ ν΅μ¬ κ΅¬μ± μμμ λλ€. λ°μ΄ν° λͺ¨λΈμ νμ₯νμ¬ λ²μ ν€λ₯Ό ν¬ν¨ν μ μμ΅λλ€.
            
export const ORDER_STATUSES = [
  { code: 'PENDING', i18nKey: 'orderStatus.pending' },
  { code: 'PROCESSING', i18nKey: 'orderStatus.processing' },
  { code: 'SHIPPED', i18nKey: 'orderStatus.shipped' },
] as const;
export type OrderStatusCode = typeof ORDER_STATUSES[number]['code'];
            
          
        κ·Έλ° λ€μ UI μ»΄ν¬λνΈλ `i18nKey`λ₯Ό μ¬μ©νμ¬ μ¬μ©μμ νμ¬ λ‘μΌμΌμ λν λ²μλ λ¬Έμμ΄μ μ‘°νν μ μμ§λ§ λΉμ¦λμ€ λ‘μ§μ μμ μ μ΄κ³ λ³νμ§ μλ `code`μ λν΄ κ³μ μλν©λλ€.
κ±°λ²λμ€ λ° μ μ§ κ΄λ¦¬ λͺ¨λ² μ¬λ‘
μ΄λ¬ν ν¨ν΄μ ꡬννλ κ²μ νλ₯ν μμμ΄μ§λ§ μ₯κΈ°μ μΈ μ±κ³΅μλ νλ₯ν κ±°λ²λμ€κ° νμν©λλ€.
- λ¨μΌ μμ€ μ§μ€(SSOT): μ΄κ²μ κ°μ₯ μ€μν μμΉμ λλ€. λͺ¨λ μ°Έμ‘° λ°μ΄ν°λ νλμ κΆμ μλ μμ€μμλ§ μμλμ΄μΌ ν©λλ€. νλ°νΈμλ μ ν리μΌμ΄μ μ κ²½μ° λ¨μΌ λͺ¨λ λλ μλΉμ€μΌ μ μμ΅λλ€. λ ν° μν°νλΌμ΄μ¦μμλ APIλ₯Ό ν΅ν΄ λ°μ΄ν°κ° λ ΈμΆλλ μ μ© MDM μμ€ν μΈ κ²½μ°κ° λ§μ΅λλ€.
 - λͺ νν μμ κΆ: μ°Έμ‘° λ°μ΄ν°μ μ νμ±κ³Ό 무결μ±μ μ μ§ κ΄λ¦¬ν μ± μμ΄ μλ ν λλ κ°μΈμ μ§μ ν©λλ€. λ³κ²½ μ¬νμ μ μ€νκ³ λ¬Έμνκ° μ λμ΄μΌ ν©λλ€.
 - λ²μ  κ΄λ¦¬: APIμμ μ°Έμ‘° λ°μ΄ν°λ₯Ό λ‘λν λ API μλν¬μΈνΈλ₯Ό λ²μ  κ΄λ¦¬ν©λλ€. μ΄λ κ² νλ©΄ λ°μ΄ν° ꡬ쑰μ μ£Όμ λ³κ²½ μ¬νμ΄ μ΄μ  ν΄λΌμ΄μΈνΈμ μν₯μ λ―ΈμΉλ κ²μ λ°©μ§ν μ μμ΅λλ€.
 - λ¬Έμν: JSDoc λλ κΈ°ν λ¬Έμν λꡬλ₯Ό μ¬μ©νμ¬ κ° μ°Έμ‘° λ°μ΄ν° μΈνΈμ μλ―Έμ μ¬μ©λ²μ μ€λͺ ν©λλ€. μλ₯Ό λ€μ΄ κ° `OrderStatus`μ λν λΉμ¦λμ€ κ·μΉμ λ¬Έμνν©λλ€.
 - μ½λ μμ± κ³ λ €: λ°±μλμ νλ°νΈμλ κ°μ κΆκ·Ήμ μΈ λκΈ°νλ₯Ό μν΄ λ°±μλ API μ¬μ(μ: OpenAPI/Swagger)μμ μ§μ  TypeScript νμ μ μμ±νλ λꡬλ₯Ό μ¬μ©νλ κ²μ κ³ λ €νμμμ€. μ΄λ κ² νλ©΄ ν΄λΌμ΄μΈνΈ μΈ‘ νμ μ APIμ λ°μ΄ν° ꡬ쑰μ λκΈ°ννλ νλ‘μΈμ€κ° μλνλ©λλ€.
 
κ²°λ‘ : TypeScriptλ‘ λ°μ΄ν° λ¬΄κ²°μ± ν₯μ
λ§μ€ν° λ°μ΄ν° κ΄λ¦¬λ μ½λλ₯Ό ν¨μ¬ λ°μ΄λλ λΆμΌμ΄μ§λ§ κ°λ°μλ‘μ μ°λ¦¬λ μ ν리μΌμ΄μ  λ΄μμ λ°μ΄ν° 무결μ±μ μ΅μ’ κ²μ΄νΈν€νΌμ λλ€. μ·¨μ½ν "λ§€μ§ μ€νΈλ§"μμ λ²μ΄λ νλμ μΈ TypeScript ν¨ν΄μ μ±νν¨μΌλ‘μ¨ μΌλ°μ μΈ λ²κ·Έμ μ 체 ν΄λμ€λ₯Ό ν¨κ³Όμ μΌλ‘ μ κ±°ν μ μμ΅λλ€.
νμ νμκ³Ό κ²°ν©λ `as const` ν¨ν΄μ μ°Έμ‘° λ°μ΄ν°λ₯Ό κ΄λ¦¬νκΈ° μν κ°λ ₯νκ³ μ μ§ κ΄λ¦¬ κ°λ₯νλ©° μ°μν μ루μ μ μ 곡ν©λλ€. λ°νμ λ‘μ§κ³Ό μ»΄νμΌ μκ° νμ κ²μ¬κΈ°μ λͺ¨λ μ 곡λλ λ¨μΌ μμ€ μ§μ€μ μ€μ νμ¬ λκΈ°νλμ§ μμ μ μλλ‘ ν©λλ€. μ€μ μ§μ€μ μλΉμ€ λ° μΈλΆ λ°μ΄ν°μ λν λ°νμ μ ν¨μ± κ²μ¬μ κ²°ν©νλ©΄ μ΄ μ κ·Ό λ°©μμ 볡μλ ₯ μλ μν°νλΌμ΄μ¦κΈ μ ν리μΌμ΄μ μ ꡬμΆνκΈ° μν κ°λ ₯ν νλ μμν¬λ₯Ό λ§λλλ€.
κΆκ·Ήμ μΌλ‘ TypeScriptλ `null` λλ `undefined` μ€λ₯λ₯Ό λ°©μ§νλ λꡬ κ·Έ μ΄μμ λλ€. λ°μ΄ν° λͺ¨λΈλ§κ³Ό λΉμ¦λμ€ κ·μΉμ μ½λ ꡬ쑰μ μ§μ  ν¬ν¨νκΈ° μν κ°λ ₯ν μΈμ΄μ λλ€. μ°Έμ‘° λ°μ΄ν° κ΄λ¦¬λ₯Ό μν΄ μ μ¬λ ₯μ μ΅λν νμ©ν¨μΌλ‘μ¨ λ κ°λ ₯νκ³ μμΈ‘ κ°λ₯νλ©° λ μ λ¬Έμ μΈ μννΈμ¨μ΄ μ νμ ꡬμΆν μ μμ΅λλ€.