๐Ÿš€ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํด๋ž˜์Šค ์ž‘์„ฑ๋ฒ• ๋งˆ์Šคํ„ฐํ•˜๊ธฐ ๐Ÿš€

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํด๋ž˜์Šค ์ž‘์„ฑ๋ฒ• ๋งˆ์Šคํ„ฐํ•˜๊ธฐ ๐Ÿš€

 

 

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

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

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

์ž, ๊ทธ๋Ÿผ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์‹œ์ž‘ํ•ด๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํด๋ž˜์Šค์˜ ์„ธ๊ณ„๋กœ Go Go! ๐Ÿš—๐Ÿ’จ

1. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํด๋ž˜์Šค์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ ๐Ÿ—๏ธ

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํด๋ž˜์Šค์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ถ€ํ„ฐ ์‚ดํŽด๋ณผ๊ฒŒ์š”. ํด๋ž˜์Šค๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํ…œํ”Œ๋ฆฟ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ผ์š”. ๋งˆ์น˜ ์ฟ ํ‚ค ํ‹€์ฒ˜๋Ÿผ์š”! ๐Ÿช


class Cookie {
  flavor: string;

  constructor(flavor: string) {
    this.flavor = flavor;
  }

  describe(): string {
    return `This is a ${this.flavor} flavored cookie.`;
  }
}

const chocolateCookie = new Cookie('chocolate');
console.log(chocolateCookie.describe()); // "This is a chocolate flavored cookie."

์ด ์˜ˆ์ œ์—์„œ ์šฐ๋ฆฌ๋Š” 'Cookie'๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์—ˆ์–ด์š”. ์ด ํด๋ž˜์Šค๋Š” 'flavor'๋ผ๋Š” ์†์„ฑ๊ณผ 'describe'๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ฃ . 'constructor'๋Š” ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ํŠน๋ณ„ํ•œ ๋ฉ”์„œ๋“œ์˜ˆ์š”.

ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋น„์Šทํ•œ ํŠน์„ฑ์„ ๊ฐ€์ง„ ๊ฐ์ฒด๋“ค์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์–‘ํ•œ ๋ง›์˜ ์ฟ ํ‚ค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒ ์ฃ ?


const strawberryCookie = new Cookie('strawberry');
const vanillaCookie = new Cookie('vanilla');

console.log(strawberryCookie.describe()); // "This is a strawberry flavored cookie."
console.log(vanillaCookie.describe()); // "This is a vanilla flavored cookie."

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

๐Ÿฌ Sweet Tip: ํด๋ž˜์Šค ์ด๋ฆ„์€ ํ•ญ์ƒ ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ๊ด€๋ก€์˜ˆ์š”. 'cookie'๊ฐ€ ์•„๋‹ˆ๋ผ 'Cookie'์ฒ˜๋Ÿผ์š”!

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

2. ์ ‘๊ทผ ์ œ์–ด์ž (Access Modifiers) ๐Ÿ”

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํด๋ž˜์Šค์—์„œ๋Š” ๋ฉค๋ฒ„(์†์„ฑ๊ณผ ๋ฉ”์„œ๋“œ)์˜ ์ ‘๊ทผ์„ฑ์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ฅผ ์œ„ํ•ด ์„ธ ๊ฐ€์ง€ ์ ‘๊ทผ ์ œ์–ด์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ฃ . ๋ฐ”๋กœ public, private, protected์˜ˆ์š”.

  • public: ๊ธฐ๋ณธ๊ฐ’์ด์—์š”. ํด๋ž˜์Šค ์™ธ๋ถ€์—์„œ ์ž์œ ๋กญ๊ฒŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•ด์š”.
  • private: ํ•ด๋‹น ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•ด์š”.
  • protected: ํ•ด๋‹น ํด๋ž˜์Šค์™€ ์ƒ์†๋ฐ›์€ ์ž์‹ ํด๋ž˜์Šค์—์„œ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•ด์š”.

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


