본문 바로가기
Q&A해결2025년 1월 8일1분 읽기

React useEffect 클린업 함수에서 abort controller가 작동하지 않아 메모리 누수 발생

주
주니어개발자소연
조회 789댓글 4

React 컴포넌트에서 API 호출을 하고 있는데, 컴포넌트가 unmount 되어도 fetch가 계속 진행됩니다. AbortController를 사용했는데도 콘솔에 "Can't perform a React state update on an unmounted component" 경고가 나옵니다.

useEffect(() => {
  const controller = new AbortController()
  fetch("/api/data", { signal: controller.signal })
    .then(res => res.json())
    .then(data => setData(data))
  return () => controller.abort()
}, [])

댓글 4

김김영삼1년 전

AbortController 사용은 맞지만, abort된 후의 에러 처리가 빠져있습니다. fetch가 abort되면 AbortError가 throw되는데 이걸 catch해야 합니다.

useEffect(() => {
const controller = new AbortController()

const fetchData = async () => {
try {
const res = await fetch("/api/data", { signal: controller.signal })
const data = await res.json()
setData(data) // abort 안 됐을 때만 실행
} catch (err) {
if (err.name !== "AbortError") {
console.error("Fetch failed:", err)
}
// AbortError는 무시 (정상적인 cleanup)
}
}

fetchData()
return () => controller.abort()
}, [])

핵심은 catch에서 AbortError를 분리 처리하는 것입니다.

주주니어개발자소연1년 전
감사합니다! 그런데 React 18의 Strict Mode에서 useEffect가 2번 실행되는 것도 관련이 있나요?
김김영삼1년 전

네, 좋은 포인트입니다. React 18 Strict Mode에서는 개발 환경에서 마운트 → 언마운트 → 재마운트가 발생합니다. 이때 첫 번째 effect의 cleanup이 호출되면서 abort가 실행되고, 두 번째 effect에서 새 fetch가 시작됩니다.

이건 개발 환경에서만 발생하고 프로덕션에서는 1번만 실행되니, cleanup이 올바르게 작동하는지 검증하는 용도로 보시면 됩���다. 오히려 버그를 미리 잡아주는 거예요.

주주니어개발자소연1년 전
AbortError 분리 처리 + Strict Mode 설명까지 완벽합니다. 경고 메시지 완전히 사라졌어요! 감사합니다 🙏
Ctrl+Enter로 등록