메모리 누수(Memory Leak)란, 프로그램이 사용하던 메모리를 필요하지 않게 되었음에도 불구하고 제대로 해제하지 않아, 여전히 차지하고 있는 상태를 말합니다. 이는 프로그램이 실행될 때 메모리를 할당받아 사용하고, 그 사용이 끝났을 때 반납하는 과정에서 문제가 발생하는 경우에 나타납니다.
예를 들어, 웹 애플리케이션에서 DOM 요소에 이벤트 리스너를 추가했다가 해당 요소를 제거할 때 리스너를 해제하지 않으면, 브라우저는 그 요소와 리스너에 대한 참조를 메모리에 계속 유지합니다. 이런 경우에 메모리 누수가 발생합니다.
자바스크립트 같은 자동 메모리 관리 언어에서는 가비지 컬렉터가 더 이상 필요 없는 객체를 정리해주지만, 여전히 프로그래머가 실수로 참조를 유지하는 경우에는 가비지 컬렉터가 이를 회수할 수 없게 됩니다. 메모리 누수가 계속해서 발생하면 사용 가능한 메모리 양이 줄어들어 결국 애플리케이션의 성능 저하나 시스템의 안정성에 영향을 줄 수 있습니다.
-
글로벌 변수 최소화: 글로벌 변수는 의도치 않게 메모리 누수를 일으킬 수 있습니다. 가능한 한 지역 변수를 사용하고, 필요하지 않은 변수는 null이나 undefined로 설정하여 참조를 해제합니다.
-
이벤트 리스너 관리: 이벤트 리스너를 더 이상 필요하지 않을 때 제거합니다. addEventListener를 사용하여 등록한 이벤트는 removeEventListener를 사용하여 명시적으로 해제합니다.
-
DOM 요소 제거 시 이벤트 리스너 해제: DOM 요소를 제거할 때 연결된 이벤트 리스너와 데이터 바인딩도 같이 제거해야 합니다. 이는 메모리에서 해당 요소의 참조를 완전히 제거합니다.
-
클로저 사용 주의: 클로저는 매우 유용하지만 메모리 누수를 일으킬 수 있는 복잡한 참조를 만들 수 있습니다. 클로저 내부에서 사용하는 외부 변수는 클로저가 활성 상태일 때 계속 메모리에 남게 됩니다. 필요하지 않은 참조는 null을 할당하여 해제합니다.
-
타이머 취소: setTimeout이나 setInterval을 사용할 때는 필요 없어진 후에 clearTimeout이나 clearInterval로 취소합니다.
-
캐시된 데이터 관리: 캐싱은 성능 향상을 위해 중요하지만, 크기가 무제한으로 증가하지 않도록 관리해야 합니다. 불필요한 데이터는 캐시에서 정기적으로 제거합니다.
-
메모리 프로파일링 사용: 개발자 도구의 메모리 프로파일링 도구를 사용하여 메모리 사용을 모니터링하고, 누수가 의심되는 부분을 정밀 분석합니다.
-
의도치 않은 객체 참조 방지: WeakMap이나 WeakSet과 같은 약한 참조를 지원하는 컬렉션을 사용하여 객체가 필요 없어지면 가비지 컬렉터가 수집할 수 있도록 합니다.
-
외부 라이브러리 주의: 외부 라이브러리를 사용할 때는 해당 라이브러리가 메모리를 효율적으로 관리하는지 확인합니다. 라이브러리가 업데이트되지 않거나 유지 관리가 중단된 경우 메모리 누수의 원인이 될 수 있습니다.
메모리 누수를 방지하기 위해 이러한 전략들을 적절히 사용하고, 정기적으로 코드 리뷰와 리팩토링을 통해 코드베이스를 깨끗하게 유지하는 것이 중요합니다.
useEffect(() => {
// 이벤트 리스너 등록
window.addEventListener("resize", handleResize);
// 클린업 함수
return () => {
// 이벤트 리스너 해제
window.removeEventListener("resize", handleResize);
};
}, []);
useEffect 훅을 사용하여 이벤트를 등록 후, 클린업 함수를 통해 컴포넌트가 언마운트될 때 이벤트 리스너를 해제해야 합니다. 이렇게 하지 않으면, 컴포넌트가 사라진 후에도 이벤트 리스너가 남아있어 브라우저가 해당 리스너를 계속 추적하게 되고, 이는 메모리 누수로 이어질 수 있습니다.
클린업 함수는 컴포넌트가 언마운트될 때 실행되어, 이벤트 리스너를 안전하게 제거합니다. 이렇게 하면 리소스 누수를 방지하고 메모리 관리를 효율적으로 할 수 있습니다.