Skip to content

Latest commit

Β 

History

History
394 lines (314 loc) Β· 13.5 KB

File metadata and controls

394 lines (314 loc) Β· 13.5 KB

item11 ~ item13

μ•„μ΄ν…œ11 | μž‰μ—¬ 속성 체크의 ν•œκ³„ μΈμ§€ν•˜κΈ°

Recognize the Limits of Excess Property Checking

  • νƒ€μž…μ΄ λͺ…μ‹œλœ λ³€μˆ˜μ— 객체 λ¦¬ν„°λŸ΄μ„ ν• λ‹Ήν•  λ•Œ νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” ν•΄λ‹Ή νƒ€μž…μ˜ 속성이 μžˆλŠ”μ§€ β€˜κ·Έ μ™Έμ˜ 속성은 μ—†λŠ”μ§€β€™ 확인
interface Room {
  numDoors: number;
  ceilingHeightFt: number;
}
const r1: Room = {
  numDoors: 1,
  ceilingHeightFt: 10,
  elephant: 'present',
// ~~~~~~~~~~~~~~~~~~ Object literal may only specify known properties,
//                    and 'elephant' does not exist in type 'Room'
};

const obj = {
  numDoors: 1,
  ceilingHeightFt: 10,
  elephant: 'present',
};
const r2: Room = obj;  // OK
  • r1의 경우. Room μΈν„°νŽ˜μ΄μŠ€μ— μ„ μ–Έλ˜μ§€ μ•Šμ€ 속성이 μΆ”κ°€λ˜μ—ˆμ„ λ•Œ, β€˜κ΅¬μ‘°μ  타이핑’ κ΄€μ μ—μ„œ 보면 였λ₯˜κ°€ λ°œμƒν•˜μ§€ μ•Šμ•„μ•Ό ν•˜μ§€λ§Œ λ°œμƒ.
  • obj κ°μ²΄μ—μ„œ μΆ”λ‘ λœ νƒ€μž…μ€ Room νƒ€μž…(의 λΆ€λΆ„ 집합)을 ν¬ν•¨ν•˜λ―€λ‘œ Room νƒ€μž…μ— ν• λ‹Ή κ°€λŠ₯ν•˜λ©°, νƒ€μž…μ²΄μ»€λ„ 톡과
  • r1 μ—μ„œλŠ” μž‰μ—¬ 속성 체크 λΌλŠ” 과정이 μˆ˜ν–‰
  • μž‰μ—¬ 속성 μ²΄ν¬λŠ”
    • 쑰건에 따라 λ™μž‘ν•˜μ§€ μ•ŠμŒ
    • 톡상적인 ν• λ‹Ή κ°€λŠ₯ 검사와 함꼐 쓰이면 ꡬ쑰적 타이핑이 무엇인지 ν—·κ°ˆλ¦Ό
    • ν• λ‹Ή κ°€λŠ₯ κ²€μ‚¬μ™€λŠ” λ³„λ„μ˜ κ³Όμ •
interface Options {
  title: string;
  darkMode?: boolean;
}
function createWindow(options: Options) {
  if (options.darkMode) {
    // setDarkMode();
  }
  // ...
}
createWindow({
  title: 'Spider Solitaire',
  darkmode: true
// ~~~~~~~~~~~~~ Object literal may only specify known properties, but
//               'darkmode' does not exist in type 'Options'.
//               Did you mean to write 'darkMode'?
});

