슬슬 Hooks로 이사 가셔야죠?

휴먼스케이프

리액트(+리덕스)에서 클래스형 컴포넌트를 함수형 컴포넌트 + Hooks로 바꿔보기

안녕하세요. 휴먼스케이프에서 개발자로 일하고 있는 Henry입니다. 이번 포스트에서는 React에서 클래스형 컴포넌트를 함수형 컴포넌트 + Hooks로 바꿔보며, 동시에 얻는 이점들을 정리하려고 합니다.

Hooks가 무엇인가요?

하단 링크로 접속하셔서 Lily가 작성하신 글을 참고해주세요!

https://medium.com/humanscape-tech/hooks-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-usestate-useeffect-811636d1035e

한 번 바꿔보기

우선 아래 명령어를 입력해서, 클래스형 컴포넌트로 작성된 Todo 앱을 내려받아주세요.

$ git clone https://github.com/hw0k/migrate-to-hooks.git --branch v1.0

내려받아서 보시면, Redux를 이용해 만든 Todo 앱이 있습니다.

간단한 것부터 복잡한 것까지

저의 작업 플랜은 이렇습니다.

State, Lifecycle Method가 없는 컴포넌트 전환

State, Lifecycle Method가 있는 컴포넌트 전환

이외 컴포넌트 전환

우선 TodoItem부터 변경하겠습니다.

그 다음은 TodoList를 변경합니다.

비교적으로 할 일이 많아보이는 TodoInput도 무리없이 바꿀 수 있습니다.

잠시만요, useCallback은 무엇인가요?

useCallback은 함수의 Memoization을 담당하는 훅입니다. 두 번째 파라미터인 deps 배열 안의 값이 바뀌었을 때만 새로운 함수를 생성하여 조금의 성능 개선이 이루어집니다.

물론 평상시에는 쓰지 않아도 되지만, 고성능을 지향하신다면 사용하시는 걸 추천합니다.

사용하지 않는다면 handleAdd() 메서드와 handleKeyPress() 메서드를 아래처럼 바꿔주시면 됩니다.

const handleAdd = () => {
  if (input === '') {
    alert('값을 입력해주세요');
    return;
  }
  
  addTodo(input);
  setInput('');
};
const handleKeyPress = (event) => {
  if (event.key === 'Enter') {
    handleAdd();
  }
};

이렇게 변경한 후 App 컴포넌트를 변경합니다.

이제 다 바꾼 것 같습니다! 그런데 제가 꼭 알려드리고 싶은 것이 하나 남았습니다.

React Redux에 있는 Hooks도 꽤 유용해요

React Redux에 있는 훅을 활용하면, Container 컴포넌트가 필요없어질 지도 모릅니다.

이 프로젝트에서 저희는 지금 Container 컴포넌트를 사용하고 있습니다.

Container 컴포넌트들.

저는 Container 컴포넌트의 장단점은 이렇다고 생각합니다.

장점

Redux 리듀서를 사용하는 부분을 깔끔히 분리

개별 컴포넌트의 코드 수 감소

단점

파일의 갯수 증가 (Container 컴포넌트를 분리했을 시)

React-Redux 초보자가 바로바로 배우기 힘든 극악의 난이도

불필요한 depth 추가 (connect()가 HOC 패턴으로 구현되어 있음.)

props를 단번에 파악하기 어려움.

React-Redux에는 이러한 단점들을 타개하기 위한 useSelector()와 useDispatch()라는 새로운 Hook을 제시했습니다.

참고 링크: https://react-redux.js.org/next/api/hooks

useSelector(selector: Function, equalityFn: Function): Selector Function으로 State를 가져오는 Hook (mapStateToProps 대체)

useDispatch(): dispatch() 함수를 사용할 수 있는 Hook (mapDispatchToProps 대체)

이 두 훅을 사용하여 Container Component를 대체하겠습니다.

그런데 이렇게 바꾸고 나니, Container 컴포넌트의 필요성이 느껴지지 않아보입니다. 그렇지 않나요? Container를 컴포넌트로 만들지 말고 Custom Hooks로 만들면 앞서 언급한 단점들을 모두 커버할 수 있습니다.

/hooks 디렉토리를 만들고 4개의 Custom Hooks를 만듭니다.

모두 하셨으면, /container 디렉토리와 안의 Container 컴포넌트들을 삭제하고, 방금 만든 Hooks를 사용해봅시다.

응용은 여러분들의 몫이에요

이 코드를 실전에서 쓰려면, 독자분이나 독자분의 팀이 지향하는 Fit에 맞게 꼭 응용하여 쓰시길 바랍니다.

이 프로젝트에서 저는 사용할 수 있는 최소한으로 구현하여 진행했습니다. Action을 모아 useTodoActions 라는 훅을 만들 수도 있고, 더 나아가 useTodos 안에 State, Actions를 모두 담는 거대한 훅을 만들어 사용하실 수도 있습니다.

물론 가져올 것이 많이 없고 간단하다면, 커스텀 훅을 만들지 않고도 충분히 사용하실 수 있어요!

바꿨는데, 무엇이 좋아졌을까?

함수형 컴포넌트 + Hooks로 마이그레이션 한 후, 제가 생각하는 이점들입니다.

간결한 코드

함수형 컴포넌트로의 통합

성능 최적화에 용이

간⭐지

우선 컴포넌트를 위해 사용하는 코드의 크기가 비약적으로 줄어들었습니다. 많은 불필요한 컴포넌트들이 지워졌기 때문입니다. 또, 사용할 부분끼리 코드를 묶어두기도 하며 공통된 로직을 Hooks로 분리하여 공유하므로 가독성 또한 늘어났습니다.

그리고 이제는 클래스형 컴포넌트를 사용할 이유가 없게 되어 모든 컴포넌트를 함수형으로 대체할 수 있게 되었습니다.

또 useCallback() 그리고 useMemo() 훅을 이용해 성능 최적화도 이전보다 훨씬 간결하게 할 수 있고, 함수형 컴포넌트의 성능 자체도 클래스형보다 좋지 않을까요?

이상으로 이번 포스트를 마치겠습니다. 감사합니다.

Get to know us better! Join our official channels below.

Telegram(EN) : t.me/Humanscape KakaoTalk(KR) : open.kakao.com/o/gqbUQEM Website : humanscape.io Medium : medium.com/humanscape-ico Facebook : www.facebook.com/humanscape Twitter : twitter.com/Humanscape_io Reddit : https://www.reddit.com/r/Humanscape_official Bitcointalk announcement : https://bit.ly/2rVsP4T Email : support@humanscape.io

기업문화 엿볼 때, 더팀스

로그인

/