๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Language/TypeScript

[TypeScript] Class vs Interface vs Type ์ฐจ์ด์  ์ •๋ฆฌ

 

 

JavaScript Class vs TypeScript Class

 

1. ์†์„ฑ ์ดˆ๊ธฐํ™” ์ฝ”๋“œ๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.

  • TS Class๋Š” ์ƒ์„ฑ์ž์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž… ์„ ์–ธ๊ณผ ๋™์‹œ์— ์ ‘๊ทผ ์ œ์–ด์ž(+readonly)๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ์†์„ฑ ์ดˆ๊ธฐํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด๋•Œ๋Š” ์†์„ฑ์ด public์ด์–ด๋„ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค.
// JS
class User {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
}
// TS
// ์ปดํŒŒ์ผํ•˜๋ฉด ์œ„ JS ์ฝ”๋“œ์™€ ๋™์ผํ•˜๋‹ค
class User {
  constructor(private firstName: string, private lastName: string) {}
}

 

2. ์ ‘๊ทผ ์ œํ•œ์ž(access modifier)๋ฅผ ์ง€์›ํ•œ๋‹ค.

  • ์ ‘๊ทผ ์ œํ•œ์ž๋Š” TS ์ŠคํŽ™์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ปดํŒŒ์ผํ•˜๋ฉด ์‚ฌ๋ผ์ง„๋‹ค.
  • JS์—์„œ๋Š” private๊ณผ ๊ฐ™์€ ์šฉ๋„๋กœ # prefix๋ฅผ ๋ถ™์ธ๋‹ค.
  • TS ์ ‘๊ทผ ์ œํ•œ์ž์—๋Š” public, protected, private์ด ์žˆ๋‹ค.
    • public : ์–ด๋””์„œ๋‚˜ ์ž์œ ๋กญ๊ฒŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
    • protected : ๋‚ด ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•œ ์ž์‹ ํด๋ž˜์Šค ๋‚ด์—์„œ ๊นŒ์ง€๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
    • private : ๋‚ด ํด๋ž˜์Šค์—์„œ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
  • JS, TS ๋ชจ๋‘ ์ ‘๊ทผ ์ œํ•œ์ž๋ฅผ ์ƒ๋žตํ•˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ public์ด๋‹ค.

 

3. ์ถ”์ƒ ํด๋ž˜์Šค(abstract class)๋ฅผ ์ง€์›ํ•œ๋‹ค.

  • ์ถ”์ƒ ํด๋ž˜์Šค๋Š” TS ์ŠคํŽ™์ด๋‹ค. ์ปดํŒŒ์ผํ•˜๋ฉด abstract ํ‚ค์›Œ๋“œ๊ฐ€ ์‚ฌ๋ผ์ง„ ์ผ๋ฐ˜ ํด๋ž˜์Šค๊ฐ€ ๋œ๋‹ค.
  • ์ƒ์†๋ฐ›๋Š” ํด๋ž˜์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•ด์•ผํ•  ์ง€ ์•Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•œ ํด๋ž˜์Šค๋กœ, interface์™€ ์œ ์‚ฌํ•˜๋‹ค.
    • interface๊ฐ€ ํด๋ž˜์Šค๋‚˜ ๊ฐ์ฒด์˜ ๋ผˆ๋Œ€๋ฅผ ๋งŒ๋“ ๋‹ค๋ฉด, ์ถ”์ƒ ํด๋ž˜์Šค๋Š” ํด๋ž˜์Šค ์ „์šฉ์œผ๋กœ ํด๋ž˜์Šค์˜ ๋ผˆ๋Œ€๋ฅผ ๋งŒ๋“œ๋Š” ์—ญํ• ์ด๋‹ค.
  • ํ•˜์ง€๋งŒ abstract class๋กœ๋Š” ์ง์ ‘ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค. extends ํ‚ค์›Œ๋“œ๋กœ ์ž์‹ ํด๋ž˜์Šค์— ์ƒ์†์‹œ์ผœ์•ผ ํ•œ๋‹ค.
  • ์†์„ฑ์ด๋‚˜ ๋ฉ”์„œ๋“œ ์•ž์— abstract ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์—ฌ์„œ ๋‚˜๋ฅผ ์ƒ์†ํ•˜๋Š” ๋‹ค๋ฅธ ํด๋ž˜์Šค์—์„œ ์ด ์†์„ฑ์ด๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ฒŒ ํ•œ๋‹ค.
    • ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋Š” ์ถ”์ƒ ํด๋ž˜์Šค์— ์„ ์–ธ๋˜๋Š” ๋ฉ”์„œ๋“œ๋กœ, call signature๋งŒ ์ž‘์„ฑํ•œ๋‹ค.
    • ์ถ”์ƒ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” ์ž์‹ ํด๋ž˜์Šค๋Š” ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.
