React Hooks Design Pattern

믕듀·2022년 3월 1일
0

React

목록 보기
7/10

저번에 이어, ReactReduxlifescycle을 공부하고자 한다.

이번에는 React Hooks에 대해 알고자하는데, 앞서 Class Componentlifecycle을 알아본 봐 있고, 이는 크게 hooks에서도 다르지 않다.

우선 정의는 다음과 같다

Hook 이란 함수형 Component에서 React stateLifecycle연동(Hook)하는 것

결국 Hook에서의 Lifecycle이란 말 보다, Lifecyclestate를 이어주는 다리 라고 생각하는 것이 더 직관적인 것 같다.
그렇다면 가장 중요한 useEffect에 대해 알아보자.

useEffectComponentDidMount, ComponentDidUpdate, ComponentWillUnmount 같은 목적 제공, 하나의 API로 통합한 것

즉, stateLifecycle을 이어주는 HookuseEffect는, 다양한 Lifecycle을 하나로 묶어줌으로써, state와 연동하여 사용하게끔 도와준다.

이로써 각 단계에 따라 정해주듯 주체가 Lifecycle이 아닌, state가 되도록 하는 것이다.

가장 어려웠던 부분 중 하나 인 부분이었다. 객체 지향 언어와 절차 지향 언어가 아닌 함수형 프로그래밍에서, 프로그래밍 하는 방식을 이해하고 100퍼센트 활용하기에는 React 3개월차인 나에게는 아직 버겁기도 하였다.

이는 결국 state의 남발, useEffect의 남용, 꼬여버린 스파게티코드와 함수 그리고 critical bug를 남기기도 하였다.

과거에 존재하였던 Class Component, 왜 Hook과 함께 Functional Component로 넘어왔고, Class Component의 유지보수는 틀리지 않지만, 새로운 코드들은 Functional Component로 적극 권유할까?

이유는 다음과 같다.

Class components have downsides

  • Confusing (both human and machines, especially at binding and thiskeyword)
  • Lifecycle methods, logic spread over different lifecycle methods
  • Hard to test compared to functional components
    Compiled code size and compile time

Class componentthis와 같이 기계와 사람 모두에게 혼동을 주고, Lifecycle 메소드와 로직은 각기 다른 Lifecycle에 퍼지며, 테스트에 용이하지 않다. 한마디로 훨씬 복잡하다 라고 할 수 있을 것이다.


그렇다면 어떻게 코드를 짜야될까...

우선 거시적인 관점에서, 코드를 짜기전, 대 선배님들이 정리해주는 올바른 길, 디자인 패턴을 보고자한다.

1. Presentational and Container Component Pattern

- Presentational Components

UI가 어떻게 보여지는데에 대한 컴포넌트들은 존재한다. 이들은 어플리케이션과 어떠한 의존성도 없고, 데이터를 보여주는 것에만 사용된다.

const ItemsList = (props) => {
    return (
    <ul>
        {props.items.map((item) => (
        <li key={item.id}>
            <a href={item.url}>{item.name}</a>
        </li>
        ))}
    </ul>
    );
};

- Container Components

앞선 presentational components와 다르게, Container components는 더욱 작동 방식에 책임을 갖는다. 일반적으로 Life Cycle과 구성 요소를 포함하는 클래스 구성 요소이다.

class TvShowsContainer extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          shows: [],
          loading: false,
          error: ""
        };
      }
      componentDidMount() {
        this.setState({ loading: true, error: "" });
        fetch("https://api.tvmaze.com/schedule/web?date=2020-05-29")
          .then((res) => res.json())
          .then((data) => this.setState({ loading: false, shows: data }))
          .catch((error) =>
            this.setState({ loading: false, error: error.message || error })
          );
      }
      render() {
        const { loading, error, shows } = this.state;
        return (
          <div>
            <h1> Tv Shows </h1>
            {loading && <p>Loading...</p>}
            {!loading && shows && <ItemsList items={shows} />}
            {!loading && error && <p>{error}</p>}
          </div>
        );
      }
    }
    

하지만 이의 제작자는 더 이상 다음 패턴을 호옹하지 않는다... 따라서 의도만 이해하고 넘어가면 될 것 같다.

2. Provider Pattern

prop drilling이라는 현상은 리엑트 개발자들이 가장 많이 맞서는 문제중 하나이다. 데이터(prop)가 원하는 컴포넌트까지 오기 전까지 전달하는것에서 발생한다. 이는 Central Store에 저장함으로 (eg. Redux Store) 원하는 어떠한 컴포넌트에도 전달함으로써 해결 할 수 있다.

실제로 마지막으로 진행했던 프로젝트는 다음과 같은 사항들을 염두해, cssstyled-componentdataReact-Redux toolkit으로 저장한 바 있다. 이는 더욱 프로젝트를 관리하는데 윤택하고 편리하게 한다.


메인 기능 (Route)별로 central store를 만들고 관리하였다. 또한 cssstyled component로 각 컴포넌트 당 할당해주었다.

데이터는 공통적으로 쓰이는 곳이 많아, 재사용성이 높고, 활용도가 높아 가장 큰 단위에서 위치 할 수 있도록 하였고, 디자인에 쓰이는 css의 경우는 styled component의 특성 상, 각 태그명에 쓰였는데, 최소한의 단위로 쪼개야 가독성과 locating 하는 것이 매우 쉬워졌다.

위와 같이 한개의 컴포넌트의 css 정보를 담고 있는 styles.js는 100줄이 넘어갔고, 이는 평이한 수준 이었다. 비슷, 동일한 css가 반복적으로 쓰인다면 (eg. Button) 최상단에서 정의하여 주는것이 용이 할 수 있으나, 디자인과가 아닌 이상, 지속적인 수정이 이루어져야 했고 (당장만 봐도 px로 위치와 크기를 정해주 었다... 리팩토링 시 반응형을 고려하여 모두 수정해줘야 할 것 같다....) 이는 개발자가 이해 할 수 있는 최소 단위로 연결 해주는 것이 훨 씬 용이하다 생각이 들었다.

다음 글에서는 최신 5가지 패턴들을 소개하고, 또한 그 패턴 중에서 가장 호평을 받는 패턴을 소개 및 적용해보고자 한다.

profile
Front-End 개발자가 되는 꿈을 꾸는ing

0개의 댓글