본문 바로가기
프론트엔드/TS 공부

타입스크립트의 객체 지향

by 학습하는 청년 2024. 5. 24.

최종 수정 : 2024-05-24

타입스크립트의 객체 지향(OOP)

자바스크립트는 프로토타입 기반의 객체 지향 언어로 분류된다. 그러나 전통적인 객체 지향 프로그래밍 언어에서 기대할 수 있는 일부 기능을 지원하지 않아 객체 지향을 온전히 구현하는 데 부족함이 있다. 이러한 제약을 타입스크립트가 private과 같은 접근 제어자나 추상 클래스, 추상 메서드 같은 기능을 지원하면서 해결해준다. 결국, 타입스크립트는 객체 지향을 구현할 수 있도록 도와주는 자바스크립트의 슈퍼셋이라고 말할 수 있다.

 

타입스크립트는 점진적 타이핑, 구조적 타이핑 그리고 덕 타이핑이 결합한 언어이다. 이 3가지 개념이 섞인 언어는 흔치 않은데, 이것들이 모여 객체 지향의 폭을 넓혀준다고 말할 수 있다.

 

점진적 타이핑

프로그램 전체가 아닌 개발자가 명시한 일부분만 정적 타입 검사를 거치게 하고 나머지 부분은 그대로 동적 타입 검사가 이루어지게 하여 점진적 개선을 할 수 있도록 해준다.

 

덕 타이핑

객체의 변수와 메서드 집합이 객체의 타입을 결정하게 해준다.

 

구조적 타이핑(= 구조적 타입 시스템)

