[React] useMemo와 useEffect 이해하기

jellyjw·2022년 12월 19일
3

리액트 강의를 듣다가 useMemo와 useEffect의 개념 및 차이를 정확하게 이해하고 싶어서 정리해보는 글이다.


React Lifecycle

리액트의 컴포넌트들은 생명주기(Lifecycle)를 가지게 되는데, 간단히 탄생-변화-죽음 으로 나타낼 수 있다.

  • 탄생 : Mount, 화면에 나타나는 것 (ex: 초기화 작업)
  • 변화 : Update, 리렌더링 되는 과정 (ex: 예외 처리 작업)
  • 죽음 : UnMount, 화면에서 사라짐 (ex: 메모리 정리 작업)

원래 리액트는 기본적으로 이런 Lifecycle들을 제어할 수 있는 method들을 가지고 있다. 하지만 아쉽게도 이런 메서드는 class형 컴포넌트에서만 사용할 수 있다.

class형 컴포넌트에서만 사용 가능한 생애주기 제어 method

  • ComponentDidMount
  • ComponentDidUpdate
  • ComponentWillUnmount

사실 근본적으로 함수형 컴포넌트에서는 상태를 관리하는 state나 위의 메서드들을 사용할 수 없었지만, React Hooks 가 생긴 뒤부터 함수형 컴포넌트에서도 다양한 hooks를 이용해 제어할 수 있게 되었다! 👏

함수형 컴포넌트에서도 사용 가능한 Hooks의 등장

  • useState
  • useEffect
  • useRef ... , 등등 수많은 Hooks 존재

React Hooks

React Hooks는 2019년 6월 정식 출시된 기능으로, Class형 컴포넌트의 길어지는 코드 길이 및 중복 코드, 가독성 문제 등을 해결하기 위해 등장하게 되었다.

useEffect

useEffect는 컴포넌트가 렌더링 될 때마다 특정 작업(side effect)을 실행할 수 있도록 하는 React Hook이다.
여기서 특정 작업(side effect)이란, 컴포넌트 렌더링 이후 비동기로 처리되어야 하는 부수적인 효과들을 뜻한다.

기본 형태

useEffect(() => {
  // 실행하고자 하는 코드
}, []}

useEffect는 두개의 파라미터를 전달받게 되는데,

  • 첫번째 파라미터에는 callback 함수
  • 두번째 파라미터에는 deps라고 불리는 의존성 배열이 들어간다.
    배열 안의 값이 변화할때마다 콜백함수가 수행된다.

useEffect 사용 예시

1. component가 Mount 되었을 때, deps를 생략할 경우

useEffect(() => {
  console.log("렌더링 될때마다 실행됩니다.")
});
              

이렇게 deps 부분을 생략할 경우 해당 컴포넌트가 렌더링 될 때마다 useEffect가 실행되게 된다.

처음 렌더링될때, 딱 한번만 실행되게 하고 싶다면 빈 배열을 넣어주면 된다.

useEffect(() => {
  console.log("처음 렌더링될 때 한번만 실행됩니다.")
}, [])

2. component가 Update 되었을 때

useEffect(() => {
  console.log(data)
  console.log("data 값이 변화(업데이트)할 때만 실행됩니다.")
}, [data])

이렇게 deps 안에 특정 값을 넣어준다면, 특정 값이 변화할때마다 useEffect가 실행된다.

3. component가 unmount 될 때

useEffect(() => {
  console.log("mount될 때 실행됩니다.")
  return () => {
    console.log("unmount시점에 실행되게 됩니다.")
  }
}, [])

useEffect가 return을 통해 함수를 반환할 경우 이 함수를 cleanUp이라고 한다.

unmount 될 때만 함수를 실행시키고 싶다면 deps에 빈 배열을 넣어주면 되고, 특정 값이 업데이트 되기 직전 cleanup 함수를 실행시키고 싶다면 deps에 특정 값을 넣어주면 된다.


Memoization

메모이제이션이란, 이미 계산한 연산 결과를 기억해 두었다가 동일한 계산을 시키면 다시 연산하지 않고 기억해 두었던 데이터를 반환시키는 프로그래밍 기법이다.

메모이제이션을 적용하면 중복되는 연산을 피해 성능 최적화가 가능하다.

useMemo

useMemo는 이전 렌더링과 현재 렌더링 간에 값이 동일할 경우 메모이제이션된 값을 반환하는 것으로, deps 배열 안의 값이 변경될 경우에만 함수가 실행되는 것이다.

배열의 길이인 arr.length 가 변경될 때만 리렌더링 되어야 하는 컴포넌트가 있다고 가정했을 때, 불필요한 렌더링을 막기 위해 deps에 useMemo의 두번째 파라미터인 deps에 arr.length 를 넣어주면 arr.length 값이 변화될때만 함수를 실행한다.

만약 arr.length 값이 동일한 경우 다시 함수를 호출해 값을 구하는 대신 메모이제이션된 값을 반환하여 그대로 사용하기 때문에 리렌더링 되지 않는다.

기본 형태

useMemo(() => {
  console.log("결과값 생성")
}, [deps])
  • 첫번째 파라미터에는 callback 함수
  • 두번째 파라미터에는 deps 의존성 배열 안에 특정 값이 들어간다.

useMemo 사용 예시

useMemo를 사용하기 이전에는 getDiaryAnalysys 는 감정점수를 분석해주는 평범한 함수였다.
하지만 useMemo로 감싸준 뒤부터는 useMemo가 함수를 전달받아 콜백함수가 전달하는 값을 리턴하기 때문에, getDiaryAnalysys 을 리턴받게 된다.
따라서 사용할 때 함수 호출 방법이 아닌 으로 사용되어야 한다.

const { goodCount, badCount, goodRatio } = getDiaryAnalysys();
// 자주 하는 실수이다. ()를 붙여서 함수처럼 사용하면 에러가 발생한다.

const { goodCount, badCount, goodRatio } = getDiaryAnalysys;
// 값으로 사용

useMemo와 useEffect의 차이는 무엇일까?

  • useEffect : 생성에 관련된 기능으로, 값을 기억해 놓고 deps가 변경될 경우에만 다시 계산하는 기능
  • useEffect : 사이트이펙트 등 한번만 호출해도 될 기능들이 렌더링되어 실행되거나 호출 과정에서 렌더링에 영향을 끼칠 수 있는 것들을 모아 따로 처리하기 위한 기능

가장 큰 차이점은 useEffect는 해당 컴포넌트의 렌더링이 완료된 후에 실행되고, useMemo는 렌더링 중에 실행된다.


참고자료

  • winterlood 한입 크기로 잘라먹는 리액트 강의자료
profile
남는건 기록뿐👩🏻‍💻

0개의 댓글