TypeScript의 interface
는 객체의 형태를 정의하는 데 사용되는 구조적 계약입니다. 자바스크립트는 동적 타이핑 언어이기 때문에 객체가 어떤 속성을 가지는지 명확하게 알 수 없지만, TypeScript에서는 인터페이스를 통해 객체의 구조를 미리 정의하고 이를 바탕으로 코드의 안정성과 일관성을 유지할 수 있습니다.
주요 특징 및 사용법
1. 기본 사용법
interface
는 객체의 형태(shape)를 정의하며, 해당 형태를 구현하는 객체는 반드시 그 구조를 따라야 합니다.
interface User {
name: string;
age: number;
isAdmin: boolean;
}
const user1: User = {
name: "John",
age: 30,
isAdmin: true
};
위 코드에서 User
라는 인터페이스는 name
, age
, isAdmin
이라는 세 가지 속성을 갖는 객체의 구조를 정의합니다. user1
은 이 구조에 맞게 정의되어야 합니다.
2. 선택적 속성 (Optional Properties)
인터페이스에서 특정 속성을 필수가 아닌 선택 사항으로 지정할 수 있습니다. 이를 위해 속성 이름 뒤에 ?
를 추가합니다.
interface User {
name: string;
age?: number; // 선택적 속성
}
const user2: User = {
name: "Jane"
}; // age 속성이 없어도 오류가 발생하지 않음
age
속성은 선택적이므로, 객체에 존재하지 않아도 문제가 되지 않습니다.
3. 읽기 전용 속성 (Readonly Properties)
인터페이스의 속성을 읽기 전용으로 만들 수 있으며, 이를 통해 해당 속성은 초기화 이후 변경이 불가능해집니다. 읽기 전용 속성은 readonly
키워드를 사용합니다.
interface User {
readonly id: number;
name: string;
}
const user3: User = {
id: 1,
name: "Alice"
};
// user3.id = 2; // 오류 발생! 읽기 전용 속성은 수정 불가능
4. 함수 타입 정의
인터페이스는 객체의 구조뿐만 아니라 함수의 타입도 정의할 수 있습니다. 함수 인터페이스는 매개변수와 반환 타입을 명시합니다.
interface Add {
(a: number, b: number): number;
}
const add: Add = (x, y) => {
return x + y;
};
위에서는 Add
인터페이스가 두 개의 숫자 매개변수를 받아서 숫자를 반환하는 함수 타입을 정의합니다.
5. 인덱스 시그니처 (Index Signature)
인덱스 시그니처를 사용하면, 동적으로 속성 이름과 타입을 정의할 수 있습니다.
interface StringArray {
[index: number]: string;
}
const myArray: StringArray = ["hello", "world"];
console.log(myArray[0]); // "hello"
이 예시에서는 StringArray
인터페이스가 숫자 인덱스로 문자열 값을 가진 배열을 나타냅니다.
6. 확장 (Extending Interfaces)
인터페이스는 다른 인터페이스를 확장할 수 있습니다. 이는 상속과 유사한 개념으로, 기존 인터페이스를 기반으로 새로운 인터페이스를 만들 수 있습니다.
interface Person {
name: string;
}
interface Employee extends Person {
employeeId: number;
}
const employee: Employee = {
name: "Bob",
employeeId: 123
};
Employee
인터페이스는 Person
인터페이스를 확장하여 name
속성에 더해 employeeId
속성을 추가로 정의합니다.
7. 클래스에서의 인터페이스 구현
클래스는 인터페이스를 구현(implement)할 수 있으며, 이는 클래스가 해당 인터페이스에서 정의한 구조를 따라야 한다는 것을 의미합니다.
interface Animal {
name: string;
sound(): void;
}
class Dog implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
sound() {
console.log("Woof!");
}
}
const dog = new Dog("Buddy");
dog.sound(); // "Woof!"
Dog
클래스는 Animal
인터페이스를 구현하고 있으며, 인터페이스에서 요구하는 속성(name
)과 메서드(sound()
)를 반드시 정의해야 합니다.
8. 인터페이스 합치기 (Declaration Merging)
TypeScript에서는 동일한 이름을 가진 인터페이스가 여러 개 선언되면, 자동으로 병합됩니다. 이 기능을 "인터페이스 합치기(Declaration Merging)"라고 합니다.
interface Car {
brand: string;
}
interface Car {
year: number;
}
const myCar: Car = {
brand: "Toyota",
year: 2020
};
Car
인터페이스는 두 번 정의되었지만, brand
와 year
속성을 모두 가진 하나의 인터페이스로 병합됩니다.
결론
TypeScript의 interface
는 객체, 함수, 클래스 등의 구조를 정의하고 강제할 수 있어 코드의 안정성과 유지보수성을 높이는 데 중요한 역할을 합니다.