이안의 평일코딩

[React] 리액트 Hooks 총 정리 본문

Front-end/React

[React] 리액트 Hooks 총 정리

이안92 2022. 7. 31. 21:35
반응형

 

 React Hooks

React Hooks는 ReactConf 2018에서 발표된 class없이 state를 사용할 수 있는 새로운 기능이다.

Class Component로 사용되어온 React에서 느껴왔던 불편함이나 문제점들을 해결하기 위해서 개발되었다.

원래 React는 주로 Class Component를 사용하고 React Hooks는 Functional Component를 사용한다.

위와 같이, Class 컴포넌트와 비교했을 때 함수형 컴포넌트를 이용하면 더 간결한 코드, 더 빠른 성능, 더 나은 가독성을 가진다.

함수형 컴포넌트에서는 클래스 컴포넌트에서 사용하던 리액트의 생명주기를 사용하기 못했기 때문에,

함수형 컴포넌트가 더 간결하고 빠르더라도 클래스형 컴포넌트를 써왔지만, 이것은 React 16.8 Hooks 업데이트로 변경되었다.

이로 인해 함수형 컴포넌트에서도 생명주기를 사용할 수 있기에 데이터를 가져오고 컴포넌트를 시작하자마자 API도 호출할 수 있게 되었다.

Class Component에서는 생명주기를 이용할 때 componentDidMount와 componentDidUpdate 그리고 componentWillUnmount를 다르게 처리를 해주지만 리액트 훅을 사용할 때는 useEffect 안에서 다 처리해줄 수 있다.

즉,  componentDidMount, componentDidUpdate, componentWillUnmount 모두를 Hooks에서는 usEffect를 이용해 처리한다.

 

 React State

리액트에서 데이터가 변할 때 화면을 다시 렌더링 해주기 위해서는 React State를 사용해야 한다.

React State란 컴포넌트의 렌더링 결과물에 영향을 주는 데이터를 갖고 있는 객체이다.

State가 변경되면 컴포넌트는 리렌더링(Re-rendering)된다. 또한 State는 컴포넌트 안에서 관리된다.

Hooks에서는 state를 정의하고 위의 setValue와 같이 이용해 state를 업데이트한다.

