타입스크립트 Interface 2

세나정·2023년 3월 9일
0

TypeScript

목록 보기
4/6

인터페이스 vs Type Alias

이 글을 보고 있다면 당연히 알고 있을 Type Alias에 대해 다시 한번 알아봅시다
우리는 JS에서 어떤 값을 재사용 편~하게 하기 위해 변수를 썼습니다

TS에서는 복잡한 타입을 재사용하기 위해 Type Alias를 사용합니다

예시를 들어볼까요

저희는 name이 string, age가 number인 객체를 만들고 싶다면 이렇게 간단히 씁니다
근데 모든 사람들의 코딩 관례상 반복되는 코드는 좀 무리인 것 같긴합니다

당신이 TS를 좀 한다면 다음과 같이 생각할 수도 있을 겁니다
"에? 어차피 TS가 추론 해줄텐데 바보 ㅋㅋ"
물론 가능은 한데 다음처럼 속성을 추가했을 때 그건 누가 추론할 겁니까

뭐 만약에 우리가 모든 변수에 어떤 속성이 들어가는지 전부 기억한다면 굳이 안 써줘도 되긴 하겠지요 하지만 그런 걸 현업에선 다루지 않습니다 (라고 배움)

네 이렇게 역시나 잘 추론 해주죠 (TS 똑똑이~)

하지만 결론적으로는 당연히도
변수에 제대로 타입을 지정해주는 것이 좋지 않을까요

프로그래머는 반복작업을 싫어해야만 합니다
반복작업을 줄이는 것은 실수를 줄일 수 있기 때문이죠

그러면 어떻게 줄이는데요!! 그쵸 저도 기승전결에서 결만 좋아합니다

두 가지 방법

두 가지 방법이 존재합니다
Type Alias와 이번에 배울 Interface이죠

당신이 잘하는 Type Alias로 해결을 해봅시다

예, 거즘 변수를 넣는 거죠 뭐

자 그러면 이번엔 Interface로 해결을 해봅시다

여기서 틀린그림찾기!

뭐가 달라졌나요 라고 보면
맨 윗줄 코드가 다르고 만드는 방법이 다릅니다

type는 = 도 있습니다
interface는 저 같은 상남자처럼 그런 거 따위 신경 안 쓰는 모습이군요

=을 제외하고는 외관상 차이가 없는뎁쇼?
맞습니다 그게 다라면 제가 왜 이야기 했겠습니까

둘의 차이점이 존재합니다

차이점

차이점1 : 추론 방식이 차이가 납니다 type은 친절합니다 객체 형태로 해당 타입이 무엇인지까지 다 설명을 해줘요, 하지만 우리의 상남자 interface는 그런 거 따위 나 몰라라 보여주지도 않습니다 (굿)

즉, type Alias는 타입을 그냥 변수처럼 담아 놓은 Type 변수입니다

차이점2 : 확장성에서 차이가 있습니다
Type Alias의 확장은 & (인터섹션) 을 통해 이뤄지는 방면
인터페이스의 확장은 implements (구현) 를 통해 이뤄집니다


인터페이스는 구현방식은 스크롤 아래에 나오니 넘어갈게욤

대부분의 시니어 개발자들은 Type Alias보다는 인터페이스를 쓰라고 하는 편입니다
왜냐하면 Type Alias 녀석은 그저 변수를 활용한 타입의 정의 그 이상, 그 이하도 아니기 때문입니다. 확장 "가능한" (김종민 X) 코드를 짜려면 당연히 인터페이스죠

자, 여기서 타린이들은 물을 겁니다 "에? 그럼 확장 가능한이 왜 중요하죠?"

확장 가능한 코드는 아무리 말해도 중요합니다
기능을 추가해달라는 업무를 받을 때 다른 코드의 변경 없이 기능을 추가해야하기 때문이죠

바~버 ㅋㅋ

인터페이스의 개념

자 우리가 대학에서건 어디서건 자바를 처음 배울 때 인터페이스랑 클래스랑 추상 클래스 도대체 무슨 차이야? 했을 겁니다 (제가 그랬어요.)