class BankAccount {
  public accountHolder: string;
  private balance: number;
  protected accountNumber: string;

  constructor(accountHolder: string, initialBalance: number) {
    this.accountHolder = accountHolder;
    this.balance = initialBalance;
    this.accountNumber = Math.random().toString(36).substr(2, 9);
  }

  public deposit(amount: number): void {
    this.balance += amount;
  }

  public withdraw(amount: number): boolean {
    if (this.balance >= amount) {
      this.balance -= amount;
      return true;
    }
    return false;
  }

  private calculateInterest(): number {
    return this.balance * 0.05;
  }

  protected getAccountDetails(): string {
    return `Account Number: ${this.accountNumber}, Balance: ${this.balance}`;
  }
}

const myAccount = new BankAccount('ํ™๊ธธ๋™', 1000000);

console.log(myAccount.accountHolder); // 'ํ™๊ธธ๋™'
myAccount.deposit(500000);
console.log(myAccount.withdraw(200000)); // true

// ์•„๋ž˜ ์ฝ”๋“œ๋“ค์€ ์ปดํŒŒ์ผ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
// console.log(myAccount.balance); // Error: Property 'balance' is private and only accessible within class 'BankAccount'.
// console.log(myAccount.calculateInterest()); // Error: Property 'calculateInterest' is private and only accessible within class 'BankAccount'.
// console.log(myAccount.getAccountDetails()); // Error: Property 'getAccountDetails' is protected and only accessible within class 'BankAccount' and its subclasses.

์ด ์˜ˆ์ œ์—์„œ 'BankAccount' ํด๋ž˜์Šค๋Š” ๋‹ค์–‘ํ•œ ์ ‘๊ทผ ์ œ์–ด์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด์š”. 'accountHolder'๋Š” public์ด๋ผ ์™ธ๋ถ€์—์„œ ์ž์œ ๋กญ๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, 'balance'๋Š” private์ด๋ผ ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•ด์š”. 'accountNumber'๋Š” protected๋ผ์„œ ์ด ํด๋ž˜์Šค์™€ ์ƒ์†๋ฐ›์€ ํด๋ž˜์Šค์—์„œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์ฃ .

๐Ÿ’ฐ Money Tip: ์‹ค์ œ ์€ํ–‰ ์‹œ์Šคํ…œ์ฒ˜๋Ÿผ, ์ค‘์š”ํ•œ ์ •๋ณด๋Š” private์œผ๋กœ ์„ค์ •ํ•˜๊ณ , ํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋งŒ public์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค!

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

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

3. ํด๋ž˜์Šค ์ƒ์† (Inheritance) ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ

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

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” 'extends' ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์š”. ํ•œ๋ฒˆ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์‚ดํŽด๋ณผ๊นŒ์š”?


class Animal {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  makeSound(): void {
    console.log("Some generic animal sound");
  }
}

class Dog extends Animal {
  breed: string;

  constructor(name: string, breed: string) {
    super(name);  // ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ constructor๋ฅผ ํ˜ธ์ถœ
    this.breed = breed;
  }

  makeSound(): void {
    console.log("Woof! Woof!");
  }

  fetch(): void {
    console.log(`${this.name} is fetching the ball!`);
  }
}

const myDog = new Dog("๋ฝ€์‚", "ํ‘ธ๋“ค");
console.log(myDog.name);  // "๋ฝ€์‚"
console.log(myDog.breed);  // "ํ‘ธ๋“ค"
myDog.makeSound();  // "Woof! Woof!"
myDog.fetch();  // "๋ฝ€์‚ is fetching the ball!"