const o1: Options = document;  // OK
const o2: Options = new HTMLAnchorElement;  // OK
  • μœ„ μ½”λ“œλŠ” λŸ°νƒ€μž„ 였λ₯˜λŠ” μ—†μœΌλ‚˜ νƒ€μž…μŠ€ν¬λ¦½νŠΈ 였λ₯˜λ§Œ λ°œμƒ.
  • Options νƒ€μž…μ˜ 경우, μ–΄λ–€ 객체가 title 속성(string νƒ€μž…)을 가지고 μžˆλ‹€λ©΄ - 단, darkMode 값이 μ—†κ±°λ‚˜ boolean νƒ€μž…μ΄μ–΄μ•Ό 함 - κ·Έ κ°μ²΄λŠ” λͺ¨λ‘ Options νƒ€μž… λ²”μœ„μ— 속함.
  • κ·Έλž˜μ„œ o1, o2 도 title 속성(string νƒ€μž…)을 가지고 μžˆμ–΄μ„œ 정상 λ™μž‘.
  • μž‰μ—¬ 속성 체크 λ₯Ό μ΄μš©ν•˜λ©΄, 객체 λ¦¬ν„°λŸ΄μ— μ•Œ 수 μ—†λŠ” 속성을 ν—ˆμš©ν•˜μ§€ μ•ŠμŒμœΌλ‘œμ¨ λ¬Έμ œμ μ„ 방지
    • so, μ—„κ²©ν•œ 객체 λ¦¬ν„°λŸ΄ 체크 라고 λΆˆλ¦¬κΈ°λ„
  • document, new HTMLAnchorElement λŠ” 객체 λ¦¬ν„°λŸ΄μ΄ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— μž‰μ—¬ 속성 체크 μ•ˆλ¨
  • { title, darkmode } κ°μ²΄λŠ” μž‰μ—¬ 속성 체크 κ°€λŠ₯
const o1: Options = { darkmode: true, title: 'Ski Free' };
                  // ~~~~~~~~ 'darkmode' does not exist in type 'Options'...

const intermediate = { darkmode: true, title: 'Ski Free' };
const o2: Options = intermediate;  // OK

const o3 = { darkmode: true, title: 'Ski Free' } as Options;  // OK
  • o1 의 였λ₯Έμͺ½μ€ 객체 λ¦¬ν„°λŸ΄, o2 의 였λ₯Έμͺ½μ€ 객체 λ¦¬ν„°λŸ΄μ΄ μ•„λ‹˜. κ·Έλž˜μ„œ μž‰μ—¬ 속성 체크가 μ μš©λ˜μ§€ μ•ŠμŒ.
  • μž‰μ—¬ 속성 μ²΄ν¬λŠ” νƒ€μž… 단언문을 μ‚¬μš©ν•  λ•Œμ—λ„ μ μš©λ˜μ§€ μ•ŠμŒ - o3
    • κ·Έλž˜μ„œ νƒ€μž… 단언문보닀 선언문을 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€!
interface Options {
  darkMode?: boolean;
  [otherOptions: string]: unknown;
}
const o: Options = { darkmode: true };  // OK
  • μž‰μ—¬ 속성 체크λ₯Ό μ›ν•˜μ§€ μ•ŠμœΌλ©΄, 인덱슀 μ‹œκ·Έλ‹ˆμ²˜λ₯Ό μ‚¬μš©ν•΄ νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ 좔가적인 속성을 μ˜ˆμƒν•˜λ„λ‘ 함
interface LineChartOptions {
  logscale?: boolean;
  invertedYAxis?: boolean;
  areaChart?: boolean;
}
const opts = { logScale: true };
const o: LineChartOptions = opts;
   // ~ Type '{ logScale: boolean; }' has no properties in common
   //   with type 'LineChartOptions'
  • 선택적 μ†μ„±λ§Œ κ°€μ§€λŠ” μ•½ν•œ(weak) νƒ€μž…μ—λ„ λΉ„μŠ·ν•œ 체크가 λ™μž‘

  • ꡬ쑰적 κ΄€μ μ—μ„œ LineChartOptions νƒ€μž…μ€ λͺ¨λ“  객체λ₯Ό 포함할 수 있음

  • 이런 μ•½ν•œ νƒ€μž…μ€ νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ κ°’ νƒ€μž…κ³Ό μ„ μ–Έ νƒ€μž…μ— κ³΅ν†΅λœ 속성이 μžˆλŠ”μ§€ λ³„λ„λ‘œ 확인

  • 곡톡 속성 μ²΄ν¬λŠ” μž‰μ—¬ 속성 체크와 λΉ„μŠ·ν•˜κ²Œ μ˜€νƒ€λ₯Ό μž‘λŠ”λ° 효과적, ꡬ쑰적으둜 μ—„κ²©ν•˜μ§€ μ•ŠμŒ

  • μž‰μ—¬ 속성 체크와 λ‹€λ₯Έ 점은 μ•½ν•œ νƒ€μž…κ³Ό κ΄€λ ¨λœ ν• λ‹Ήλ¬Έλ§ˆλ‹€ μˆ˜ν–‰. μž„μ‹œ λ³€μˆ˜λ₯Ό μ œκ±°ν•΄λ„ 곡톡 속성 μ²΄ν¬λŠ” λ™μž‘ν•¨

  • μž‰μ—¬ 속성 μ²΄ν¬λŠ”

    • ꡬ쑰적 타이핑 μ‹œμŠ€ν…œμ—μ„œ ν—ˆμš©λ˜λŠ” μ‹€μˆ˜λ₯Ό μ€„μ—¬μ€Œ
    • 선택적 ν•„λ“œλ₯Ό ν¬ν•¨ν•˜λŠ” νƒ€μž…μ— 특히 유용
    • 적용 λ²”μœ„κ°€ μ œν•œμ , 였직 객체 λ¦¬ν„°λŸ΄μ—λ§Œ 적용

