[React] - useEffect

JP·2023년 2월 5일
0

* [ React ] *

목록 보기
9/12

useEffect

useEffect() 함수는 컴포넌트 가 렌더링 될 때마다 특정 작업(Sied effect)을 실행할 수 있도록 하는 리액트 Hook이다. Side effect는 component가 렌더링 된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 뜻한다.
(https://velog.io/@jhp4986/React-side-effect)
이러한 기능으로 인해 함수형 컴포넌트에서도 클래스형 컴포넌트에서 사용했던 생명주기 메서드를 사용할 수 있게 되었다.

useEffect 는 함수이고, 매개변수로 콜백 함수를 가진다.
useEffect 에 인자로 전달하는 콜백 함수에는 특정한 side effect를 수행 시킬수 있다.

위 코드에서 side effect 를 렌더링 전에 발생시키고 있다.
이러한 코드는 렌더링을 blocking 하기에 좋지 않다는 측면을 알고 있다.
그렇다면 이 문제를 해결하기 위해서 useEffect를 사용해 볼 수 있다.

side effect 를 발생시키는 함수를 바로 호출 하는것이 아니라 useEffect 의 인자로 전달 했다. 위와 같이 useEffect 의 인자로 전달된 콜백 함수는 곧바로 호출되는 것이 아니라 모든 렌더링이 완료된 후에 호출된다. 즉 렌더링을 Blocking 하지 않고 side effect를 발ㄹ생시킬 수 있게 되는 것이다.

useEffect 를 통해서 렌더링이 모두 다 완료되고 난 후 side effect 를 실행한다는 요구사항은 충족되었지만 아직도 매 렌더링 마다 side effect 가 실행된다는 사실은 변함이 없다.

useEffect 는 콜백함수 외에 한가지 매개변수를 더 가지고 있다.
useEffect 는 콜백 함수 외에 의존성 배열 (dependencyArray) 이라는 두번째 매개변수를 가진다. 의존성 배열은 이름에서부터 알 수 있듯이 배열의 형태이다.
이 배열이 바로 side effect의 발생 여부를 결정짓는 조건 이다.

useEffect의 동작 방식은 간단하다.
첫 번째 렌더링 이후에는 무조건 useEffect 에 전달된 콜백 함수를 호출하고 다은 렌더링부터는 아래의 조건에 따라 동작 한다.
1. 의존성 배열이 전달되지 않았다면 매 렌더링마다 콜백 함수를 호출 한다.
2. 의존성 배열이 전달되었다면 의존성 배열의 값을 검사한다.

  • a. 의존성 배열에 있는 값 중 하나라도 이전 렌더링과 비교했을 때 달라졌다면 콜백 함수를 호출 한다.
  • b. 의존성 배열에 있는 값이 이전 렌더링과 비교했을 때 모두 다 같다면 콜백 함수를 호출하지 않는다.

즉, useEffect 에서 첫 번째 인자인 콜백 함수는 실행시킬 동작을 결정하고 두 번째 인자인 의존성 배열은 실행시킬 타이밍을 결정짓는다고 할수 있다.

Rendering & Effect Cycle

함수 컴포넌트의 렌더링과 useEffect 가 발생하는 과정을 풀어 설명하면 아래와 같다.

  1. 컴포넌트가 렌더링 된다.
    (최초로 진행되는 렌더링은 브라우저에처음으로 이 컴포넌트가 보였다는 의미로 mount 라고 표현 한다. )
  2. useEffect 첫 번째 인자로 넘겨준 콜백 함수가 호출된다 (side effect)
  3. 컴포넌트의 state 또는 props 가 변경되었을 경우 리렌더링이 발생한다.
  4. useEffect 는 두번째 인자에 들어있는 의존성 배열을 확인한다.
    • 만약 의존성 배열이 전달되지 않았거나 / 의존성 배열 내부의 값 중 이전 렌더링과 비교했을 때 변경된 값이 하나라도 있다면 첫 번째 인자로 넘겨준 콜백 함수가 호출된다 (side effect)
    • 의존성 배열 내부의 값 중 이전 렌더링과 비교했을 때 변경된 값이 없다면 콜백 함수를 호출 하지 않는다.
    • state 또는 props 가 변경된다면 3~4 의 과정을 반복
  5. 컴포넌트가 더 이상 필요 없어지면 화면에서 사라진다.
    ( 컴포넌트가 브라우저의 화면에서 사라졌다는 의미로 unmount 라고 표현한다. )

Clean up Effect

clean up 필요성 

side effect 에는 여러 종류가 있을 수 있다.
그중에서 반드시 clean up 이 필요한 effect 들이 있을 수 있다.

위 side effect 는 clean up 이 필요하다.
이 side effect 는 setInterval 함수를 이용해서 100ms 마다 countTime 함수가 호출 되도록 하고 있다.
useEffect 의 의존성 배열에 빈 배열이 전달되었으므로 첫 번째 렌더링 이후에 side effect 가 실행된다. 그런데 side effect 를 clean up 해주지 않는다면 컴포넌트가 unmount 되는 경우 등 setInterval을 통한 구독이 필요 없어진 상황에서도 계속해서 콘솔이 출력되고 있을 것 이다.

clean up 방법 

useEffect는 side effect를 clean up 할 수 있는 방법을 제공해 준다. 결론부터 말하자면 useEffect에서 side effect를 clean up 하기 위해서는 useEffect에 전달한 콜백 함수에서 clean up을 하는 함수를 리턴하면 된다

위와 같이 발생시킨 side effect 를 상쇄하기 위한 함수를 만든 뒤 그 함수를 return 해주면 된다. addEventListener 로 등록한 eventListner 는 removeEventListener 함수를 통해서 제거할 수 있기 때문에 해당 동작을 하는 함수 (clean up 함수 ) 를 만든 뒤 콜백 함수 내에서 clean up 함수를 리턴 해주었다.
clean up 함수를 return 만 해준 다면 clean up 함수를 적절한 시점에 호출해 주는 일은 uesEffect 가 알아서 처리 해준다.

useEffect에 의존성 배열을 전달하지 않았기 때문에 해당 effect는 매 렌더링마다 실행된다.
리렌더링이 발생해서 useEffect가 다시 호출되는 상황이 발생한다.

a. clean up 함수를 리턴해줬기 때문에 clean up 함수가 호출된다.
b. clean up 함수가 호출된 뒤 effect가 발생된다.
c. 리렌더링이 발생하면 a ~ b의 과정이 반복된다.

컴포넌트가 unmount 되면 clean up 함수가 호출된다.

정리

  • React 에서 side effect 를 발생시킬 때는 조건을 충족 시켜야 한다.
    • 렌더링 이후에 발생시켜야 한다.
    • 매 렌더링 이후가 아니라 조건부로 원하는 순간에만 실행할 수 있어야 한다.
  • React 에서는 위의 조건을 충족시키면서 side effect를 발생시킬 수 있는 useEffect 라는 hook 을 제공해 주며 이를 통해서 손쉽게 side effecet 를 발생시킬 수 있다.
  • 일부 side effect 는 발생시킨 후 다시 clean up 하는 과정이 필요할 수 있다.
  • useEffect 에 인자로 전달한 콜백 함수에서 함수를 return 하면 다음 effect 가 실행되기 전과, 컴포넌트가 unmount 될 때 return 된 함수를 호출해 주며 이를 통해 기존의 side effect 를 clean up 할 수 있다.

profile
🐰와 🐢에 🐢

0개의 댓글