์ด ์˜ˆ์ œ์—์„œ 'Dog' ํด๋ž˜์Šค๋Š” 'Animal' ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๊ณ  ์žˆ์–ด์š”. 'Dog' ํด๋ž˜์Šค๋Š” 'Animal' ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํŠน์„ฑ(์—ฌ๊ธฐ์„œ๋Š” 'name' ์†์„ฑ๊ณผ 'makeSound' ๋ฉ”์„œ๋“œ)์„ ๊ฐ€์ง€๋ฉด์„œ, ์ž์‹ ๋งŒ์˜ ํŠน์„ฑ('breed' ์†์„ฑ๊ณผ 'fetch' ๋ฉ”์„œ๋“œ)๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์ฃ .

'super' ํ‚ค์›Œ๋“œ๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ constructor๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ผ์š”. ์ด๋ฅผ ํ†ตํ•ด ๋ถ€๋ชจ ํด๋ž˜์Šค์—์„œ ์ •์˜๋œ ์ดˆ๊ธฐํ™” ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ฃ .

๋˜ํ•œ, 'Dog' ํด๋ž˜์Šค์—์„œ 'makeSound' ๋ฉ”์„œ๋“œ๋ฅผ ์ƒˆ๋กœ ์ •์˜ํ–ˆ๋Š”๋ฐ, ์ด๋ฅผ ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ(method overriding)์ด๋ผ๊ณ  ํ•ด์š”. ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ž์‹ ํด๋ž˜์Šค์—์„œ ์žฌ์ •์˜ํ•˜๋Š” ๊ฑฐ์ฃ .

๐Ÿพ Paw Tip: ์ƒ์†์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” "is-a" ๊ด€๊ณ„๋ฅผ ๊ณ ๋ คํ•ด๋ณด์„ธ์š”. "๊ฐœ๋Š” ๋™๋ฌผ์ด๋‹ค(A dog is an animal)"๋ผ๋Š” ๊ด€๊ณ„๊ฐ€ ์„ฑ๋ฆฝํ•˜๋ฏ€๋กœ ์ด ๊ฒฝ์šฐ ์ƒ์†์ด ์ ์ ˆํ•ด์š”!

์ƒ์†์„ ํ™œ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ ์ค„์ด๊ณ , ๊ตฌ์กฐ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ๋„ท์—์„œ ๋‹ค์–‘ํ•œ ์œ ํ˜•์˜ ์‚ฌ์šฉ์ž(์ผ๋ฐ˜ ์‚ฌ์šฉ์ž, ํ”„๋ฆฌ๋ฏธ์—„ ์‚ฌ์šฉ์ž, ๊ด€๋ฆฌ์ž ๋“ฑ)๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์ƒ์†์„ ํ™œ์šฉํ•˜๋ฉด ํšจ์œจ์ ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘ฉโ€๐Ÿ’ผ

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

4. ์ธํ„ฐํŽ˜์ด์Šค (Interface) ๐Ÿค

์ธํ„ฐํŽ˜์ด์Šค๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์˜ˆ์š”. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด์˜ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ์ฃ . ํด๋ž˜์Šค๊ฐ€ ํŠน์ • ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฅด๋„๋ก ๊ฐ•์ œํ•  ์ˆ˜๋„ ์žˆ๊ณ , ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋‚˜ ๋ฐ˜ํ™˜๊ฐ’์˜ ํƒ€์ž…์„ ์ง€์ •ํ•  ๋•Œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•๋ถ€ํ„ฐ ์‚ดํŽด๋ณผ๊นŒ์š”?


interface Person {
  name: string;
  age: number;
  greet(): void;
}

class Student implements Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  greet(): void {
    console.log(`์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” ${this.name}์ด๊ณ  ${this.age}์‚ด์ž…๋‹ˆ๋‹ค.`);
  }

  study(): void {
    console.log(`${this.name}์ด(๊ฐ€) ๊ณต๋ถ€ ์ค‘์ž…๋‹ˆ๋‹ค.`);
  }
}

