[TIL] 디자인패턴(1) - React는 잘 쪼개기만 해도 반은 간다

lezsuuu·2022년 10월 23일
0

TIL

목록 보기
38/42
post-thumbnail

레거시는 죽어서 디자인패턴을 남기고...

미루고 미루던 디자인패턴을 찍먹해보고자 한다. 가장 먼저 리액트 디자인패턴에 대해 알아보자. 흐릿하게만 알고 있던 탓에 코드의 발전이 없는 듯 하여, 다시 한 번 리액트의 원칙을 짚고 넘어가려고 한다.

1. 컴포넌트 기반 아키텍처

컴포넌트(Component)는 리액트의 핵심 중 하나다. 컴포넌트는 화면의 작은 부분을 나타내는 독립적인 요소로 버튼, 입력 폼, 리스트 등이 모두 컴포넌트에 해당한다. 리액트에서는 컴포넌트를 잘 쪼개야 코드의 재사용성과 유지보수성을 높이고 깨끗하게 코드를 작성할 수 있다.

1-1) 단일 책임 원칙(Single Responsibility Principle)

하나의 컴포넌트는 하나의 책임만을 가져야 한다.

1-2) 재사용성(Reusability)

유사한 기능을 가진 컴포넌트는 추상화하여 공통 로직을 재사용해야 한다.

1-3) 컴포넌트 분리(Component Decomposition)

컴포넌트를 잘게 쪼개서 코드를 모듈화하고 독립적으로 관리할 수 있어야 한다.

1-4) UI와 로직의 분리(Separation of UI and Logic)

컴포넌트 내의 UI와 비즈니스 로직을 분리한다.

  • 컨테이너 컴포넌트: 상태 관리와 비즈니스 로직을 처리하는 역할.
    주로 상태 관리 라이브러리(예: Redux, MobX)와 연동되어 애플리케이션의 전체적인 상태를 관리하거나, 데이터를 가져와서 프레젠테이션 컴포넌트에게 전달하는 역할을 한다.

  • 프레젠테이션 컴포넌트: UI 렌더링을 담당.
    컨테이너 컴포넌트로부터 전달받은 데이터(props)를 사용하여 화면을 그리거나 사용자 이벤트를 처리한다. 로직이나 상태 관리와 관련된 부분은 최소화하여 코드를 단순하게 유지한다.

1-5) 상태 관리 외부화(Externalized State Management)

상태 관리 라이브러리(예: Redux, MobX)를 사용하여 컴포넌트의 상태를 외부에서 관리하는 것이 흐름과 변경을 예측하는 데 용이하다.

1-6) 단방향 데이터 흐름(Unidirectional Data Flow)

상위 컴포넌트에서 하위 컴포넌트로 데이터를 props로 전달하여 데이터 흐름을 단방향으로 유지하면, 데이터의 흐름을 추적하기 쉽다.

1-7) 렌더링 최적화(Rendering Optimization)

불필요한 렌더링을 방지하기 위해 React.memo, useMemo, useCallback 등을 활용하여 성능을 향상시켜야 한다.

1-8) 조합과 컴포지션 (Composition)

작은 컴포넌트를 조합하여 복잡한 기능을 구현한다.

2. 상태 관리 패턴

리액트 특성상 상태 관리는 매우 중요하다. 상태 관리로 UI의 동적인 변화를 일으키고, 애플리케이션 효율의 영향을 주기 때문이다. 리액트에서 상태(state)란 컴포넌트의 데이터를 말하는데, 상태 관리 패턴은 컴포넌트의 데이터를 어떻게 관리하고 전달할지에 대한 방법을 제시한다. 가장 일반적으로 사용되는 상태 관리 라이브러리로 Redux와 MobX가 있다.

- 상태(state): 컴포넌트의 데이터를 나타냄. 리액트 컴포넌트의 렌더링 결과는 상태의 변화에 따라 달라짐.

Redux

  • 예측 가능한 상태 관리를 강조한다.
  • 단일 상태 트리를 사용해 앱의 모든 상태를 저장하며, Action을 통해 상태 변경이 이루어진다.
  • Action은 상태 변경을 설명하는 일종의 객체로, dispatch로 전달되어 상태 변경을 요청한다.
  • 상태 변경은 Reducer 함수를 통해 이전 상태와 Action을 받아 새로운 상태를 반환하는 것이다.
  • 상태의 불변성을 유지하고 순수한 함수를 사용하여 상태 변화를 추적하고 예측 가능하게 관리할 수 있다.
  • 복잡한 상태 관리와 debugging에 유리하다.

MobX

  • 상태와 UI 간의 관계를 자동으로 추적한다.
  • 간단하고 직관적인 상태 관리를 지향한다.
  • 상태를 옵저버블(Observable)로 감싸서 상태의 변화를 감지하고, 이에 따라 자동으로 렌더링이 업데이트된다.
  • 클래스 내에서 ActionComputed property, Reaction을 사용하여 상태 변화와 의존성 관리를 처리한다.
  • 몹엑스에서 Action은 상태 변경 메서드로, 이를 통해 상태 변화를 추적하고 반응한다.
  • Computed property는 상태의 변화에 따라 자동으로 계산되는 값이다.
  • Reaction은 상태의 변화에 따라 특정 동작을 자동으로 수행하게 해준다.
  • 몹엑스는 선언적인 방식으로 상태 변화를 다루고, 코드가 더 직관적이며 간결할 수 있다.

이 외에도 다른 상태관리 Recoil 등의 상태 관리 라이브러리가 있고, 그에 따른 상태 관리 패턴도 차이가 있다. 모든 사용법이 그러하듯 사용자와 프로젝트에 따라 적절한 기술을 선택하면 되겠지만, 각 상태 관리의 패턴에 적절하게 운영해야 진정으로 상태를 '관리' 할 수 있다!

3. 조합(composition) vs 상속(inheritance)

리액트는 컴포넌트 간의 조합을 통해 재사용성을 강조한다. 상속보다는 조합을 통해 컴포넌트 간의 기능을 확장하는 것이 권장된다.

  • 조합: 작은 컴포넌트를 조합하여 복잡한 기능을 구현하는 방식. 컴포넌트 간의 상호작용을 통해 기능 확장.
  • 상속: 부모 컴포넌트의 속성과 메서드를 자식 컴포넌트가 상속받는 방식. 리액트에서는 권장되지 않는 방식.

4. 렌더링 최적화

리액트로 구현한 클라이언트에서 성능을 향상시키기 위해서는 브라우저의 작동 원리, 상태 관리, 렌더링과 리렌더링 등등 공부할 것도 많고 구현할 방식도 많지만 대표적으로 React.memo, useMemo가 있다. 리액트는 애초에 가상 DOM을 이용해 불필요한 렌더링을 줄이는 것이 목적인데 React.memo, useMemo를 사용하면 컴포넌트의 업데이트를 효율적으로 관리하여 애플리케이션의 반응성을 높일 수 있다.

  • React.memo: 프레젠테이션 컴포넌트의 불필요한 재렌더링을 방지하기 위해 사용되는 함수.
  • useMemouseCallback: 계산 비용이 높은 작업을 최적화하기 위해 사용되는 훅.

리액트 관련 디자인패턴에 대해 가볍게 훑어 보았다. 사실 가볍지 않다... 프로젝트 구현하면서 더 딥한 내용을 마주치게 된다면 다시 블로깅 해야지!! 화이팅

profile
돌고 돌아 벨로그

0개의 댓글