abstract class User {
  constructor(protected firstName: string, protected lastName: string) {}

  abstract getFullName(): void;
}

class Player extends User {
  constructor(private firstName: string, private lastName: string) {}

  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}
const player = new Player("Timothee", "Chalamet");
player.getFullName();

 


Interface

  • interface๋Š” ํด๋ž˜์Šค๋‚˜ ๊ฐ์ฒด์˜ ๋ชจ์–‘์„ ๋งŒ๋“ค์–ด์ค€๋‹ค.
  • interface๋Š” TS ์ŠคํŽ™์œผ๋กœ, ์ปดํŒŒ์ผํ•˜๋ฉด ์‚ฌ๋ผ์ง„๋‹ค.
  • interface๋Š” ์„ ์–ธ์„ ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ๋‹ค.
interface User {
  firstName: string
}

interface User {
  lastName: string
}

interface User {
  health: number
}

const user: User {
  firstName: "Timothee",
  lastName: "Chalamet",
  health: 10
}
  • extends ํ‚ค์›Œ๋“œ๋กœ interface๋ฅผ ํ™•์žฅํ•˜์—ฌ ์ƒˆ๋กœ์šด interface๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
interface Animal {
  name: string;
}

interface Bear extends Animal {
  honey: boolean;
}

const bear = getBear();
bear.name;
bear.honey;

 


Type

  • type์€ ๊ฐ์ฒด์˜ ๋ชจ์–‘์„ ๋งŒ๋“ค๊ฑฐ๋‚˜, ํŠน์ • ๊ฐ’์„ ๊ฐ€์ง€๋„๋ก ์ œํ•œํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
  • type์€ TS ์ŠคํŽ™์œผ๋กœ, ์ปดํŒŒ์ผํ•˜๋ฉด ์‚ฌ๋ผ์ง„๋‹ค.
  • type์€ ํƒ€์ž… ๋ณ„์นญ(type alias)์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
type Health = 1 | 5 | 10;
type Team = "red" | "yellow" | "blue";

type Player = {
  healthBar: number;
  team: Team;
};

const player: Player = {
  healthBar: 10,
  team: "blue",
};
  • & ๋กœ type์„ ํ™•์žฅํ•˜์—ฌ ์ƒˆ๋กœ์šด type์„ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ๋‹ค.
type Animal = {
  name: string;
};

type Bear = Animal & {
  honey: boolean;
};

const bear = getBear();
bear.name;
bear.honey;

 


Abstract class vs Interface

๊ณตํ†ต์ 

  • ๋‘˜ ๋‹ค ํด๋ž˜์Šค์˜ ๋ชจ์–‘์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฐจ์ด์ 

  • Abstract class๋Š” ์ปดํŒŒ์ผํ•˜๋ฉด ์ผ๋ฐ˜ ํด๋ž˜์Šค๊ฐ€ ๋˜๊ณ , Interface๋Š” ์ปดํŒŒ์ผํ•˜๋ฉด ์‚ฌ๋ผ์ง„๋‹ค.
  • ๋‹ค์ค‘ ์ƒ์†์„ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํด๋ž˜์Šค๋Š” ํ•˜๋‚˜์˜ Abstract class๋งŒ ์ƒ์†(extends)ํ•  ์ˆ˜ ์žˆ๊ณ ,
    ๋‹ค์ค‘ ๊ตฌํ˜„์„ ์ง€์›ํ•˜๋ฏ€๋กœ ์—ฌ๋Ÿฌ ๊ฐœ์˜ interface๋กœ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„(implements)ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Abstract class๋Š” ์ถ”์ƒ ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹Œ ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ์—๋Š” ๊ตฌํ˜„์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์ง€๋งŒ,
    Interface๋Š” ๋ฉ”์„œ๋“œ์— ๊ตฌํ˜„์„ ํฌํ•จํ•  ์ˆ˜ ์—†๊ณ  call signature๋งŒ ์จ์•ผ ํ•œ๋‹ค.

