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
찍기 등)[]
를 의존성 배열로 넣을 때)