
React Hook을 공부하다가 useEffect 의 cleanup function에 대해 궁금해져서 찾아보았다.
React에서 useEffect의 cleanup 함수는 메모리 누수를 방지하고, 컴포넌트가 사라지거나(unmount), useEffect가 다시 실행되기 전에 부작용(side effects)을 정리하는 역할을 합니다.
useEffect 내부에서 이벤트 리스너를 추가하거나, 타이머를 설정하는 경우, 컴포넌트가 제거될 때 정리(cleanup)를 해야 함. useEffect의 의존성(dependency)이 변경될 때[]) 안의 값이 바뀔 경우, useEffect가 다시 실행되기 전에 기존의 실행된 효과를 정리(cleanup)한 후 새로운 useEffect를 실행함.React의 useEffect에서 return 문을 사용하여 cleanup 함수를 정의할 수 있습니다:
useEffect(() => {
console.log("Effect 실행됨!");
return () => {
console.log("Cleanup 함수 실행됨!");
};
}, []); // 의존성 배열이 비어 있으므로 컴포넌트가 언마운트될 때만 실행됨
import React, { useEffect, useState } from "react";
const WindowResize = () => {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => {
setWidth(window.innerWidth);
};
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize); // Cleanup 함수 실행
};
}, []); // 의존성 배열이 없으므로 처음 마운트될 때만 실행됨
return <h1>현재 창 너비: {width}px</h1>;
};
export default WindowResize;
window.addEventListener("resize", handleResize)를 추가했지만 컴포넌트가 언마운트될 때 이벤트 리스너를 제거하지 않으면, 메모리 누수가 발생할 수 있음.// eventlistner 예시 element.addEventListener("click", function(){ alert("Hello World!"); });
setInterval, setTimeout 같은 타이머를 사용할 때, cleanup을 하지 않으면 컴포넌트가 사라진 후에도 실행됨 → 이를 방지하려면 정리 필요!
useEffect(() => {
setInterval(() => {
console.log("이 코드는 계속 실행됨...");
}, 1000);
}, []); // 언마운트 시에도 계속 실행됨
useEffect(() => {
const intervalId = setInterval(() => {
console.log("이 코드는 정리됩니다!");
}, 1000);
return () => clearInterval(intervalId); // Cleanup: 타이머 해제
}, []);
의존성 값(query)이 바뀔 때마다 API 요청을 보내면, 이전 요청이 끝나기도 전에 새로운 요청이 실행될 수 있음 → Cleanup 함수를 이용해 이전 요청을 취소해야 함.
useEffect(() => {
fetch(`https://api.example.com/data?query=${query}`)
.then(response => response.json())
.then(data => console.log(data));
}, [query]); // query가 변경될 때마다 실행됨 (이전 요청이 완료되지 않아도 새 요청이 실행됨)
useEffect(() => {
const controller = new AbortController();
fetch(`https://api.example.com/data?query=${query}`, { signal: controller.signal })
.then(response => response.json())
.then(data => console.log(data))
.catch(err => {
if (err.name === "AbortError") {
console.log("이전 요청 취소됨!");
}
});
return () => controller.abort(); // Cleanup: 이전 요청 취소
}, [query]);
controller.abort()를 실행하면 이전 요청이 자동으로 취소됨.query 값이 변경되더라도 불필요한 API 요청이 줄어들어 성능이 개선됨.useEffect에서 단순히 데이터를 가져오거나 로깅하는 경우에는 cleanup 함수가 필요 없음.useEffect(() => {
console.log("컴포넌트가 마운트됨!");
}, []);✅ Cleanup 함수(return 문 사용)의 역할
useEffect 내부에서 실행된 부작용을 정리하는 함수.useEffect가 다시 실행되기 전에 실행됨 (의존성 변경 시).✅ Cleanup이 필요한 경우
window.addEventListener)setTimeout, setInterval)✅ Cleanup이 필요하지 않은 경우
console.log 찍기 등)[]를 의존성 배열로 넣을 때)