const student1 = new Student("๊น€์ฒ ์ˆ˜", 20);
student1.greet();  // "์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” ๊น€์ฒ ์ˆ˜์ด๊ณ  20์‚ด์ž…๋‹ˆ๋‹ค."
student1.study();  // "๊น€์ฒ ์ˆ˜์ด(๊ฐ€) ๊ณต๋ถ€ ์ค‘์ž…๋‹ˆ๋‹ค."

์ด ์˜ˆ์ œ์—์„œ 'Person' ์ธํ„ฐํŽ˜์ด์Šค๋Š” 'name'๊ณผ 'age' ์†์„ฑ, ๊ทธ๋ฆฌ๊ณ  'greet' ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค๊ณ  ์ •์˜ํ•˜๊ณ  ์žˆ์–ด์š”. 'Student' ํด๋ž˜์Šค๋Š” ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„(implement)ํ•˜๊ณ  ์žˆ์ฃ .

'implements' ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ํด๋ž˜์Šค๊ฐ€ ํŠน์ • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋”ฐ๋ฅด๋„๋ก ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•ด๋‹น ํด๋ž˜์Šค๋Š” ๋ฐ˜๋“œ์‹œ ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋œ ๋ชจ๋“  ์†์„ฑ๊ณผ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•ด์š”. ๊ตฌํ˜„ํ•˜์ง€ ์•Š์œผ๋ฉด ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ฃ .

์ธํ„ฐํŽ˜์ด์Šค๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๋™์‹œ์— ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด๋ณผ๊นŒ์š”?


interface Printable {
  print(): void;
}

class Book implements Person, Printable {
  name: string;
  age: number;
  author: string;

  constructor(name: string, age: number, author: string) {
    this.name = name;
    this.age = age;
    this.author = author;
  }

  greet(): void {
    console.log(`์ด ์ฑ…์˜ ์ œ๋ชฉ์€ ${this.name}์ด๊ณ , ์ถœ๊ฐ„๋œ ์ง€ ${this.age}๋…„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.`);
  }

  print(): void {
    console.log(`${this.name} by ${this.author}`);
  }
}

const myBook = new Book("TypeScript ๋งˆ์Šคํ„ฐํ•˜๊ธฐ", 2, "๊น€๊ฐœ๋ฐœ");
myBook.greet();  // "์ด ์ฑ…์˜ ์ œ๋ชฉ์€ TypeScript ๋งˆ์Šคํ„ฐํ•˜๊ธฐ์ด๊ณ , ์ถœ๊ฐ„๋œ ์ง€ 2๋…„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
myBook.print();  // "TypeScript ๋งˆ์Šคํ„ฐํ•˜๊ธฐ by ๊น€๊ฐœ๋ฐœ"

์—ฌ๊ธฐ์„œ 'Book' ํด๋ž˜์Šค๋Š” 'Person'๊ณผ 'Printable' ๋‘ ๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋™์‹œ์— ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค์˜ ํŠน์„ฑ์„ ํ•œ ํด๋ž˜์Šค์— ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์ฃ .

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

์ธํ„ฐํŽ˜์ด์Šค๋Š” ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์„ ๊ฐœ๋ฐœํ•  ๋•Œ ํŠนํžˆ ์œ ์šฉํ•  ๊ฑฐ์˜ˆ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์–‘ํ•œ ์œ ํ˜•์˜ ์žฌ๋Šฅ(์Œ์•…, ๋ฏธ์ˆ , ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋“ฑ)์„ ํ‘œํ˜„ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ , ๊ฐ ์žฌ๋Šฅ ์œ ํ˜•๋ณ„๋กœ ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ? ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ”๋“œ์˜ ๊ตฌ์กฐ๊ฐ€ ๋ช…ํ™•ํ•ด์ง€๊ณ , ์ƒˆ๋กœ์šด ์žฌ๋Šฅ ์œ ํ˜•์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋„ ์‰ฌ์›Œ์งˆ ๊ฑฐ์˜ˆ์š”! ๐ŸŽจ๐ŸŽต๐Ÿ’ป

