들어가며
타입스크립트는 인터페이스(Interface)와 클래스(Class)를 통해 객체의 구조와 동작을 명확히 정의할 수 있습니다. 인터페이스는 데이터 구조를 정의하고, 클래스는 객체의 상태와 행동을 구현합니다. 객체지향 프로그래밍(OOP) 패러다임을 따르는 타입스크립트는 상속, 캡슐화, 다형성과 같은 개념을 활용해 복잡한 애플리케이션을 설계할 수 있도록 돕습니다.
이번 글에서는 인터페이스와 클래스의 개념, 활용법, 그리고 이를 활용한 실용적인 예제를 다룹니다.
1. 인터페이스(Interface)
1-1. 인터페이스란 무엇인가?
인터페이스는 객체의 구조를 정의하는 데 사용됩니다. 이를 통해 객체가 가져야 할 속성과 메서드를 지정할 수 있습니다.
[typescript]
interface User {
id: number;
name: string;
email?: string; // 선택적 속성
}
const user: User = {
id: 1,
name: 'Alice',
};
- 필수 속성 : id, name은 반드시 포함되어야 합니다.
- 선택적 속성(Optional) : email?은 존재할 수도, 존재하지 않을 수도 있습니다.
1-2. 메서드를 포함한 인터페이스
인터페이스는 메서드 시그니처를 정의할 수 있습니다.
[typescript]
interface User {
id: number;
name: string;
greet(): string;
}
const user: User = {
id: 1,
name: 'Alice',
greet() {
return `Hello, ${this.name}!`;
},
};
console.log(user.greet());
1-3. 읽기 전용 속성
readonly를 사용하여 속성을 읽기 전용으로 설정할 수 있습니다.
[typescript]
interface Config {
readonly apiKey: string;
}
const config: Config = {
apiKey: '12345',
};
// config.apiKey = '67890'; // 오류! 읽기 전용 속성은 변경 불가
1-4. 인덱스 시그니처(Index Signature)
인덱스 시그니처를 사용하면 동적으로 속성을 정의할 수 있습니다.
[typescript]
interface Dictionary {
[key: string]: string;
}
const dict: Dictionary = {
hello: '안녕하세요',
world: '세계',
};
2. 클래스(Class)
2-1. 클래스 기본 구조
타입스크립트의 클래스는 ES6 클래스 문법을 확장하여 타입 안전성을 제공합니다.
[typescript]
class User {
id: number;
name: string;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
greet(): string {
return `Hello, ${this.name}!`;
}
}
const user = new User(1, 'Alice');
console.log(user.greet());
2-2. 접근 제어자(Access Modifiers)
클래스의 속성과 메서드는 접근 제어자를 통해 가시성을 제어할 수 있습니다.
- public : 기본값으로 어디서나 접근 가능
- private : 클래스 내부에서만 접근 가능
- protected : 클래스 내부 및 상속받은 클래스에서만 접근 가능
[typescript]
class Employee {
private id: number;
public name: string;
protected department: string;
constructor(id: number, name: string, department: string) {
this.id = id;
this.name = name;
this.department = department;
}
getId(): number {
return this.id;
}
}
const emp = new Employee(1, 'Alice', 'IT');
console.log(emp.name); // 접근 가능
// console.log(emp.id); // 오류! private 속성
2-3. 클래스 상속과 인터페이스 구현
클래스는 다른 클래스를 상속받거나 인터페이스를 구현할 수 있습니다.
[typescript]
interface Greetable {
greet(): string;
}
class User implements Greetable {
name: string;
constructor(name: string) {
this.name = name;
}
greet(): string {
return `Hello, ${this.name}!`;
}
}
class Admin extends User {
permissions: string[];
constructor(name: string, permissions: string[]) {
super(name);
this.permissions = permissions;
}
greet(): string {
return `Admin ${this.name} with permissions: ${this.permissions.join(', ')}`;
}
}
const admin = new Admin('Bob', ['read', 'write']);
console.log(admin.greet());
3. 추상 클래스(Abstract Class)와 다형성(Polymorphism)
3-1. 추상 클래스란?
추상 클래스는 인스턴스를 생성할 수 없으며, 자식 클래스에서 반드시 구현해야 하는 추상 메서드를 포함할 수 있습니다.
[typescript]
abstract class Animal {
abstract sound(): string;
move(): void {
console.log('Moving...');
}
}
class Dog extends Animal {
sound(): string {
return 'Woof!';
}
}
const dog = new Dog();
console.log(dog.sound());
dog.move();
3-2. 다형성
다형성은 같은 메서드가 다른 클래스에서 다르게 동작하도록 합니다. 추상 클래스나 인터페이스를 활용하여 이를 구현할 수 있습니다.
[typescript]
abstract class Shape {
abstract area(): number;
}
class Circle extends Shape {
constructor(public radius: number) {
super();
}
area(): number {
return Math.PI * this.radius ** 2;
}
}
class Rectangle extends Shape {
constructor(public width: number, public height: number) {
super();
}
area(): number {
return this.width * this.height;
}
}
const shapes: Shape[] = [new Circle(5), new Rectangle(10, 20)];
shapes.forEach(shape => console.log(shape.area()));
예제 : API 응답 데이터 타입 정의 및 클래스 설계
문제
다음은 간단한 REST API 응답 데이터입니다. 이 데이터를 타입스크립트로 안전하게 처리하려면 인터페이스와 클래스를 사용해 데이터를 정의하고 관리해야 합니다.
[json]
{
"id": 1,
"title": "Task 1",
"completed": false
}
[typescript]
interface Todo {
id: number;
title: string;
completed: boolean;
}
class TodoManager {
private todos: Todo[] = [];
add(todo: Todo): void {
this.todos.push(todo);
}
list(): Todo[] {
return this.todos;
}
}
const manager = new TodoManager();
manager.add({ id: 1, title: 'Task 1', completed: false });
console.log(manager.list());
마무리
인터페이스와 클래스는 타입스크립트의 강력한 기능 중 하나로, 구조적 타이핑과 객체지향 설계를 가능하게 합니다. 인터페이스를 통해 데이터 구조를 정의하고, 클래스를 통해 객체의 행동을 구현하면, 코드의 재사용성과 유지보수성이 크게 향상됩니다.
다음 단계에서는 고급 타입(제네릭, 매핑 타입, 조건부 타입)을 학습하여 더욱 복잡한 타입 로직을 작성하는 방법을 알아보겠습니다.
'프로그래밍 > Typescript' 카테고리의 다른 글
[Typescript] 모듈과 네임스페이스, 선언 병합 : 대규모 프로젝트 구조화 (1) | 2024.12.24 |
---|---|
[Typescript] 고급 타입 : 제네릭, 매핑 타입, 조건부 타입 (0) | 2024.12.21 |
[Typescript] 타입 시스템 이해 : 정적 타입으로 안전한 코드 작성 (2) | 2024.12.18 |
[Typescript] 타입스크립트 기초 입문 : 타입스크립트를 시작하기 위한 첫걸음 (2) | 2024.12.15 |