μ•„μ΄ν…œ12 | ν•¨μˆ˜ ν‘œν˜„μ‹μ— νƒ€μž… μ μš©ν•˜κΈ°

Apply Types to Entire Function Expressions When Possible

  • js, ts μ—μ„œλŠ” ν•¨μˆ˜ λ¬Έμž₯(statement)κ³Ό ν•¨μˆ˜ ν‘œν˜„μ‹(expression)을 λ‹€λ₯΄κ²Œ 인식
function rollDice1(sides: number): number { /* COMPRESS */ return 0; /* END */ }  // Statement

const rollDice2 = function(sides: number): number { /* COMPRESS */ return 0; /* END */ };  // Expression
const rollDice3 = (sides: number): number => { /* COMPRESS */ return 0; /* END */ };  // Also expression
  • νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” ν•¨μˆ˜ ν‘œν˜„μ‹μ„ μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

    β†’ ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜λΆ€ν„° λ°˜ν™˜κ°’κΉŒμ§€ 전체λ₯Ό ν•¨μˆ˜ νƒ€μž…μœΌλ‘œ μ„ μ–Έ, ν•¨μˆ˜ ν‘œν˜„μ‹μ— μž¬μ‚¬μš© κ°€λŠ₯

type DiceRollFn = (sides: number) => number;
const rollDice: DiceRollFn = sides => { /* COMPRESS */ return 0; /* END */ };
// μ—¬κΈ°μ—μ„œ tsκ°€ 이미 sides의 νƒ€μž…μ„ number둜 인식
  • ν•¨μˆ˜ νƒ€μž… μ„ μ–Έμ˜ μž₯점 : λΆˆν•„μš”ν•œ μ½”λ“œμ˜ 반볡 μ€„μž„
function add(a: number, b: number) { return a + b; }
function sub(a: number, b: number) { return a - b; }
function mul(a: number, b: number) { return a * b; }
function div(a: number, b: number) { return a / b; }

// λ°˜λ³΅λ˜λŠ” ν•¨μˆ˜ μ‹œκ·Έλ‹ˆμ²˜λ₯Ό ν•˜λ‚˜μ˜ ν•¨μˆ˜ νƒ€μž…μœΌλ‘œ 톡합
type BinaryFn = (a: number, b: number) => number;
const add: BinaryFn = (a, b) => a + b;
const sub: BinaryFn = (a, b) => a - b;
const mul: BinaryFn = (a, b) => a * b;
const div: BinaryFn = (a, b) => a / b;
  • λΌμ΄λΈŒλŸ¬λ¦¬λŠ” 곡톡 ν•¨μˆ˜ μ‹œκ·Έλ‹ˆμ²˜λ₯Ό νƒ€μž…μœΌλ‘œ μ œκ³΅ν•˜κΈ°λ„

    • ex) λ¦¬μ•‘νŠΈλŠ” MouseEvent(ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜μ— λͺ…μ‹œ) νƒ€μž… λŒ€μ‹ , ν•¨μˆ˜ 전체에 μ μš©ν•  수 μžˆλŠ” MouseEventHandler νƒ€μž… 제곡
  • μ‹œκ·Έλ‹ˆμ²˜κ°€ μΌμΉ˜ν•˜λŠ” λ‹€λ₯Έ ν•¨μˆ˜κ°€ μžˆμ„ λ•Œλ„ ν•¨μˆ˜ ν‘œν˜„μ‹μ— νƒ€μž… 적용 κ°€λŠ₯

    • λ‹€λ₯Έ ν•¨μˆ˜μ˜ μ‹œκ·Έλ‹ˆμ²˜λ₯Ό μ°Έμ‘°ν•˜λ €λ©΄ typeof fn μ‚¬μš©
