짹뚜 스튜디오

[React] useEffect 본문

개발 공부/프론트엔드

[React] useEffect

짹뚜 2022. 1. 27. 13:38

useEffect Hook은 함수 컴포넌트에서 Side Effect를 처리할 수 있게 한다.

Side Effect

함수가 실행되면서 함수 외부에 존재하는 값들에 영향을 끼치는 것을 Side Effect라고 한다. 예를 들어 웹페이지의 Title을 변경하거나, fetch 함수로 데이터를 가져오거나 등등이 Side Effect에 속한다. 이러한 Side Effect를 처리하기 위해서 React에서는 useEffect()를 사용한다.

useEffect

useEffect의 첫 번째 인자로는 콜백 함수를 받는다. 이 콜백 함수는 useEffect가 호출될 때 실행이 된다. 컴포넌트 생성, 새로운 props 전달, state 변경이 일어나고 렌더링이 된 다음에 useEffect가 호출된다.

 

두 번째 인자로는 Dependency Array를 받는다. 이것은 useEffect가 불필요하게 호출되는 것을 방지해주고, 특정한 변수의 값이 변경될 때만 useEffect를 호출하게 한다.

const [value, setValue] = useState(0);

useEffect(() => {
    console.log("value changed");
}, [value]);

위와 같은 예제에서는 useEffect가 value의 값이 변경될 때만 호출된다. 

 

Dependency Array를 아예 전달하지 않는 경우도 있는데, 그 경우에는 렌더링이 일어날 때마다 useEffect가 호출된다. 그리고 빈 배열을 전달하는 경우에는 컴포넌트가 최초로 렌더링 될 때만 호출된다.

useEffect(() => {
    console.log("렌더링 될 때마다 호출됨");
});

useEffect(() => {
    console.log("최초 렌더링때 딱 한 번만 호출됨");
}, []);

Clean-Up 함수

useEffect를 사용하면서 문제가 생길 수 있다. 만약 우리가 현재 브라우저의 width 크기를 동적으로 가져오고 싶다고 한다면, 다음과 같이 코드를 작성할 수 있다.

  const [width, setWidth] = useState(window.innerWidth);

  const checkWidth = () => {
    setWidth(window.innerWidth);
  };

  useEffect(() => {
    window.addEventListener("resize", checkWidth);
  });

위 코드를 보면 컴포넌트가 렌더링 된 후에 resize 이벤트 리스너를 추가해주고 브라우저의 크기가 변경되면 checkWidth라는 콜백 함수를 호출하고 있다. 그리고 콜백 함수는 setWidth를 통해서 width의 값을 바꿔주고 있다. 여기서 문제가 발생하는데 setWidth를 통해 State의 값을 변경하면 렌더링이 발생하게 된다. 그렇게 되면 다시 useEffect가 호출이 되고 resize 이벤트 리스너가 하나 더 추가된다. 이런 식으로 계속해서 동일한 이벤트 리스너가 추가되면서 메모리 누수 (Memory Leak)가 발생하게 된다.

* 메모리 누수 (Memory Leak) 란 불필요한 메모리가 계속해서 점유하고 있는 현상이다.

 

이 현상을 해결할 수 있는 것이 Clean-Up 함수이다. useEffect는 함수를 반환할 수 있는데 이 함수가 Clean-Up 함수이고 이전 useEffect에서 생성된 것들을 제거해주는 역할을 한다. 그리고 React는 컴포넌트가 마운트 해제될 때 Clean-Up 함수를 실행한다.

 

위 예제에서의 useEffect를 다음과 같이 수정할 수 있다.

  useEffect(() => {
    window.addEventListener("resize", checkWidth);
    return () => {
    	window.removeEventListener("resize", checkSize);
    }
  });

 

'개발 공부 > 프론트엔드' 카테고리의 다른 글

[프론트엔드] CSR VS SSR  (0) 2022.07.04
[React] useRef  (0) 2022.02.06
[React] State와 useState  (0) 2022.01.21
[React] Props  (0) 2022.01.16
[React] React Router  (0) 2022.01.11
Comments