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. 의존성 배열이 전달되었다면 의존성 배열의 값을 검사한다.
즉, useEffect 에서 첫 번째 인자인 콜백 함수는 실행시킬 동작을 결정하고 두 번째 인자인 의존성 배열은 실행시킬 타이밍을 결정짓는다고 할수 있다.
Rendering & Effect Cycle
함수 컴포넌트의 렌더링과 useEffect 가 발생하는 과정을 풀어 설명하면 아래와 같다.
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 함수가 호출된다.
정리