declare function fetch(
  input: RequestInfo, init?: RequestInit
): Promise<Response>;

async function checkedFetch(input: RequestInfo, init?: RequestInit) {
  const response = await fetch(input, init);
  if (!response.ok) {
    // Converted to a rejected Promise in an async function
    throw new Error('Request failed: ' + response.status);
  }
  return response;
}

// ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜μ™€ 리턴 νƒ€μž…κΉŒμ§€ 보μž₯
const checkedFetch: typeof fetch = async (input, init) => {
  const response = await fetch(input, init);
  if (!response.ok) {
    throw new Error('Request failed: ' + response.status);
  }
  return response;
}

// μ‹€μˆ˜λ‘œ errorλ₯Ό return ν–ˆμ„ κ²½μš°μ—λ„ ν•¨μˆ˜ νƒ€μž… μ„ μ–Έ 덕뢄에 였λ₯˜λ₯Ό 감지
// ν•¨μˆ˜ ν‘œν˜„μ‹μ΄ μ•„λ‹ˆλΌ ν•¨μˆ˜ λ¬Έμž₯ ν˜•νƒœμΈ 경우, checkedFetch κ΅¬ν˜„μ²΄μ— 였λ₯˜κ°€ λ°œμƒν•˜λŠ”κ²Œ μ•„λ‹Œ 이 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•œ μœ„μΉ˜μ—μ„œ λ°œμƒ
const checkedFetch: typeof fetch = async (input, init) => {
  //  ~~~~~~~~~~~~   Type 'Promise<Response | HTTPError>'
  //                     is not assignable to type 'Promise<Response>'
  //                   Type 'Response | HTTPError' is not assignable
  //                       to type 'Response'
  const response = await fetch(input, init);
  if (!response.ok) {
    return new Error('Request failed: ' + response.status);
  }
  return response;
}

μ•„μ΄ν…œ13 | νƒ€μž…κ³Ό μΈν„°νŽ˜μ΄μŠ€μ˜ 차이점 μ•ŒκΈ°

Know the Differences Between type and interface

  • νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œ λͺ…λͺ…λœ νƒ€μž…(named type)을 μ •μ˜ν•˜λŠ” 방법 : λŒ€λΆ€λΆ„μ˜ 경우 λ‘˜ 쀑 μ•„λ¬΄κ±°λ‚˜ μ‚¬μš©ν•΄λ„ 됨
// νƒ€μž…
type TState = {
  name: string;
  capital: string;
}
// μΈν„°νŽ˜μ΄μŠ€
interface IState {
  name: string;
  capital: string;
}

// νƒ€μž…κ³Ό μΈν„°νŽ˜μ΄μŠ€ μ•žμ— T/I 뢙이지 말것
  • μΈν„°νŽ˜μ΄μŠ€ λŒ€μ‹  클래슀 μ‚¬μš© κ°€λŠ₯. κ·ΈλŸ¬λ‹ˆ ν΄λž˜μŠ€λŠ” κ°’μœΌλ‘œλ„ μ‚¬μš©λ˜λŠ” js λŸ°νƒ€μž„ κ°œλ…