์ž, ์ด์ œ ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์œผ๋‹ˆ, ๋‹ค์Œ์œผ๋กœ ์ œ๋„ค๋ฆญ์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊นŒ์š”? ์ œ๋„ค๋ฆญ์€ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์˜ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์˜ˆ์š”. ํ•จ๊ป˜ ์‚ดํŽด๋ณด์ฃ ! ๐Ÿš€

5. ์ œ๋„ค๋ฆญ (Generics) ๐Ÿงฌ

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

์ œ๋„ค๋ฆญ์˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•๋ถ€ํ„ฐ ์‚ดํŽด๋ณผ๊นŒ์š”?


class Box<T> {
  private content: T;

  constructor(content: T) {
    this.content = content;
  }

  getContent(): T {
    return this.content;
  }
}

const numberBox = new Box<number>(42);
console.log(numberBox.getContent());  // 42

const stringBox = new Box<string>("Hello, TypeScript!");
console.log(stringBox.getContent());  // "Hello, TypeScript!"

์ด ์˜ˆ์ œ์—์„œ 'Box' ํด๋ž˜์Šค๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… 'T'๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด์š”. ์ด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์‹ค์ œ ํƒ€์ž…์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์ฃ . 'numberBox'๋Š” ์ˆซ์ž๋ฅผ, 'stringBox'๋Š” ๋ฌธ์ž์—ด์„ ๋‹ด๊ณ  ์žˆ์–ด์š”.

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

์ œ๋„ค๋ฆญ์€ ํด๋ž˜์Šค๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ•จ์ˆ˜์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด๋ณผ๊นŒ์š”?


function swap<T, U>(tuple: [T, U]): [U, T] {
  return [tuple[1], tuple[0]];
}

const result1 = swap<string, number>(["hello", 42]);
console.log(result1);  // [42, "hello"]

const result2 = swap(["TypeScript", true]);  // ํƒ€์ž… ์ถ”๋ก ์œผ๋กœ ์ธํ•ด ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š์•„๋„ ๋ผ์š”
console.log(result2);  // [true, "TypeScript"]

์ด 'swap' ํ•จ์ˆ˜๋Š” ๋‘ ๊ฐœ์˜ ์ œ๋„ค๋ฆญ ํƒ€์ž… 'T'์™€ 'U'๋ฅผ ์‚ฌ์šฉํ•ด์š”. ์ด ํ•จ์ˆ˜๋Š” ํŠœํ”Œ์˜ ๋‘ ์š”์†Œ์˜ ์œ„์น˜๋ฅผ ๋ฐ”๊ฟ”์ฃผ๋Š” ์—ญํ• ์„ ํ•˜์ฃ .

์ œ๋„ค๋ฆญ์€ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์˜ ์˜ˆ๋ฅผ ๋“ค์–ด๋ณผ๊นŒ์š”?


interface Talent<T> {
  name: string;
  description: string;
  level: number;
  details: T;
}

interface MusicTalentDetails {
  instrument: string;
  genre: string;
}

interface ProgrammingTalentDetails {
  language: string;
  yearsOfExperience: number;
}

const musicTalent: Talent<MusicTalentDetails> = {
  name: "๊ธฐํƒ€ ์—ฐ์ฃผ",
  description: "๋ฝ๋ถ€ํ„ฐ ์žฌ์ฆˆ๊นŒ์ง€ ๋‹ค์–‘ํ•œ ์žฅ๋ฅด์˜ ๊ธฐํƒ€ ์—ฐ์ฃผ",
  level: 8,
  details: {
    instrument: "๊ธฐํƒ€",
    genre: "๋ฝ/์žฌ์ฆˆ"
  }
};

