TypeScript 접근 제어자(public, private, protected)와 상속 (15강)
TypeScript 접근 제어자(public, private, protected)와 상속 (15강)
**TypeScript**는 객체지향 프로그래밍(OOP)을 지원하며, **클래스**와 **상속**을 통해 재사용 가능하고 효율적인 코드를 작성할 수 있습니다. 그 중에서 중요한 개념 중 하나는 **접근 제어자(Access Modifiers)**입니다. 접근 제어자는 클래스의 **속성**과 **메서드**에 대한 접근을 제한할 수 있도록 도와줍니다. 이번 강의에서는 **TypeScript 접근 제어자**와 **상속**에 대해 자세히 알아보겠습니다.
TypeScript 접근 제어자란?
**접근 제어자**는 클래스의 속성과 메서드에 대한 접근을 제어하는 키워드입니다. TypeScript는 다음과 같은 세 가지 접근 제어자를 제공합니다:
- public: 모든 클래스 외부에서 접근 가능
- private: 클래스 내부에서만 접근 가능
- protected: 클래스 내부와 이를 상속받은 클래스에서만 접근 가능
이들 접근 제어자는 객체의 **캡슐화**를 구현하는 데 중요한 역할을 하며, 클래스 외부에서 **불필요한 접근**을 방지할 수 있습니다. 각각의 접근 제어자에 대해 자세히 알아보겠습니다.
1. public 접근 제어자
**public**은 **기본 접근 제어자**입니다. 클래스의 속성과 메서드가 **public**으로 선언되면, 해당 속성과 메서드는 **어디서든지 접근**할 수 있습니다. TypeScript에서 접근 제어자를 명시하지 않으면, 기본적으로 **public**으로 간주됩니다.
class Car {
public model: string;
constructor(model: string) {
this.model = model;
}
public drive(): void {
console.log(`${this.model} is driving.`);
}
}
const myCar = new Car("Tesla");
console.log(myCar.model); // "Tesla"
myCar.drive(); // "Tesla is driving."
위 예제에서 **Car** 클래스의 속성 **model**과 메서드 **drive**는 **public**으로 선언되어 있기 때문에, 클래스 외부에서 자유롭게 접근하고 호출할 수 있습니다.
2. private 접근 제어자
**private**은 클래스 내부에서만 접근할 수 있는 속성과 메서드를 정의하는 데 사용됩니다. **private**으로 선언된 속성이나 메서드는 클래스 외부에서 접근할 수 없습니다. 이를 통해 클래스의 내부 구현을 외부에 노출하지 않고, **캡슐화**를 구현할 수 있습니다.
class BankAccount {
private balance: number;
constructor(balance: number) {
this.balance = balance;
}
public deposit(amount: number): void {
if (amount > 0) {
this.balance += amount;
}
}
public getBalance(): number {
return this.balance;
}
}
const account = new BankAccount(1000);
console.log(account.balance); // 오류 발생: private 속성 접근 불가
console.log(account.getBalance()); // 1000
위 예제에서 **balance** 속성은 **private**으로 선언되어 외부에서 직접 접근할 수 없습니다. 대신 **deposit**과 **getBalance** 메서드를 통해 안전하게 **balance**를 수정하거나 조회할 수 있습니다.
3. protected 접근 제어자
**protected**는 **private**과 유사하지만, 한 가지 중요한 차이점이 있습니다. **protected**로 선언된 속성이나 메서드는 **자식 클래스**에서 접근할 수 있습니다. 즉, 부모 클래스에서 **protected**로 선언된 속성이나 메서드는 자식 클래스에서 **상속**받아 사용할 수 있습니다.
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
public greet(): void {
console.log(`Hello, my name is ${this.name}`);
}
}
class Dog extends Animal {
public bark(): void {
console.log(`${this.name} barks.`);
}
}
const dog = new Dog("Rex");
console.log(dog.name); // 오류 발생: protected 속성 접근 불가
dog.bark(); // "Rex barks."
위 예제에서 **name** 속성은 **protected**로 선언되어, **Dog** 클래스에서 상속받은 후에는 **접근**할 수 있지만, 외부에서는 접근할 수 없습니다. 이를 통해 **상속 관계**에서 속성과 메서드를 안전하게 공유할 수 있습니다.
TypeScript에서 상속(Inheritance)
**상속(Inheritance)**은 객체지향 프로그래밍에서 중요한 개념으로, **부모 클래스**의 속성과 메서드를 **자식 클래스**가 상속받아 **재사용**하고 **확장**할 수 있습니다. TypeScript에서 클래스 상속은 **extends** 키워드를 사용하여 구현할 수 있습니다.
1. 부모 클래스와 자식 클래스
TypeScript에서 클래스 상속을 사용하면, 자식 클래스는 부모 클래스의 **속성**과 **메서드**를 상속받을 수 있습니다. 자식 클래스는 부모 클래스에서 상속받은 기능을 재사용할 수 있으며, 필요한 경우 기능을 **오버라이드(재정의)**할 수 있습니다.
class Vehicle {
public brand: string;
constructor(brand: string) {
this.brand = brand;
}
public displayBrand(): void {
console.log(`Brand: ${this.brand}`);
}
}
class Car extends Vehicle {
public model: string;
constructor(brand: string, model: string) {
super(brand); // 부모 클래스의 생성자 호출
this.model = model;
}
public displayModel(): void {
console.log(`Model: ${this.model}`);
}
}
const myCar = new Car("Toyota", "Corolla");
myCar.displayBrand(); // "Brand: Toyota"
myCar.displayModel(); // "Model: Corolla"
위 예제에서 **Car** 클래스는 **Vehicle** 클래스를 상속받고 있습니다. **super(brand)**를 사용하여 부모 클래스의 생성자를 호출하고, 부모 클래스의 **displayBrand** 메서드를 재사용하며, 자식 클래스에서 **displayModel** 메서드를 추가하여 기능을 확장하고 있습니다.
2. 상속과 접근 제어자
상속을 사용할 때, **protected**로 선언된 속성이나 메서드는 자식 클래스에서 **접근**할 수 있지만, **private**으로 선언된 속성이나 메서드는 자식 클래스에서도 **접근할 수 없습니다**. 이를 통해 상속 관계에서의 **접근 제한**을 조절할 수 있습니다.
class Person {
private name: string;
protected age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public getName(): string {
return this.name;
}
}
class Employee extends Person {
private position: string;
constructor(name: string, age: number, position: string) {
super(name, age);
this.position = position;
}
public getPosition(): string {
return this.position;
}
public getAge(): number {
return this.age; // protected 속성은 자식 클래스에서 접근 가능
}
}
const emp = new Employee("Alice", 30, "Developer");
console.log(emp.getPosition()); // "Developer"
console.log(emp.getAge()); // 30
위 예제에서 **Person** 클래스의 **name** 속성은 **private**로 선언되어 자식 클래스에서 접근할 수 없고, **age** 속성은 **protected**로 선언되어 자식 클래스에서 접근할 수 있습니다. 이를 통해 **상속 관계**에서 속성에 대한 접근을 유연하게 제어할 수 있습니다.
TypeScript에서 접근 제어자와 상속을 활용한 객체지향 프로그래밍
**접근 제어자(public, private, protected)**와 **상속**은 객체지향 프로그래밍에서 코드의 **캡슐화**와 **재사용성**을 높이는 중요한 개념입니다. TypeScript는 이러한 개념을 강력하게 지원하여, 코드의 안정성과 유지보수성을 향상시킬 수 있습니다. 이번 강의를 통해 **접근 제어자**와 **상속**을 활용하여 더 안전하고 효율적인 객체지향 프로그래밍을 구현할 수 있기를 바랍니다.
마무리: 객체지향 프로그래밍의 발전
객체지향 프로그래밍(OOP)은 복잡한 시스템을 체계적으로 관리하고, 코드를 효율적으로 확장할 수 있는 중요한 패러다임입니다. **TypeScript**에서 제공하는 **접근 제어자**와 **상속**을 활용하면 더욱 안전하고 확장 가능한 코드를 작성할 수 있습니다. 다음 강의에서는 **인터페이스**와 **제네릭**을 사용하여 더 강력하고 유연한 코드 구조를 만드는 방법을 배우겠습니다.