🐰 μΈν„°νŽ˜μ΄μŠ€, νƒ€μž…μ˜ λΉ„μŠ·ν•œ 점 🐰

  • λ‘˜ 쀑 μ–΄λŠ κ²ƒμœΌλ‘œ νƒ€μž…μ„ μ •μ˜ν•˜λ“  μƒνƒœμ—λŠ” 차이가 μ—†μŒ

    // μΆ”κ°€ 속성을 ν•¨κ»˜ ν• λ‹Ήν•˜λ©΄ νƒ€μž…, μΈν„°νŽ˜μ΄μŠ€ μ„ μ–Έ λ‘˜ λ‹€ λ™μΌν•œ 였λ₯˜ λ°œμƒ
    const wyoming: TState = {
      name: 'Wyoming',
      capital: 'Cheyenne',
      population: 500_000
    // ~~~~~~~~~~~~~~~~~~ Type ... is not assignable to type 'TState'
    //                    Object literal may only specify known properties, and
    //                    'population' does not exist in type 'TState'
    };
  • 인덱슀 μ‹œκ·Έλ‹ˆμ²˜ μ‚¬μš© κ°€λŠ₯

    type TDict = { [key: string]: string };
    interface IDict {
      [key: string]: string;
    }
  • ν•¨μˆ˜ νƒ€μž…λ„ μ •μ˜ κ°€λŠ₯

    type TFn = (x: number) => string;
    interface IFn {
      (x: number): string;
    }
    
    const toStrT: TFn = x => '' + x;  // OK
    const toStrI: IFn = x => '' + x;  // OK
    
    // ν•¨μˆ˜ νƒ€μž…μ— 좔가적인 속성이 μžˆλŠ” 경우
    type TFnWithProperties = {
      (x: number): number; // '=>' μ΄μš©ν•΄ ν•¨μˆ˜λ₯Ό μ •μ˜ν•  μˆ˜λ„ 있음. λ‚΄μš©μ˜ μ°¨μ΄λŠ” μžˆλ‹€
      prop: string;
    }
    interface IFnWithProperties {
      (x: number): number;
      prop: string;
    }
    
    // μ—¬κΈ° 잘 λͺ¨λ₯΄κ² μŒ. ν•¨μˆ˜ μ •μ˜λ₯Ό μ΄λ ‡κ²Œλ„ ν•˜λ‚˜

    β†’ λ‹¨μˆœν•œ ν•¨μˆ˜ νƒ€μž…μ€ νƒ€μž… 별칭(alias) 이 더 λ‚˜μ€ 선택. μΆ”κ°€ 속성이 μžˆλŠ” 경우 λ‘˜ λ‹€ 차이 μ—†μŒ

  • μ œλ„ˆλ¦­ μ‚¬μš© κ°€λŠ₯

    type TPair<T> = {
      first: T;
      second: T;
    }
    interface IPair<T> {
      first: T;
      second: T;
    }
  • μΈν„°νŽ˜μ΄μŠ€ - νƒ€μž… ν™•μž₯ κ°€λŠ₯ νƒ€μž… - μΈν„°νŽ˜μ΄μŠ€ ν™•μž₯ κ°€λŠ₯

    interface IStateWithPop extends TState {
      population: number;
    }
    type TStateWithPop = IState & { population: number; };

    β—Β μΈν„°νŽ˜μ΄μŠ€λŠ” μœ λ‹ˆμ˜¨ νƒ€μž…κ°™μ€ λ³΅μž‘ν•œ νƒ€μž…μ€ ν™•μž₯ λΆˆκ°€

    β—Β λ³΅μž‘ν•œ νƒ€μž…μ„ ν™•μž₯ν•˜κ³  μ‹ΆμœΌλ©΄ νƒ€μž…κ³Ό & μ‚¬μš©

  • 클래슀 κ΅¬ν˜„(implements)ν•  λ•Œ μ‚¬μš© κ°€λŠ₯

    class StateT implements TState {
      name: string = '';
      capital: string = '';
    }
    class StateI implements IState {
      name: string = '';
      capital: string = '';
    }