우리가 태어났을 시절 소프트웨어는 그렇게 복잡하지 않았기에 클래스의 상속으로도 크게 복잡한 클래스 구조를 갖지 않았었다고 합니다만~

소프트웨어의 SOFT가 왜 붙어있겠습니까 계속 기능이 추가되기에 그렇습니다
그래서 우리는 ㅠㅠ 기획자들이 기획을 추가할 때마다 ㅠㅠ 클래스를 추가하고 확장해야합니다 ㅠㅠ (돈 벌어야죠)

기능이 적었던 옛날엔 뭐 클래스만 사용해도 괜찮았죠
하지만 기능 추가가 월 별로 이루어지는 지금 소프트웨어의 생태계는
코드의 재사용성과 확장성을 신경 써야만 합니다

자, 이제 추상클래스와 인터페이스가 어찌 사용되는지 예시를 들며 설명을 해봅시다

자 저희 명문 K 대학교 (하버드예일광운옥스포드 SKY 서성한 중경외시..)

예시

K 대학의 학과별로 클래스를 작성해본다고 생각을 해봅시다
아래와 같이 클래스를 작성 해볼게욤

자 이 때, 학과나 소융대 등과 같이 분류만을 위해서 사용되는 경우에는
추상 클래스와 인터페이스로 작성하게 됩니다

만약, 소융대를 직접 객체로 만들어서 사용할 경우에는 소융대 클래스로 구현해야 하는 거죠

자, 이때 갑자기 총장님께서 소융대의 두 개의 과 말고 한 가지 과(저희 과!)를 추가하고 싶다고 합니다
총장님! 그럴 땐 클래스의 상속 즉 확장성을 사용하면 됩니다! (extends!)

부랴부랴 과를 만들었는데 갑자기
정부에서 뭐라고 합니다.. "너희들은 너무 유능하니 전자공학과랑 정보융합학부랑 묶여서 사업 좀 진행해!"

다른 단과대에 있는 전자공학과 소융대인 정융이랑 어떻게 묶어줄 수 있을까요?

자 여기서 우리가 헷갈리는 주제, 다루고 있는 주제인
추상 클래스, 인터페이스란 개념이 나옵니다.

하지만, 대부분의 언어에서 단일 상속 (부모가 하나인 상속)만을 지원합니다

즉, 부모는 하나여야 한다는 거죠
현재 정융은 소융대라는 부모클래스를 가지고 있고 전자공학과는 전정대라는 부모클래스를 가지고 있습니다. 추상 클래스는 현재 상황에서 불가하기에 인터페이스를 사용하면 됩니다.

해결방안은 다음과 같습니다

그림을 보면 기존의 상속구조 (소융대-정융, 전정대-전자)에 변형 없이
따로 빼내서 반도체라는 인터페이스를 만든 것을 볼 수 있습니다!!!! (박수)

이것이 인터페이스를 활용한 소프트웨어의 확장성이며 객체지향의 장점 중 하나입니다.

다형성

인터페이스의 장점이란 다형성은 정확히 뭘까요
예 바로 부모클래스 또는 인터페이스 타입의 매개변수에 자식 클래스가 들어갈수 있다는 겁니다

사실 많은 수업 + 나때 객체지향 수업에서도 장점을 상속 위주로 많이 말하지만
객체의 가장 큰 장점은 다형성입니다.

자 이렇게 해서 생긴 반도체 단대 (?)에 참여한 학생들 중 우수한 성적을 거둔 학생들에게 상을 줄겁니다

그렇기에 정융과 전자의 클래스는 다음처럼 구현할 수 있겠죠 (소융대와 전정대도 클래스로 구현 했다고 가정)

새로 만든 "반도체"라는 인터페이스로 부터 구현 되었고
"소융대 OR 전정대"라는 클래스로부터 확장된 클래스 "정융 OR 전자공학" 이렇게 있습니다

한번 다형성을 주지 않고 우수한 성적들에게 상을 주겠습니다 짜잔

자 여기서 보다시피 문제가 뭘까요
아무리 같은 학교지만 같은 과끼리에서만 상 수여가 가능하네요

