Files
2nd/00_Raw/Memory Leak Debugging.md
T
2026-04-26 20:05:02 +09:00

4.2 KiB

Memory Leak Debugging

📌 Brief Summary

메모리 누수는 애플리케이션이 메모리를 할당한 후 더 이상 필요하지 않음에도 불구하고 이를 해제(release)하지 않아 메모리 소비가 지속적으로 증가하는 현상을 의미합니다 [1]. 이러한 문제는 시간이 지남에 따라 애플리케이션의 성능을 점진적으로 저하시키고, 인터페이스를 느리게 만들며, 궁극적으로 브라우저 탭의 멈춤이나 충돌을 유발합니다 [2-4]. 프론트엔드 환경에서 메모리 누수를 해결하려면 Chrome DevTools와 같은 도구를 활용하여 메모리 할당을 프로파일링하고, 분리된 DOM 노드나 정리되지 않은 이벤트 리스너 등의 원인을 찾아 수정해야 합니다 [5-7].

📖 Core Content

  • 메모리 누수의 정의와 주요 증상 자바스크립트에서 가비지 컬렉터(Garbage Collector)는 사용되지 않는 메모리를 자동으로 회수하지만, 변수 등에 참조가 남아있을 경우 메모리가 해제되지 않고 누수됩니다 [1]. 이러한 메모리 누수는 작업 부하가 일정함에도 불구하고 메모리 사용량이 감소하지 않고 꾸준히 증가하는 특징을 보입니다 [4]. 주요 증상으로는 장시간 사용 후 성능 저하, 잦은 화면 멈춤, 특히 모바일 기기에서의 잦은 앱 충돌 등이 있습니다 [2-4].

  • 프론트엔드의 주요 메모리 누수 패턴

    • 분리된 DOM 노드 (Detached DOM Nodes): DOM 트리에서는 제거되었지만 자바스크립트 코드나 변수에서 여전히 참조를 유지하고 있어 가비지 컬렉션의 대상이 되지 못하는 노드입니다 [8, 9].
    • 이벤트 리스너 누적 (Event Listener Accumulation): React의 useEffect 등에서 컴포넌트가 언마운트될 때 등록된 이벤트 리스너나 구독을 정리(cleanup) 해주는 함수를 반환하지 않으면 발생합니다 [9-12].
    • 클로저에 의해 유지되는 참조 (Closure-Retained References): 클로저가 부모 스코프의 변수를 계속 살려두어 불필요하게 큰 객체를 메모리에 남겨두는 경우입니다 [13].
  • 디버깅 및 탐지 방법

    • Chrome 작업 관리자: 실시간으로 모니터링하며 'JavaScript Memory' 항목의 괄호 안 숫자(라이브 숫자)가 꾸준히 증가하는지 확인하여 누수의 1차적 징후를 발견할 수 있습니다 [14, 15].
    • 성능 패널 (Performance Panel): 시간 경과에 따른 메모리 사용량을 시각화하며, 강제 가비지 컬렉션 이후에도 JS 힙(Heap) 크기가 이전보다 높은 상태로 종료된다면 메모리 누수를 의심해야 합니다 [16, 17].
    • 힙 스냅샷 (Heap Snapshots): 메모리 상태의 스냅샷을 캡처한 뒤 'Detached' 키워드로 검색하여 분리된 DOM 트리를 찾거나, 작업 전후의 두 스냅샷을 비교(Comparison)하여 지속적으로 델타(Delta) 크기가 증가하는 객체를 식별할 수 있습니다 [6, 9, 11, 18].
    • 할당 타임라인 (Allocation Timelines): 메모리 할당 패턴을 실시간으로 추적하여, 회색으로 변하지 않고 남아있는 파란색 막대(해제되지 않은 메모리 할당)를 통해 특정 사용자 상호작용 중 발생하는 누수를 찾아냅니다 [19-21].
  • 예방 및 모범 사례 대규모 객체 캐싱에는 가비지 컬렉션을 방해하지 않는 WeakMap을 사용하는 것이 권장됩니다 [12]. React 애플리케이션에서는 컴포넌트의 수명 주기에 맞춰 useEffect 내에서 항상 이벤트 리스너를 제거하거나 구독을 취소하는 정리(cleanup) 함수를 제공하여 메모리 누수를 미연에 방지해야 합니다 [10-12].

🔗 Knowledge Connections


Last updated: 2026-04-26