const programmingTalent: Talent<ProgrammingTalentDetails> = {
  name: "์›น ๊ฐœ๋ฐœ",
  description: "ํ”„๋ก ํŠธ์—”๋“œ๋ถ€ํ„ฐ ๋ฐฑ์—”๋“œ๊นŒ์ง€ ํ’€์Šคํƒ ์›น ๊ฐœ๋ฐœ",
  level: 9,
  details: {
    language: "TypeScript",
    yearsOfExperience: 5
  }
};

console.log(musicTalent);
console.log(programmingTalent);

์ด ์˜ˆ์ œ์—์„œ๋Š” 'Talent' ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ œ๋„ค๋ฆญ ํƒ€์ž… 'T'๋ฅผ ์‚ฌ์šฉํ•ด์š”. ์ด๋ฅผ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ์žฌ๋Šฅ์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์ฃ . ์Œ์•… ์žฌ๋Šฅ๊ณผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์žฌ๋Šฅ์€ ์„œ๋กœ ๋‹ค๋ฅธ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ๊ฐ€์ง€์ง€๋งŒ, ๊ฐ™์€ 'Talent' ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿง  Brain Teaser: ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์•„์ง€๊ณ , ํƒ€์ž… ์•ˆ์ •์„ฑ๋„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์–ด์š”. ํ•˜์ง€๋งŒ ๋„ˆ๋ฌด ๋งŽ์€ ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฃผ์˜ํ•ด์•ผ ํ•ด์š”!

์ œ๋„ค๋ฆญ์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ์žฌ๋Šฅ์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ๊ฐ ์žฌ๋Šฅ ์œ ํ˜•๋ณ„๋กœ ๋‹ค๋ฅธ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋™์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•ด ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ฃ . ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ƒˆ๋กœ์šด ์žฌ๋Šฅ ์œ ํ˜•์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋„ ์‰ฌ์›Œ์งˆ ๊ฑฐ์˜ˆ์š”! ๐ŸŽญ๐Ÿ‹๏ธโ€โ™€๏ธ๐ŸŽจ

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

6. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ (Decorators) ๐ŸŽ€

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

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด tsconfig.json ํŒŒ์ผ์—์„œ "experimentalDecorators" ์˜ต์…˜์„ ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•ด์š”.


