React - Side Effects

dobby·2024년 11월 27일
0
post-thumbnail

React 컴포넌트 안에서 데이터를 가져오거나 구독하고, DOM을 직접 조작하는 모든 동작을 'side effects'라고 한다.
왜냐하면, 이것은 다른 컴포넌트에 영향을 줄 수 있고, 렌더링 과정에서는 구현할 수 없는 작업이기 때문이다.

React 컴포넌트는 순수 함수이다.

순수 함수는 예측 가능하고, 신뢰할 수 있고, 테스트하기 쉽다.
반대로 함수 내의 구현 내용이 함수 외부에 영향을 끼치는 경우, 해당 함수는 side effect가 있다고 얘기한다.
여기서 side effect를 일으키는 함수를 예를 들어보면, Math.random()처럼 값이 랜덤으로 바뀌는 등 함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 미치는 경우에 side effect를 일으킨다고 볼 수 있다.
반면, side effect를 일으키지 않는 순수 함수의 경우엔 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수이다.


📌 일반적인 side effect 종류

  • 백엔드 서버에 API로 데이터 요청하기
  • 브라우저 API와 상호 작용(document, window 직접 사용하기)
  • setTimeout, setInterval 등 예측할 수 없는 타이밍 함수 사용하기

📌 Effect Hook

useEffect는 React 컴포넌트의 이러한 side effect들을 처리하는 방법을 제공하기 위해 존재한다.

컴포넌트 안에서 직접 side effect를 수행하는 경우, 컴포넌트의 렌더링에 방해가 된다.
side effect는 렌더링 과정과 분리되어야 한다.

side effect를 수행해야 하는 경우, 컴포넌트의 렌더링이 끝난 후에 수행되어야 한다.
바로 이 기능을 useEffect가 제공한다.

  • 우리가 외부 세계와 상호 작용하면서 해당 컴포넌트의 렌더링이나 성능에는 영향을 미치지 않도록 만들어주는 도구

useEffect는 두 개의 인자를 전달한다. (함수, 배열)

import {useEffect} from 'react';

function User({name}) {
	useEffect(() => {
    	document.title = name;
    }, [name]);
    
    return <h1>{name}</h1>;
}

첫 번째 인수로 전달하는 함수는 콜백 함수이다.
이 함수는 컴포넌트가 렌더링 된 이후에 호출된다.

두 번째 인수는 종속성 배열이다.
이 배열은 side effect가 의존하는 모든 값을 포함해야 한다.
위의 예에서는 외부 범위의 값인 name을 기반으로 제목을 변경하고 있으므로, name을 종속성 배열에 포함해야 한다.


📌 useEffect를 사용하며 발생하는 흔한 실수

1. useEffect에 종속성 배열을 전혀 제공하지 않고 함수만 제공하는 경우

이 경우 함수는 컴포넌트가 렌더링 될 때마다 렌더링 이후 실행된다.
useEffect는 종속성 배열이 없을 때 모든 단일 렌더링 후에 실행되므로, 무한 루프가 발생한다.

2. useEffect의 cleanup function

때로는 side effect를 멈춰야 한다.

예를 들어 setInterval 함수를 사용하는 카운트다운 타이머가 있는 경우 clearInterval 함수를 사용하지 않으면 해당 interval은 멈추지 않는다.

또 다른 예는, WebSocket과 함께 구독을 사용하는 것이다.
구독은 더 이상 사용하지 않을 때 꺼야 하며, 이것이 바로 cleanup function이 존재하는 이유이다.

setInterval을 사용하여 state를 설정하고, 그 side effect를 cleaup 하지 않으면, 컴포넌트가 언마운트되고 더 이상 사용하지 않을 때 state는 컴포넌트와 함께 소멸되지만, setInterval 함수는 계속 실행된다.

function Timer() {
  const [time, setTime] = useState(0);
    
  useEffect(() => {
    setInterval(() => setTime(1), 1000); 
    // counts up 1 every second
    // we need to stop using setInterval when component unmounts
  }, []);
}

컴포넌트가 사라지는 경우 문제는 setInterval이 더 이상 존재하지 않는 state를 업데이트하려고 시도한다는 것이다.
이것은 메모리 누수라는 오류이다.

cleanup function을 사용하려면 useEffect 함수 내에서 함수를 반환해야 한다.
이 함수 내에서 cleanup을 수행할 수 있다.

function Timer() {
  const [time, setTime] = useState(0);
    
  useEffect(() => {
    let interval = setInterval(() => setTime(1), 1000); 

    return () => {
      // setInterval cleared when component unmounts
      clearInterval(interval);
    }
  }, []);
}

컴포넌트가 언마운트될 때 cleanup function이 호출된다.

언마운트되는 컴포넌트의 일반적인 예는, 컴포넌트가 더 이상 렌더링되지 않는 애플리케이션의 새 페이지 또는 새 경로로 이동하는 것이다.

profile
성장통을 겪고 있습니다.

0개의 댓글