물론 잘 되긴 합니다 뭐 코딩과 요리를 비유하자면
저희 항상 코딩할 때 어떻게 요리하던 먹을 수 있게 요리하는 것처럼 (사실 요리라고 우기는 게 더 큼) 하지만 우리는 유교사상의 후예들이기 때문에 우리는 한 핏줄이라고 우기고 싶습니다.

결론적으로 지금은 생산성이 좀 떨어지는 것 같군요

그렇기에 아! 아까 만든 "반도체"를 사용해서 한번 만들어볼까? 생각이 들겁니다

자, 말 나온김에 (내가 했지만) 다형성을 이용해서 작성해보겠습니다

동일한 로직의 givePrizeForㅇㅇ 을 하나로 묶게 되었습니다
헉.. 너무 깔끔합니다 역시 우린 천재군요

반도체로부터 정융과 전자과가 있으니 저희도 냅다 반도체를 박아버린 겁니다

이렇게 코드를 가꾸어나가며 리팩토링을 할 수 있습니다

이제 훨~씬 깔끔하고 동일한 기능의 함수를 묶으므로 DRY 원칙을 좀 지키겠군요
*DRY : Don't Repeat Yourself... (명언처럼 보이도록 기울여봤습니다.)

추가적으로 반도체라는 곳이 아닌 소융대라고 한다면

이렇게 작성하면 되겠죠 하지만 이것도 잘 보면 반복이 있습니다
아~니 givePrizeFor가 똑같잖아~~~ 사실 개발자는 같은 걸 잘 보게 됩니다
카드게임 할 떄 잘하겠군요

이럴 때 앞서 배운 제네릭을 사용하여 봅시다

짜잔 자 이제 정말로 간단해졌습니다.
반복적으로 이렇게 우리가 잘하는 주입식 교육을 하다보면
언젠가 나도 모르게 통합적인 코드를 짜지 않을까요

객체지향적 코드에 대한 오해

객체지향을 자바로 배운 저 같은 경우 객체지향 프로그래밍을 그저 class 그 자체로 오해하기 쉽습니다. (야~ 그냥 도장 만들어 다 찍어서 생산해버리게 정도?)

하지만, "클래스를 어떻게 만들어야 하는가?"는 객체지향의 핵심이 아닙니다
저희가 배우는 자바스크립트는 class 문법을 지원하지만 사실 프로토타입 기반의 객체지향 언어입니다.

JS의 클라스 문법은 Syntactic Sugar (문법적 설탕)일 뿐입니다.


객체 지향의 핵심은 "객체와 객체가 보내는 메세지 (객체의 역할)" 입니다.


즉 우리가 클래스를 만들 때는 객체에 어떤 값을 가질 것인지 먼저 생각하는 것이 아니라 객체가 어떤 일을해서 어떤 역할을 맡을 것인지 먼저 정해야만
좋은 객체지향 코드를 작성할 수 있습니다.

TS를 배우는 당신, 우리는 이제 인터페이스와 클래스를 자주 사용할 거기 때문에 객체지향적인 설계방식을 꼭꼭 익힙시다!

사용예시 코드

// 인터페이스 선언
interface HTMLElement {
    addEventListener(listener: ()=>void):void;
}

// 인터페이스 구현을 사용한 class
class HTMLElementDivElement implements HTMLElement {
    constructor(){
    }
    addEventListener(listener: () => void): void {
    }
    a(){}
}

// 인터페이스 구현을 사용한 class 2
class HTMLElementH2Element implements HTMLElement {
    constructor(){
    }
    addEventListener(listener: () => void): void {
    }
    b(){}
}

// 클래스를 통한 타입지정
function checkForDiv(elem: HTMLElementDivElement){
}

// 클래스를 통한 타입 지정
function checkForH2(elem: HTMLElementH2Element){
}

// 경우를 두어 원하는 것을 활용하도록 단순 리팩토링
// 한 가지 팁! 이 과정에서 자동으로 메서드의 목록이 뜹니다.
function check(elem: HTMLElement) {
    if(elem instanceof HTMLElementDivElement) {
        elem.a();
    }
    if(elem instanceof HTMLElementH2Element) {
        elem.b();
    }
}
profile
압도적인 인풋을 넣는다면 불가능한 것은 없다. 🔥

0개의 댓글