React.Native

[React] useEffect와 정리함수(clean up)

De-v-signer 2024. 11. 10. 04:04

정리함수(clean up)란 말 그대로 기존의 값을 정리하여 다음 기능이 수행될 때 방해가 되지 않도록 하는 함수를 말한다. useEffect 훅의 정리함수에 대해 React에서 설명하는 문서의 문구를 가져오면 아래와 같다.

Your setup function may also optionally return a cleanup function. When your component is added to the DOM, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. After your component is removed from the DOM, React will run your cleanup function.

정리함수에 대해 언급되는 3줄을 보면, useEffect의 설정함수가 수행될 때 정리함수도 수행될 수 있는데 1) 다시 렌더링할 때 설정함수 수행 이전에 기존 값으로 정리함수를 실행하며, 2) 구성요소가 제거(unmount)된 이후에 정리함수가 수행될 것임을 명시하고 있다.

이 부분에 대해서 공부하면서 많은 블로그들에서 정리함수의 개념을 혼동하거나 테스트를 통해 순서와 개념을 확인하려는 것을 볼 수 있었는데, 그만큼 정리함수의 개념이 살짝 모호하기도 하고 관련한 오작동이 많다는 방증이다. 때문에 개념을 명확하게 하기 위해서 공식 문서에 언급되는 부분들을 추가로 조사해 보았는데, 리스트로 정리된 아래의 내용이 그 중 하나이다.

React calls your setup and cleanup functions whenever it’s necessary, which may happen multiple times:
1. Your setup code runs when your component is added to the page (mounts).
2. After every re-render of your component where the dependencies have changed:
- First, your cleanup code runs with the old props and state.
- Then, your setup code runs with the new props and state.
3. Your cleanup code runs one final time after your component is removed from the page (unmounts).

앞의 줄글로 정의된 내용과 크게 다르지 않은데, 유의할 점은 첫 줄에 있는 which may happen multiple times이다. 즉 설정함수와 정리함수의 작동이 여러 차례 발생할 수 있다는 것인데, 바로 뒤에서도 보면 아래와 같이 언급하는 부분이 있다.

To help you find bugs, in development React runs setup and cleanup one extra time before the setup.
This is a stress-test that verifies your Effect’s logic is implemented correctly. If this causes visible issues, your cleanup function is missing some logic. The cleanup function should stop or undo whatever the setup function was doing. The rule of thumb is that the user shouldn’t be able to distinguish between the setup being called once (as in production) and a setup→cleanup→setup sequence (as in development).

버그 탐색을 위해 개발모드에서는 설정함수와 정리함수가 설정 전에 한번 더 수행된다는 내용인데, 이러한 점들은 Javascript의 비동기식 통신 방법으로 인해 생기는 문제를 해결하기 위한 노력들로 보인다. 중요한 것은 개발모드에서의 실제와 동작이 다르기 때문에, 단순히 로그를 찍어보면서 개념이나 타이밍을 완전히 이해하기에는 약간 어려움이 있어보인다는 점이다. 이러한 점 때문에, useEffect 관련하여 예상과 다르게 동작하거나 개념을 이해하기 어려운 부분들이 발생한다.

정리함수의 문법은 아래와 같이 사용한다.

useEffect(() => {
  doSomething();
  return () => {
    cleanUp();
  };
}, []);

위의 cleanUp() 함수 부분이 정리함수 부분이 되는데, 위의 설명들을 참조하였을 때 이 Effect는 첫 렌더링 시 doSomething()을 수행하고 대기하다가 해당 구성요소가 해제(unmount)될 때 cleanUp()을 수행할 것이라고 짐작해볼 수 있다.

반면

const serverUrl = 'https://localhost:1234';

function ChatRoom({ roomId }) {
  const [message, setMessage] = useState('');

  const options = { // 🚩 This object is created from scratch on every re-render
    serverUrl: serverUrl,
    roomId: roomId
  };

  useEffect(() => {
    const connection = createConnection(options); // It's used inside the Effect
    connection.connect();
    return () => connection.disconnect();
  }, [options]); // 🚩 As a result, these dependencies are always different on a re-render
  // ...

위와 같은 경우, options라는 객체를 의존성 배열로 하는 Effect로 options가 바뀔 때마다 정리함수인 connection.disconnect()를 수행하고 설정함수 connection.connect()를 수행하는 식으로 동작할 것이며, 이 구성요소가 해제될 때 connection.disconnect()가 수행될 것임을 알 수 있다.

앞서 언급한 Javascript의 비동기성( Asynchronous)은 이러한 시점이나 정확한 로직 측면에서 비직관적이고 이해하기 어렵다는 단점이 있는데, 때문에 단순히 보이는 응답시간이나 순서로 특징을 파악하기에는 어려움이 있다. 이러한 부분은 좀 더 공부하여 명확하게 정리할 필요가 있어 보인다.

반응형