학습
TypeScript 객체 지향 프로그래밍 (OOP)
TypeScript 객체 지향 프로그래밍 (OOP) — 중급
객체 지향 프로그래밍 (OOP)
1. 도입 (왜 배워야 하는가)
객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 소프트웨어 개발에서 매우 중요한 개념입니다. OOP는 프로그램을 '객체'로 구성하여 코드의 재사용성과 유지보수성을 높이는 방법론입니다. 실제로 대규모 시스템 개발 시 OOP를 활용하면 협업이 용이하고, 코드 구조가 명확해져서 버그를 줄이는 데 도움이 됩니다.
만약 OOP를 모른다면, 복잡한 시스템을 관리하는 데 어려움을 겪을 수 있습니다. 예를 들어, 비슷한 기능을 여러 번 구현하게 되어 코드 중복이 발생하고, 이는 유지보수 시 큰 부담으로 작용할 수 있습니다. 또한, 코드의 가독성이 떨어져 팀원 간의 협업이 어려워질 수 있습니다.
2. 핵심 개념 설명
OOP의 주요 개념은 다음과 같습니다:
| 개념 | 정의 | 비유 |
|---|---|---|
| 클래스 | 객체의 설계도, 속성과 행동을 정의 | 자동차의 설계도 (모든 자동차는 엔진, 바퀴, 핸들이 있음) |
| 객체 | 클래스의 인스턴스, 실제로 메모리에 존재하는 실체 | 실제 자동차 (설계도에서 만들어진 차량) |
| 상속 | 클래스가 다른 클래스를 기반으로 새로운 클래스를 만드는 것 | 부모로부터 물려받은 성격 |
| 다형성 | 같은 인터페이스를 통해 다양한 객체를 다룰 수 있는 능력 | 여러 종류의 문서(워드, PDF)를 프린트할 수 있는 프린터 |
| 캡슐화 | 객체의 속성과 행동을 하나로 묶고 외부에서 접근을 제한 | 자동차 엔진을 외부에서 직접 조작할 수 없는 것 |
3. 기본 코드 예제
아래는 TypeScript로 클래스를 정의하고 객체를 생성하는 기본적인 예제입니다.
class Car {
// 속성
private brand: string;
private model: string;
// 생성자
constructor(brand: string, model: string) {
this.brand = brand;
this.model = model;
}
// 메서드
public displayInfo(): string {
return 차량 브랜드: ${this.brand}, 모델: ${this.model};
}
}
// 객체 생성
const myCar = new Car('현대', '아반떼');
console.log(myCar.displayInfo());
실행 결과:
차량 브랜드: 현대, 모델: 아반떼
코드 한 줄씩 동작 설명:
class Car { ... }:Car라는 클래스를 정의합니다.private brand: string; private model: string;: 차량 브랜드와 모델을 저장할 속성입니다.private는 외부에서 접근할 수 없도록 제한합니다.constructor(brand: string, model: string) { ... }: 객체를 생성할 때 브랜드와 모델을 초기화하는 생성자입니다.public displayInfo(): string { ... }: 차량 정보를 반환하는 메서드입니다.public은 외부에서 호출할 수 있음을 의미합니다.const myCar = new Car('현대', '아반떼');:Car클래스의 인스턴스를 생성합니다.console.log(myCar.displayInfo());: 차량 정보를 출력합니다.- 캡슐화의 미비: 속성을
public으로 선언하여 외부에서 직접 수정하는 경우. - 상속의 남용: 코드 중복을 피하기 위해 상속을 남용하는 경우.
- 다형성의 오해: 인터페이스를 잘못 이해하고 사용하는 경우.
- OOP는 재사용성과 유지보수성을 높이는 중요한 프로그래밍 패러다임입니다.
- 클래스, 객체, 상속, 다형성, 캡슐화는 OOP의 핵심 개념입니다.
- 실무에서는 장바구니, 게임 캐릭터 등 다양한 패턴으로 활용됩니다.
- 다음에 학습하면 좋은 주제로는 디자인 패턴, SOLID 원칙, TypeScript의 고급 타입 등이 있습니다.
4. 실전 활용 예제
쇼핑몰에서 장바구니를 구현할 때
장바구니는 상품을 담아두는 역할을 하며, 여러 상품을 객체로 관리할 수 있습니다. 아래는 장바구니를 구현한 예제입니다.
class Product {
constructor(public name: string, public price: number) {}
}
class ShoppingCart {
private items: Product[] = [];
public addItem(item: Product): void {
this.items.push(item);
}
public getTotalPrice(): number {
return this.items.reduce((total, item) => total + item.price, 0);
}
}
// 사용 예
const cart = new ShoppingCart();
cart.addItem(new Product('신발', 50000));
cart.addItem(new Product('모자', 15000));
console.log(총 금액: ${cart.getTotalPrice()}원);
실행 결과:
총 금액: 65000원
게임 캐릭터 시스템 구현
게임에서 캐릭터는 상속을 통해 다양한 특성을 가질 수 있습니다.
class Character {
constructor(public name: string) {}
public attack(): string {
return ${this.name}이(가) 공격했습니다!;
}
}
class Warrior extends Character {
public attack(): string {
return ${this.name}이(가) 검으로 공격했습니다!;
}
}
// 사용 예
const hero = new Warrior('전사');
console.log(hero.attack());
실행 결과:
전사이(가) 검으로 공격했습니다!
5. 흔한 실수와 주의사항
- 잘못된 코드:
class User {
public age: number;
constructor(age: number) {
this.age = age;
}
}
- 올바른 코드:
class User {
private age: number;
constructor(age: number) {
this.age = age;
}
public getAge(): number {
return this.age;
}
}
- 잘못된 코드: 여러 클래스를 같은 기능을 위해 상속받는 경우. - 올바른 코드: 공통 기능을 가진 기본 클래스를 만들고 이를 상속받는 방법.
- 잘못된 코드: 서로 다른 기능을 가진 클래스를 같은 인터페이스로 강제로 묶는 경우. - 올바른 코드: 공통된 기능을 가진 인터페이스를 정의하고, 각 클래스에서 구현.