๊ฒฐ๋ก 

  • ํด๋ž˜์Šค์˜ ๋ชจ์–‘์„ ์ •์˜ํ•  ๋•Œ
    ๊ณตํ†ต๋œ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๋„๋ก ๊ตฌํ˜„ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค๋ฉด abstract class๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
    ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์ปดํŒŒ์ผํ•˜๋ฉด ์‚ฌ๋ผ์ง€๋Š” interface๋ฅผ ์‚ฌ์šฉํ•˜๊ธธ ๊ถŒ์žฅํ•œ๋‹ค.

 


Interface vs Type

๊ณตํ†ต์ 

  • ๋‘˜ ๋‹ค ๊ฐ์ฒด์˜ ๋ชจ์–‘์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ปดํŒŒ์ผํ•˜๋ฉด ์‚ฌ๋ผ์ง„๋‹ค.
  • abstract class๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋‹ค.
type PlayerA = {
  firstName: string;
};

interface PlayerB {
  firstName: string;
}

class User implements PlayerA {
  constructor(public firstName: string) {}
}
// ๋˜๋Š”
class User implements PlayerB {
  constructor(public firstName: string) {}
}

์ฐจ์ด์ 

  • ์ •์˜ํ•˜๋Š” ๋ฐฉ์‹์ด ๋‹ค๋ฅด๋‹ค.
    • interface Y { }
    • type X = { }
  • ํ™•์žฅ ๋ฐฉ์‹์ด ๋‹ค๋ฅด๋‹ค.
    • interface A extends B { }
    • type A = B & { }
  • interface๋Š” ์—ฌ๋Ÿฌ ๋ฒˆ์˜ ์„ ์–ธ์„ ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, type์€ ์„ ์–ธ์„ ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์—†๋‹ค.
  • type์€ ํŠน์ • ๊ฐ’์œผ๋กœ ํƒ€์ž…์„ ์ œํ•œํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ํ™œ์šฉ๋„๊ฐ€ ์ข€ ๋” ๋†’๋‹ค.

๊ฒฐ๋ก 

  • interface๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๊ฐœ๋…์„ ํ™œ์šฉํ•ด์„œ ๋””์ž์ธ๋˜์—ˆ๊ณ , type์€ ์ข€ ๋” ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํด๋ž˜์Šค๋‚˜ ๊ฐ์ฒด์˜ ๋ชจ์–‘์„ ์ •์˜ํ•˜๊ณ  ์‹ถ์œผ๋ฉด interface,
    ์ด์™ธ์—๋Š” ํƒ€์ž… ๋ณ„์นญ์ด๋‚˜ ํŠน์ •๊ฐ’์œผ๋กœ ํƒ€์ž…์„ ์ œํ•œํ•˜๋Š” ๊ฒฝ์šฐ type ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•œ๋‹ค.

 

์ฐธ๊ณ 

โŒœDo it! ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ๊ทธ๋ž˜๋ฐโŒŸ - ์ „์˜ˆํ™

โŒœํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋กœ ๋ธ”๋ก์ฒด์ธ ๋งŒ๋“ค๊ธฐโŒŸ - Nomad Coders ๊ฐ•์˜

๐Ÿ“˜ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํด๋ž˜์Šค · ๊ฐ์ฒด ์ง€ํ–ฅ ๋ฌธ๋ฒ• ๐Ÿ’ฏ ์ด์ •๋ฆฌ

private, protected ํ”„๋กœํผํ‹ฐ์™€ ๋ฉ”์„œ๋“œ

TypeScript - ์ธํ„ฐํŽ˜์ด์Šค vs ์ถ”์ƒ ํด๋ž˜์Šค

Differences Between Type Aliases and Interfaces