명시적인 선언이나 이름에 의존하여 명확한 상속 관계를 지향하는 노미널 타이핑(Nominal Typing, 자바 #C)과 달리, 구조적 타이핑은 객체의 속성에 해당하는 특정 타입의 속성을 갖는지를 검사하여 타입 호환성을 결정한다.

 

cf. 노미털 타이핑 언어는 인터페이스와 클래스가 일대일로 대응된다. 그러나 타입스크립트 같은 구조적 타이핑 언어는 하나의 클래스에 여러 인터페이스가 연결될 수 있으며, 하나의 인터페이스에 여러 클래스가 연결될 수 있다. 또한 자바스크립트의 슈퍼셋으로 기존 웹 환경과 잘 호환되며, 객체 지향을 자바스크립트보다 더 쉽게 표현할 수 있게 해준다.

 

타입스크립트를 활용해 프론트엔드에서 객체 지향을 구현할 수 있다. 객체는 별다른 게 아니다. 우리가 자주 쓰고 있는 컴포넌트도 객체의 한 형태다. 컴포넌트는 스스로 책임을 져야하는 역할을 수행하면서 다른 컴포넌트 객체와 협력하는 독립적인 객체다. 다시 말해, 컴포넌트를 조합하는 것도 객체 지향을 활용하는 것이라고 볼 수 있다. 물론 JSX 문법은 선언적이라는 특성이 있지만 이미 우리는 컴포넌트를 개발하면서 사실상 객체 지향을 구현하고 있다.


Q. 객체 지향 관점에서 타입스크립트가 프론트엔드에 어떤 이점을 주는가?

1. 타입스크립트는 prop을 인터페이스로 정의할 수 있다. 객체 지향 패러다임에서는 객체 간의 협력 관계에 초점을 둔다. 컴포넌트 간의 협력 관계를 표현하는 것이 prop이다. 또한 객체 자체가 아니라 프레임워크에 의해 객체의 의존성이 주입되는 DI(Dependency Injection, 의존성 주입) 패턴을 따르는데, 이러한 패턴을 더욱 명확하게 표현할 수 있게 해주는 것이 타입스크립트다.

 

DI는 객체 간의 의존 관계를 설정하는 데 사용 된다. DI를 구현하기 위해서는 A 클래스가 B 클래스에 의존한다고 하더라도, A가 B의 구체 클래스가 아닌 B의 인터페이스에 의존하도록 설계해야 한다. DI패턴을 따르면 객체 간의 결합도를 낮출 수 있는데 타입스크립트로 DI 패턴을 더욱 명확하게 표현할 수 있다.

 

2. 타입스크립트 자체가 객체 지향적으로 다양한 측면을 표현하는 데 큰 장점을 가지고 있다. 여러 타이핑 언어의 특성 덕분에 객체 지향의 폭을 넓혀준다.

 

프론트엔드 개발에서 객체 지향은 중요한 개념이다. 사실, 웹 개발을 하면서 제대로 된 객체 지향을 구현하기 어려운 이유가 있다. JSX와 같은 선언적 문법을 사용하여 마크업을 처리하는데, 일반적으로 객체 지향을 구현하려면 객체 간의 협력 관계를 먼저 고려하고, 메시지를 정의하여 해당 메시지를 수신할 알맞은 객체를 결정하는 절차를 따르게 된다.

 

하지만 HTML 마크업을 선언적으로 작성할 때는 컴포넌트 간의 관게를 먼저 떠올리기 어렵다. 디자인 요구 사항이 제시되어야 그에 맞춰 마크업을 진행할 수밖에 없다. 이처럼 컴포넌트 간의 협력 관계를 먼저 고려하고 메시지를 정하는 것은 현실적으로 힘든 일이다. 게다가 애플리케이션의 변동 사항에 유연하게 대응하기 위해 객체 지향을 구현하는 것인데 사전에 레이아웃의 변화를 예측할 수 없다.

 

이러한 레이아웃의 변동에 좀 더 나은 대응을 하기 위해 MVP, MVC, MVVM 등의 다양한 패턴이 등장했지만 이것들이 만병통치약은 아니다. 선언적인 문법을 사용하면서 객체 지향을 완벽하게 구현한다는 것은 너무 이상적인 이야기다.


Q. 어떻게 프론트엔드에서 객체 지향을 효과적으로 활용할 수 있을까?

컴포넌트만 객체는 아니다. 리액트에서 컴포넌트는 props를 받아 결과물을 렌더링한다. 이때 props로 전달되는 값을 객체로 해석할 수도 있다. 좀 더 크게 보면 상태 관리 측면에서 유기적인 객체를 생성할 수도 있을 것이다. 특히 MobX는 객체 지향 패러다임을 기반으로 한 대표적인 상태 관리 라이브러리다.

 

그렇다면 어떻게 프론트엔드에서 객체 지향을 효과적으로 활용할 수 있을까? 특히 레이아웃은 예상치 못한 변동 사항이 생길 가능성이 높기 때문에 미확정 영역으로 두고 공통으로 사용되는 컴포넌트와 비즈니스 영역에서 객체 지향 원칙을 적용하여 설계하면 좋은 구조를 개발할 수 있을 것이다.


컴포넌트 자체가 객체다.

많이 하는 착각 중 하나가 객체 지향 구현 자체를 클래스라고 생각하는 것이다. 전혀 그렇지 않다. 클래스는 객체를 표현하는 방법의 하나의 도구일 뿐이다. 컴포넌트를 함수형으로 선언하든 클래스형으로 선언하든 모두 객체를 나타낸다.


캡슐화와 추상화

캡슐화는 객체 지향에서 끊임없이 나오는 핵심 개념 중 하나이다. 캡슐화와 추상화가 객체 지향 패러다임의 근본적인 지향점까지는 아닐지라도 올바른 협력을 설계하기 위해서는 적절한 캡슐화가 이루어져야 한다. 프로젝트 설계의 궁극적인 목표는 객체들이 유기적으로 협력하게금 만들어서 적절하게 도메인 분리를 하는 것이다. 이를 위해 캡슐화는 중요한 도구가 될 수 있다. 추상화도 별것 아니다. 객체들을 모델링하는 과정 자체가 추상화다. 이 객체들을 좀 더 사람이 인지할 수 있도록 적합한 설계를 하는 것이 곧 추상화다.

 

캡슐화란 다른 객체 내부의 데이터를 꺼내와서 직접 다루지 않고, 해당 객체에게 처리할 행위를 따로 요청함으로써 협력하는 것이다. 컴포넌트는 객체다. 그렇다면 컴포넌트의 내부 데이터인 상태(state)가 바로 캡슐화의 대상이 될 수 있다. 결국 컴포넌트 내의 상태와 prop를 잘 다루는 것도 캡슐화의 개념에 부합하는 것이다. 달리 말하면, Prop drilling은 좋지 못한 관계를 형성하게 하고 캡슐화를 저헤한다. 이런 문제를 해결하기 위해 옵저버 패턴이 등장했으며 나아가 컨텍스트 API 및 Redux, MobX, Recoil과 같은 다양한 상태 관리 라이브러리가 생겼다.

 

적절하게 캡슐화되고 추상화된  컴포넌트를 활용하면 애플리케이션을 더 유기적으로 구성할 수 있다. 최종적인 지향점은 객체들이 유기적으로 협력하게끔 해서 올바르게 도메인을 분리하는 것이다. 객체 지향 패러다임에 매몰되기보다는 어떻게 하면 더 유기적인 협력 관계를 만들어낼 수 있을지, 명확하게 도메인을 분리할 수 있을지에 집중하자.


우리는 이미 객체 지향을 구현하고 있다.

"이것이 객체 지향이야"라고 개발하기란 어려운 일이다. 그런데도 객체 지향은 현실 세계와 닮은 패러다임이기에 객체 지향을 의식하지 않고 개발하더라도 나중에 보면 객체 지향이 이미 적용되어 있을 때가 많다. 우리는 이미 객체 지향을 구현하고 있다.

 

그게 아니었다면, 여전히 JQuery를 사용하여 DOM을 직접 제어하고 있을 것이다. 객체 지향을 단순한 설계 방법의 하나로 볼 게 아니라 현시대의 패러다임으로 봐야 한다. 함수, 클래스, 모듈을 분리하는 것도 객체 지향 프로그래밍의 일부다. 객체 지향의 핵심은 말 그대로 객체이지만, 객체 그 자체보다는 객체의 책임을 먼저 생각하라고 말한다. 물론 어려운 일이다. 그러면 우선 객체나 책임을 신경 쓰지 않고 개발 속도에 집중하여 화면 전체를 만든 후에 각 부부느이 역할과 책임을 나누면서 리팩터링하는 방법도 객체 지향을 구현하기 위한 트레이닝이 될 수 있다. 이렇게 경험이 쌓이다 보면 화면을 구성하기 전에 개별적인 컴포넌트를 먼저 생각하게 될지도 모른다.

 

객체 지향은 유지보수를 위한 개념인데, 유지보수가 필요하지 않다면 객체 지향을 꼭 따를 필요가 없을지도 모른다. 어디에나 반드시 객체 지향이 적용되어야 하는 것은 아니지만 객체 지향 관점으로 개발하는 것은 여전히 중요하다. 


참고 자료

우아한 타입스크립트 with 리액트 (p.364-375)

 

'프론트엔드 > TS 공부' 카테고리의 다른 글

설치하기  (0) 2024.05.27
자바스크립트의 런타임과 타입스크립트의 컴파일  (0) 2024.05.25
HTML DOM + React 타입 정리  (0) 2024.05.24
React.FC  (0) 2024.05.24
ReactNode / ReactChild / ReactElement / JSX.element  (0) 2024.05.24

댓글