πŸ°Β μΈν„°νŽ˜μ΄μŠ€, νƒ€μž…μ˜ λ‹€λ₯Έ 점 🐰

  • μœ λ‹ˆμ˜¨ νƒ€μž…μ€ μžˆμ§€λ§Œ μœ λ‹ˆμ˜¨ μΈν„°νŽ˜μ΄μŠ€λŠ” μ—†μŒ

    type AorB = 'a' | 'b';
  • μΈν„°νŽ˜μ΄μŠ€λŠ” νƒ€μž…μ„ ν™•μž₯ν•  수 μžˆμ§€λ§Œ μœ λ‹ˆμ˜¨μ€ ν•  수 μ—†μŒ.

    // μœ λ‹ˆμ˜¨ νƒ€μž…μ„ ν™•μž₯ν•˜λŠ”κ²Œ ν•„μš”ν•  경우. 
    // νƒ€μž…μ„ ν•˜λ‚˜μ˜ λ³€μˆ˜λͺ…μœΌλ‘œ λ§€ν•‘ν•˜μ—¬ μΈν„°νŽ˜μ΄μŠ€ μ •μ˜ν•˜λŠ” 예제
    type Input = { /* ... */ };
    type Output = { /* ... */ };
    interface VariableMap {
      [name: string]: Input | Output;
    }
    
    // μœ λ‹ˆμ˜¨ νƒ€μž…μ— name 속성을 뢙인 νƒ€μž…μ„ λ§Œλ“€μˆ˜λ„
    type NamedVariable = (Input | Output) & { name: string };

    β†’ 이 νƒ€μž…μ€ μΈν„°νŽ˜μ΄μŠ€λ‘œ ν‘œν˜„ λΆˆκ°€

    β†’ 일반적으둜 type ν‚€μ›Œλ“œλŠ” interface 보닀 μ“°μž„μƒˆκ°€ λ§Žλ‹€.

  • νŠœν”Œκ³Ό λ°°μ—΄ νƒ€μž…λ„ type ν‚€μ›Œλ“œ μ΄μš©ν•΄ 더 κ°„κ²°ν•˜κ²Œ ν‘œν˜„ κ°€λŠ₯

    type Pair = [number, number];
    type StringList = string[];
    type NamedNums = [string, ...number[]];
    
    // μΈν„°νŽ˜μ΄μŠ€λ‘œ νŠœν”Œ λΉ„μŠ€λ―€λ ˆν•˜κ²Œ κ΅¬ν˜„ν•œ 경우
    // νŠœν”Œμ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” concat 같은 λ©”μ„œλ“œ μ‚¬μš© λΆˆκ°€
    interface Tuple {
      0: number;
      1: number;
      length: 2;
    }
    const t: Tuple = [10, 20];  // OK
  • μΈν„°νŽ˜μ΄μŠ€λŠ” 보강(augment)이 κ°€λŠ₯

    interface IState {
      name: string;
      capital: string;
    }
    interface IState {
      population: number;
    }
    const wyoming: IState = {
      name: 'Wyoming',
      capital: 'Cheyenne',
      population: 500_000
    };  // OK
    • 이 처럼 속성을 ν™•μž₯ν•˜λŠ” 것 β†’ μ„ μ–Έ 병합(declaration merging)

    • μ„ μ–Έ 병합은 주둜 νƒ€μž…μ„ μ–Έ νŒŒμΌμ—μ„œ μ‚¬μš©

      β†’ νƒ€μž… μ„ μ–Έ νŒŒμΌμ„ μž‘μ„±ν•  λ•ŒλŠ” μ„ μ–Έ 병합을 μ§€μ›ν•˜κΈ° μœ„ν•΄ λ°˜λ“œμ‹œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•΄μ•Όν•˜κ³ , ν‘œμ€€μ„ 따라야 함

    • 병합은 μ„ μ–Έμ²˜λŸΌ 일반적인 μ½”λ“œμ—μ„œλ„ 지원

    • νƒ€μž…μ€ κΈ°μ‘΄ νƒ€μž…μ— 좔가적인 보강이 μ—†λŠ” κ²½μš°μ—λ§Œ μ‚¬μš©ν•΄μ•Όν•¨

  • κ²°λ‘ 

    • λ³΅μž‘ν•œ νƒ€μž…μ΄λ©΄ νƒ€μž… 별칭 μ‚¬μš©
    • κ°„λ‹¨ν•œ 객체 νƒ€μž…μ΄λ©΄
      • μΌκ΄€μ„±μ˜ 관점 : μΌκ΄€λ˜κ²Œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” ν”„λ‘œμ νŠΈμ—μ„  μΈν„°νŽ˜μ΄μŠ€, μΌκ΄€λ˜κ²Œ νƒ€μž…μ„ μ‚¬μš©ν•˜λŠ” κ²½μš°μ—” νƒ€μž…
      • λ³΄κ°•μ˜ 관점 : ν–₯ν›„ νƒ€μž… 선언에 λ³΄κ°•μ˜ κ°€λŠ₯성이 μžˆλ‹€λ©΄ μΈν„°νŽ˜μ΄μŠ€ μΆ”μ²œ
    • ν”„λ‘œμ νŠΈ λ‚΄λΆ€μ μœΌλ‘œ μ‚¬μš©λ˜λŠ” νƒ€μž…μ— μ„ μ–Έ 병합이 λ°œμƒν•˜λŠ” 것은 잘λͺ»λœ 섀계 β†’ νƒ€μž…μ„ μ‚¬μš©ν•΄μ•Ό 함

Item28 ~ Item30