1. 인터페이스의 역할
인터페이스는 타입스크립트에서 클래스의 설계도 역할을 합니다. 인터페이스는 클래스가 가져야 할 **속성(필드)**과 메서드를 정의하여 클래스가 이 규칙을 따르게 합니다. 이렇게 하면 코드의 일관성을 유지하고, 클래스들이 특정 구조를 준수하도록 강제할 수 있습니다.
2. 인터페이스와 클래스의 관계
타입스크립트에서 클래스가 인터페이스를 "구현"하는 것을 implements 키워드를 사용해 표현합니다. **implements**는 클래스가 해당 인터페이스에서 정의된 모든 속성과 메서드를 구현해야 한다는 의미입니다. 만약 클래스가 인터페이스에서 정의한 내용들을 구현하지 않으면, 컴파일 시 오류가 발생합니다. 이렇게 강제함으로써 타입 안정성을 보장할 수 있습니다.
예제를 통해 더 자세히 보겠습니다.
예제: 인터페이스와 클래스를 활용한 구현
interface CharacterInterface {
name: string; // 캐릭터의 이름 (문자열)
moveSpeed: number; // 이동 속도 (숫자)
move(): void; // 이동 동작을 정의한 메서드 (반환값 없음)
}
class Character implements CharacterInterface {
// 생성자에서 public, private 키워드로 필드 정의 및 초기화
constructor(
public name: string, // public: 외부에서 접근 가능
public moveSpeed: number, // public: 외부에서 접근 가능
private extra: string // private: 클래스 내부에서만 접근 가능
) {}
// 인터페이스에 정의된 move 메서드를 구현
move(): void {
console.log(`${this.moveSpeed} 속도로 이동!`);
}
}
const character = new Character("Warrior", 10, "ExtraPower");
character.move(); // 출력: 10 속도로 이동!
위 예제에서 살펴보면 다음과 같은 구조가 있습니다.
1. 인터페이스 정의 (CharacterInterface)
interface CharacterInterface {
name: string;
moveSpeed: number;
move(): void;
}
- 이 인터페이스는 name과 moveSpeed라는 필드와 move()라는 메서드를 갖고 있습니다.
- 인터페이스는 구체적인 구현을 갖지 않으며, 필드와 메서드의 구조만 정의합니다.
- 다른 클래스나 객체가 이 구조를 따르도록 강제합니다.
2. 클래스 구현 (Character)
class Character implements CharacterInterface {
constructor(
public name: string,
public moveSpeed: number,
private extra: string
) {}
move(): void {
console.log(`${this.moveSpeed} 속도로 이동!`);
}
}
- implements CharacterInterface: 이 부분은 Character 클래스가 인터페이스를 구현하겠다는 선언입니다. 이를 통해 Character 클래스는 인터페이스에서 정의된 모든 필드와 메서드를 가져야 합니다.
- 필드와 생성자:
- public name: name 필드는 public 접근 제어자가 붙어서 외부에서 자유롭게 접근할 수 있습니다. 인터페이스에서 정의된 name: string을 충족합니다.
- public moveSpeed: moveSpeed도 인터페이스의 moveSpeed: number를 만족하며, 외부에서 접근 가능합니다.
- private extra: extra는 인터페이스에 포함되지 않았지만 클래스 자체에서 추가한 필드입니다. private로 선언되어 클래스 외부에서는 접근할 수 없습니다.
- move() 메서드:
- 인터페이스에서 정의된 move(): void 메서드를 구현합니다.
- console.log를 통해 이동 속도를 출력합니다.
- 이렇게 인터페이스에서 요구하는 모든 필드와 메서드를 충족하지 않으면, 타입스크립트는 컴파일 오류를 발생시킵니다.
3. 구현된 클래스 사용
const character = new Character("Warrior", 10, "ExtraPower");
character.move(); // 출력: 10 속도로 이동!
- new Character()를 통해 인스턴스를 생성합니다.
- name과 moveSpeed는 인터페이스에 정의된 필드이므로 클래스 외부에서 접근 가능합니다.
- **character.move()**를 호출하면 "10 속도로 이동!"이라는 문자열을 출력합니다.
3. 인터페이스를 사용해야 하는 이유
인터페이스를 이용하면 다음과 같은 장점이 있습니다.
- 타입 안전성: 클래스가 특정 형식을 반드시 따라야 하므로, 코드의 일관성을 보장하고 컴파일 시점에 오류를 미리 잡아낼 수 있습니다.
- 유연한 설계: 인터페이스는 다양한 클래스가 특정 구조를 구현하도록 유도할 수 있습니다. 예를 들어, 여러 개의 캐릭터 클래스(Mage, Archer 등)가 CharacterInterface를 구현하면, 각 캐릭터는 서로 다른 구현을 가질 수 있지만, 일관된 형태의 필드와 메서드를 가집니다.
- 다형성: 인터페이스를 타입으로 사용하면 다형성을 활용할 수 있습니다. 예를 들어, 어떤 함수가 CharacterInterface를 요구할 때, 해당 인터페이스를 구현하는 모든 클래스의 인스턴스를 그 함수의 인자로 전달할 수 있습니다.
예제: 인터페이스를 이용한 다형성
function moveCharacter(character: CharacterInterface) {
character.move();
}
const mage = new Character("Mage", 8, "MagicStaff");
moveCharacter(mage); // 출력: 8 속도로 이동!
- 함수 moveCharacter는 CharacterInterface를 요구합니다.
- 이 인터페이스를 구현하는 Character 클래스의 인스턴스인 mage를 전달하여, 다형성을 통해 여러 타입의 객체를 유연하게 처리할 수 있습니다.
정리
- 인터페이스는 클래스의 설계도를 제공합니다.
- 클래스가 인터페이스를 **implements**로 구현하면, 인터페이스에서 정의된 모든 필드와 메서드를 강제로 구현해야 합니다.
- 이를 통해 일관된 구조를 가지며, 컴파일 시점에 타입 오류를 방지할 수 있습니다.
- 인터페이스를 사용하면 코드의 유연성과 유지보수성이 향상되며, 다양한 클래스들이 같은 인터페이스를 구현하여 다형성을 활용할 수 있습니다.
타입스크립트에서 인터페이스를 사용하여 클래스의 구현을 명확하게 정의하고, 구조적 일관성을 강제하는 것이 큰 장점입니다. 인터페이스와 클래스를 잘 활용하면 안전하고 유지보수하기 쉬운 코드를 작성할 수 있습니다.
'TypeScript' 카테고리의 다른 글
TypeScript 제네릭2 (0) | 2024.10.29 |
---|---|
TypeScript 제네릭1 (1) | 2024.10.29 |
TypeScript 클래스 (1) | 2024.10.29 |
JavaScript this정리 (0) | 2024.10.29 |
자바스크립트, 타입스크립트 스코프,호이스팅 (2) | 2024.10.29 |