반응형

Clean-Up Function에 대한 내용입니다.

React에서 clean-up 함수는 구성 요소가 마운트 해제되거나 다시 렌더링되기 전에 실행되는 코드입니다.

이는 주로 useEffect Hook에서 메모리 누수를 방지하고 리소스가 적절하게 릴리스되는지 확인하기 위해 가격 지우기, 네트워크 요청 취소, 구독 취소 등의 작업을 수행하는데 사용됩니다.

 

예제

import { useEffect, useState } from "react";

const App = () => {

    const [data, setData] = useState(null);

    useEffect(() => {
        // mount 될 때 실행됩니다.
        const fetchData = async () => {
            try {
                const res = await fetch("https://api.ex.com/data");

                const result = await res.json();
                setData(result);
            } catch (err) {
                console.log("Fetching Data", err);
            }
        }

        fetchData();

        return () => {
            // unmount 될 때 실행됩니다.
            console.log("clean-up function ~");
        }
    }, [])

    return (
        <section>
            TEST
        </section>
    );
}

export default App;

 

  • useEffect Hook은 구성요소가 마운트 될 때 데이터를 가져오는데 사용됩니다.
  • useEffect에서 반환된 정리 기능은 구성 요소가 마운트 해제될 때 또는 다시 렌더링되기 전에 실행됩니다.
  • 빈 배열은 구성 요소가 마운트 될 때 효과가 한 번만 실행되도록 합니다.

애플리케이션에서 잠재적 메모리 누수를 방지하려면 clean-up 함수에 정리 로직을 포함해야 합니다.

 

 


 

실행 시점 알아보기

useEffect Hook은 컴포넌트가 mount, update, unmount 될 때 실행됩니다.

useEffect Hook의 실행은 컴포넌트의 렌더링과 동시에 일어나는 것이 아닌 렌더링이 끝난 후에 일어납니다.

 

Mount 예제

import { useEffect, useState } from "react";

const App = () => {

    console.log("1");

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

    console.log("3");
    return (
        <section>
            TEST
        </section>
    );
}

export default App;

 

실행순서는 1 -> 3 -> 2 순서로 실행됩니다.

풀어보자면 컴포넌트의 렌더링이 끝난 후에 useEffect의 2가 실행되는 것을 확인 할 수 있습니다.

 

Update, Unmount 예제

import { useEffect, useState } from "react";

const Test = () => {

    const [btn, setBtn] = useState(0);
    console.log("1");

    useEffect(() => {
        console.log("2");

        return () => {
            console.log("Unmount");
        }
    }, [btn])

    console.log("3");
    
    return (
        <section>
            <button onClick={() => setBtn(prev => prev + 1)}>Click</button>
        </section>
    );
}

export default Test;

 

버튼을 클릭 했을 때, 실행순서는 1 -> 3 -> Unmount -> 2 순서로 실행됩니다.

풀어보자면 1과 3이 먼저 실행되고, 그 다음 unmount가 되면서 clean-up 함수를 실행시켜 Unmount를 실행하고 update가 되면서 2를 실행하게 됩니다.

 

clean-up 함수가 바라보는 값

const [btn, setBtn] = useState(0);

useEffect(() => {
    console.log("2", btn);

    return () => {
        console.log("Unmount", btn);
    }
}, [btn])

return (
    <section>
        <button onClick={() => setBtn(prev => prev + 1)}>Click</button>
    </section>
);

 

:: clean-up 함수는 이전의 값을 바라보고 있기 때문에 이 상태에서 버튼을 클릭하면 아래처럼 실행됩니다.

// 처음 눌렀을 때
Unmount 0
2 1

// 두번째 눌렀을 때
Unmount 1
2 2

 

:: 만약에 useEffect에 의존성 배열을 제거하면 useEffect가 실행되지 않기 때문에 useEffect의 내부는 출력되지 않습니다.

 

중첩 Component 예제

import { useEffect, useState } from "react";

const One = () => {
    useEffect(() => {
        console.log("One");
    }, [])

    return <div>One</div>;
}

const Two = () => {
    useEffect(() => {
        console.log("Two");
    }, [])
}

const Test = () => {

    useEffect(() => {
        console.log("Test");
    }, [])
    return (
        <div>
            Test
            <One />
            <Two />
        </div>
    );
}

export default Test;

 

useEffect를 이런식으로 중첩으로 사용하면 One -> Two -> Test 순서로 실행됩니다.

 

그러면 One 컴포넌트 내부에 Two를 넣어주면 어떻게 실행되는지 예상할 수 있습니다.

내부의 내부로 들어갔기 때문에 Two -> One -> Test 순서로 실행됩니다.

 

중첩 Component에 props로 데이터를 전달 예제

import { useEffect, useState } from "react";

const One = (test) => {
    useEffect(() => {
        console.log("One");

        return () => {
            console.log("CleanUp One")
        }
    }, [test])

    return <div>
        One
        <Two test={test} />
    </div>;
}

const Two = (test) => {
    useEffect(() => {
        console.log("Two");

        return () => {
            console.log("CleanUp Two")
        }
    }, [test])
}

const Test = () => {

    const [test, setTest] = useState(0);

    useEffect(() => {
        console.log("Test");

        return () => {
            console.log("CleanUp Test")
        }
    }, [test])
    return (
        <div>
            <button onClick={() => setTest(1)}>클릭</button>
            Test
            <One test={test} />
        </div>
    );
}

export default Test;

 

버튼을 클릭했을 때 실행순서는 "CleanUp Two" -> "CleanUp One" -> "CleanUp Test" -> "Two" -> "One" -> "Test"순서로 실행이 됩니다.

가장 내부의 자식부터 unmount들이 먼저 발동하고 끝난 이후에, 가장 내부의 자식부터 mount가 발동됩니다.

 

 

반응형

+ Recent posts