{
  "compilerOptions": {  ๋„ค, ๊ณ„์†ํ•ด์„œ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์— ๋Œ€ํ•ด ์„ค๋ช…๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

<pre><code>
{
  "compilerOptions": {
    "experimentalDecorators": true
  }
}

์ด์ œ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•์„ ์‚ดํŽด๋ณผ๊นŒ์š”?


function logged(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyKey} with`, args);
    const result = originalMethod.apply(this, args);
    console.log(`${propertyKey} returned`, result);
    return result;
  };
  return descriptor;
}

class Calculator {
  @logged
  add(a: number, b: number): number {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(5, 3);
// ์ถœ๋ ฅ:
// Calling add with [5, 3]
// add returned 8

์ด ์˜ˆ์ œ์—์„œ '@logged' ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ์™€ ๋ฐ˜ํ™˜๋  ๋•Œ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•ด์š”. ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์ฝ”๋“œ์˜ ๋™์ž‘์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์ฃ .

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ๋‹ค์–‘ํ•œ ์šฉ๋„๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ํด๋ž˜์Šค ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ํด๋ž˜์Šค์— ์ƒˆ๋กœ์šด ์†์„ฑ์ด๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์ฃ .


function reportableClass(constructor: Function) {
  constructor.prototype.reportingURL = "http://www.example.com/report";
}

@reportableClass
class BugReport {
  type = "report";
  title: string;

  constructor(t: string) {
    this.title = t;
  }
}

const bug = new BugReport("Needs dark mode");
console.log((bug as any).reportingURL); // "http://www.example.com/report"

์ด ์˜ˆ์ œ์—์„œ '@reportableClass' ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” 'BugReport' ํด๋ž˜์Šค์— 'reportingURL' ์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์š”.

์žฌ๋Šฅ๋„ท ํ”Œ๋žซํผ์—์„œ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•˜๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด๋ณผ๊นŒ์š”?


function validateSkillLevel(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args: any[]) {
    const level = args[0];
    if (level < 1 || level > 10) {
      throw new Error("Skill level must be between 1 and 10");
    }
    return originalMethod.apply(this, args);
  };
  return descriptor;
}

class Talent {
  name: string;
  level: number;

  constructor(name: string) {
    this.name = name;
    this.level = 1;
  }

  @validateSkillLevel
  setSkillLevel(level: number) {
    this.level = level;
    console.log(`${this.name} skill level set to ${this.level}`);
  }
}

const coding = new Talent("Coding");
coding.setSkillLevel(7); // "Coding skill level set to 7"
// coding.setSkillLevel(11); // Error: Skill level must be between 1 and 10

์ด ์˜ˆ์ œ์—์„œ '@validateSkillLevel' ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ์Šคํ‚ฌ ๋ ˆ๋ฒจ์ด ์œ ํšจํ•œ ๋ฒ”์œ„ ๋‚ด์— ์žˆ๋Š”์ง€ ๊ฒ€์ฆํ•ด์š”. ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์ฃ .

๐ŸŽˆ Decorator Tip: ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ณ , ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”. ํ•˜์ง€๋งŒ ์•„์ง ์‹คํ—˜์  ๊ธฐ๋Šฅ์ด๋ฏ€๋กœ, ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•ด์š”!

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์žฌ๋Šฅ๋„ท ํ”Œ๋žซํผ์—์„œ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ํšจ์œจ์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž ์ธ์ฆ, ๋กœ๊น…, ์„ฑ๋Šฅ ์ธก์ • ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์ฃ . ๐Ÿ”๐Ÿ“Šโฑ๏ธ

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

๋งˆ์น˜๋ฉฐ ๐ŸŽฌ

์˜ค๋Š˜ ์šฐ๋ฆฌ๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํด๋ž˜์Šค์˜ ๋‹ค์–‘ํ•œ ํŠน์„ฑ๋“ค์„ ์‚ดํŽด๋ดค์–ด์š”. ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ์ ‘๊ทผ ์ œ์–ด์ž, ์ƒ์†, ์ธํ„ฐํŽ˜์ด์Šค, ์ œ๋„ค๋ฆญ, ๊ทธ๋ฆฌ๊ณ  ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๊นŒ์ง€, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํด๋ž˜์Šค์˜ ํ•ต์‹ฌ ๊ฐœ๋…๋“ค์„ ๋ชจ๋‘ ๋‹ค๋ค˜์ฃ .

์ด๋Ÿฌํ•œ ๊ฐœ๋…๋“ค์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ๋”์šฑ ์•ˆ์ „ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฌ์šด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ํŠนํžˆ ์žฌ๋Šฅ๋„ท๊ณผ ๊ฐ™์€ ๋ณต์žกํ•œ ํ”Œ๋žซํผ์„ ๊ฐœ๋ฐœํ•  ๋•Œ ์ด๋Ÿฐ ๊ฐœ๋…๋“ค์ด ํฐ ๋„์›€์ด ๋  ๊ฑฐ์˜ˆ์š”.

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

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

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

๐Ÿš€ Final Tip: ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ฐฐ์šฐ๋Š” ๊ณผ์ •์ด ๋•Œ๋กœ๋Š” ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์–ด์š”. ํ•˜์ง€๋งŒ ํฌ๊ธฐํ•˜์ง€ ๋งˆ์„ธ์š”! ๊พธ์ค€ํ•œ ์—ฐ์Šต๊ณผ ์‹ค์ œ ํ”„๋กœ์ ํŠธ ์ ์šฉ์„ ํ†ตํ•ด ์—ฌ๋Ÿฌ๋ถ„์€ ์ ์  ๋” ์ˆ™๋ จ๋œ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ํ™”์ดํŒ…! ๐Ÿ’ช