인터페이스란 코드 내 계약(약속, 규칙)을 정의하는 강력한 방법이다. 인터페이스는 일반적으로 벼수, 함수, 클래스 타입을 체크하기 위해 사용된다. 예로 아래 changhyeonO
변수는 Person
인터페이스의 계약을 준수해야 한다.
interface Person {
name: string,
age: number
};
let changhyeonO: Person = { name: "changhyeonO", age: 13 };
아래는 타입을 정의하는 type alias 코드 예제다.
type Human = {
name: string;
age: number;
};
type alias는 인터페이스와 비슷한 역할을 하지만, type alias는 확장(extends
)가 불가능하고 인터페이스는 확장이 가능하다. 따라서 웬만해선 인터페이스를 사용하는 것이 좋다.
인터페이스는 객체나 함수의 스펙, 배열의 접근 방식, 클래스 같은 범주에 대해 계약을 정의할 수 있다. 아래는 인터페이스 사용 예시이다.
interface Person {
age: number
};
-변수
let changhyeonO: Person = {age: 25};
-함수
function greeting(person: Person): void {
console.log(`Hello ${person.name}`);
};
-클래스
class Member implements Person {
constructor (
public name: string
) {};
};
-배열
interface Person {
[index: number]: string;
};
let people: Person = ["chnaghyoenO", "jiminYoo", "jihoYoo"];
추상 클래스와 인터페이스
추상 클래스는 일반 클래스와 달리 추상 메서드가 포함된 클래스로 일반 메서드를 포함할 수 있다. 반면 인터페이스는 모든 메서드가 추상 메서드여야 하는 차이가 있다.
추상 클래스는 상속을 통해 추상 메서드의 구현을 강제하여 자식 클래스에서 일부 동작을 구현하도록 만든 것이다. 인터페이스는 모든 구현에 대한 계약을 작성해둔 것이다. 추상 클래스는 프로그램의 전체 구조를 잡기 위해서 사용하고, 인터페이스는 기본적인 설계도로써 개발 협업에서 사용하기 용이하다.
타입스크립트의 컴파일러는 객체 프로퍼티의 프로퍼티 타입과 필수 요소 유무를 검사한다.
필수 요소 유무를 컨트롤 하기 위해서 Optional 프로퍼티인 ?
를 이용할 수 있다.
프로퍼티 선언 시 이름 끝에 ?
를 붙여 표시한다. ?
를 이용해 인터페이스에 속하지 않는 프로퍼티의 사용을 방지할 수 있다. 이는 객체 안의 몇 개의 프로퍼티만 채워서 사용하는 함수에 유용하다.("option bags"패턴이라 부른다.)
interface SquareConfig {
color?: string
width?: number
};
또한 객체가 처음 생성될 때 값 설정이 가능하고, 이후 수정이 불가능하도록 설정하는 readonly
프로퍼티도 있다. 클래스 속성의 readonly
와 동일하다. 역할도 const
와 유사하며, 사용되는 위치가 다르다.
interface Point {
readonly x: number
readonly y: number
};
타입스크립트에서 인터페이스는 함수와 클래스에서 사용이 가능하다.
-함수: 인터페이스를 이용해 함수의 타입, 인자의 타입, 반환 값의 타입을 정의할 수 있다.
function greeting(person: Person): void {
...
};
-클래스: 클래스가 특정 계약(통신 프로토콜)을 충족하도록 명시적으로 강제한다. 선언한 인터페이스를 클래스 뒤에 implements
하여 사용하며, 클래스는 인터페이스에 명시된 메서드를 반드시 구현해야 한다.
class Member implements Person {
...
};
-인터페이스 확장: 클래스와 마찬가지로 인터페이스도 인터페이스 간의 확장이 가능하다. 확장을 위해 extends
키워드를 사용한다.
interface Animal {
makeSound(): void
}
interface Dog extends Animal {
speed: number
}
Dog
인터페이스에서 Animal
인터페이스를 확장하는 예시.
-하이브리드 타입: 자바스크립트의 유연하고 동적인 타입 특성에 따라 인터페이스에서 여러가지 타입을 조합해서 사용할 수 있다. 예를 들어 함수 타입이면서 동시에 객체 타입을 정의할 수 있는 인터페이스를 만들 수 있다. 아래는 Counter
인터페이스는 함수로서 호출도 가능하고, 여러 프로퍼티도 가지고 있다.
getCounter()
함수에 나오는 as
는 타입 단언을 위한 문법으로, 말 그대로 타입을 컴파일러가 추론하지 않도록 프로그래머가 직접 지정하는 것이다.
interface Counter {
(start: number): string;
interval: number;
reset(): void;
};
function getCounter(): Counter {
let counter = function (start: number) {} as Counter;
counter.interval =123;
counter.reset = function () {};
return counter;
};
전략 패턴(Strategy pattern)이란 객체가 할 수 있는 행위들을 전략으로 만들어 두고, 동적으로 행위의 수정이 필요한 경우 전략만 수정이 가능하도록 만든 패턴이다.
예로 자판기 결제를 위한 pay
메서드가 있다고 가정 했을 때, 결제를 위한 다양한 방법이 존재한다. 새로운 결제 수단이 추가될 때마다 pay
메서드에서 조건문을 이용해 분기를 추가하면 확장성이 떨어진다.(소프트웨어 개체가 확장에 열려있어야 한다는 OCP(Open Closed Principle 원칙에 위배된다.)
따라서 전략 패턴을 적용하여 이를 해결할 수 있다. 인터페이스를 이용해 결제하는 것은 고정적으로 두고, 결제 방법(전략)을 인터페이스로 구현하는 것이다. 결제를 하는 행위를 implements
하되 현금으로 결제하는 메서드, 카드로 결제하는 메서드를 구분해서 구현하면 된다.