Props는 Properties의 줄임말로 상속하는 부모 컴포넌트로부터 자녀 컴포넌트에 데이터를 전달하는 방법으로 쓰이고, 읽기 전용(immutable)로 자녀 컴포넌트 입장에서는 변하지 않는다. (변하게 하고자 하면 부모 컴포넌트에서 state를 변경시켜줘야 한다.

State는 부모 컴포넌트에서 자녀 컴포넌트로 데이터를 보내는게 아닌 해당 컴포넌트 내부에서 데이터를 전달하고, 변경이 가능(mutable)하며 state가 변하면 Re-render된다.

 

 HOC(Higher Order Component)

HOC란 컴포넌트를 인자로 받아서 새로운 리액트 컴포넌트를 리턴하는 함수다.

화면에서 재사용 가능한 로직만을 분리해서 component로 만들고,

재사용 불가능한 UI와 같은 다른 부분들은 parameter로 받아서 처리하는 방법이다.

위의 A 페이지와 B 페이지는 같은 소스를 사용하고 있는 부분이 있는데 그 부분은 유저 리스트를 가져오는 부분이다.

어떠한 페이지에서든 유저 리스트를 가져와야 하는 애플리케이션을 만드려고 한다.

하지만 모든 페이지에서 유저 리스트를 가져오기 위해서 똑같은 소스를 넣어준다면 너무 많은 중복이 되기 때문에

중복이 되는 부분은 따로 HOC컴포넌트를 만들어 준다.

유저 리스트를 가져오는 공통적인 부분은 HOC 컴포넌트에 넣어주고 그 HOC 컴포넌트로 각각의 컴포넌트를 감싸주면 모든 컴포넌트에 따로 인증을 위한 부분은 넣어주지 않아도 된다.

Hooks가 나오기 전에는 이 방법이 추천되는 방법이었지만 여기도 문제가 있다.

바로 너무나 많은 Wrapper 컴포넌트가 생길 수 있다는 것이다.

이와 같은 문제는 Custom React Hooks를 이용해서 해결할 수 있다.

React Hooks에서는 HOC 대신 Custom Hooks를 이용해 컴포넌트를 만들어 처리해준다. Wrapper가 너무 많아지는 일을 방지한다.

  

 React.memo (컴포넌트 렌더링 최적화)

리액트앱에서 여러 컴포넌트로 나누는 이유는 재사용성을 위해서도 이지만 각 컴포넌트의 렌더링의 최적화를 위해서 이기도 하다.

예를 들어 Form에서 글을 타이핑을 할 때 원래는 Form 컴포넌트와 그 State 값을 가지고 있는 App 컴포넌트만 렌더링이 되어야 한다.

한 글자 입력 시마다 props가 바뀌지 않아서 렌더링 하지 않아도 되는 Form 이외의 리스트를 출력하는 List, Lists 컴포넌트가 있다고 하면 그 컴포넌트들까지 다시 렌더링 되는 걸 볼 수 있다.

이럴 때 React.memo를 적용하면 간단하게 문제를 해결할 수 있다.

이제는 렌더링이 필요치 않은 Lists, List 컴포넌트가 없는 것을 확인할 수 있다.

 

 useCallback (함수 최적화)

원래 컴포넌트가 렌더링 될 때 그 안에 있는 함수도 다시 만들게 된다.

하지만 똑같은 함수를 컴포넌트가 리렌더링 된다고 해서 계속 다시 만드는 것은 좋은 현상이 아니다.

그리고 이렇게 컴포넌트가 리렌더링될 때마다 함수를 계속 다시 만든다고 하면 만약이 함수가 자식 컴포넌트에 props로 내려준다면

함수를 포함하고 있는 컴포넌트가 리렌더링될 때마다 자식 컴포넌트도 함수가 새롭게 만들어지니 계속 리렌더링하게 된다.

 

함수를 만들어 props로 함수를 넘겨주면 React.memo로 감싸줘서 리렌더링되지 않던 컴포넌트들이 다시 한 글자 입력 시마다

Lists 컴포넌트와 List 컴포넌트까지 다시 리렌더링 되는 것을 볼 수있다.

 

useCallback 적용은 useCallback 안에 콜백함수와 의존성 배열을 순서대로 넣어주면 된다.

함수 내에서 참조하는 state, props가 있다면 의존성 배열에 추가해주면 된다.

useCallback으로 인해서 data가 변하지 않는 다면 함수는 새로 생성되지 않는다.

새로 생성되지 않기에 메모리에 새로 할당되지 않고 동일 참조 값을 사용하게 된다.

의존성 배열에 아무것도 없다면 컴포넌트가 최초 렌더링 시에만 함수가 생성되며 그 이후에는 동일한 참조 값을 사용하는 함수가 된다.

 

 useMemo (결과 값 최적화)

Memoization(메모이제이션)은 비용이 많이 드는 함수 호출의 결과를 저장하고 동일한 입력이 다시 발생할 때 캐시된 결과를 반환하여 컴퓨터 프로그램의 속도를 높이는 데 주로 사용되는 최적화 기술이다.

Component 내의 compute 함수가 만약 복잡한 연산을 수행하면 결과 값을 리턴하는데 오랜 시간이 걸리게 된다.

이럴 시에 컴포넌트가 계속 리렌더링 된다면 연산을 계속 수행하는데 오랜 시간이 걸려서 성능에 안좋은 영향을 미치게 되며,

UI 지연 현상도 일어나게 된다.

 

이러한 현상을 해결해주기 위해서 사용하는 것이 useMemo다.

compute 함수에 넘겨주는 a, b의 값이 이전과 동일하다면 컴포넌트가 리렌더링 되더라도 연산을 다시 하지않고 이전 렌더링 때 저장해두었던 값을 재활용하게 된다.

 

useMemo로 감싸준 후에 첫번째 인수에 의존성 배열에 compute 함수에서 사용하는 값을 넣어준다.

 

 크롬 확장 프로그램 - React Developer Tools

https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=ko 

 

React Developer Tools

Adds React debugging tools to the Chrome Developer Tools. Created from revision 336ac8ceb on 7/13/2022.

chrome.google.com

위에서 렌더링되는 것을 확인하기 위해 리액트 확장 프로그램을 크롬 익스텐션으로 다운로드 받아 설정해주면 쉽게 확인할 수 있다.

Components 탭에서 Highligh updates... 부분을 체크해주면 쉽게 컴포넌트가 렌더링 되는 것을 확인할 수 있다.

반응형
Comments