/Development/JavaScript

Garbage Collection과 메모리 관리


JavaScript를 사용하다 보면 메모리 관리에 대해 크게 신경 쓰지 않아도 된다는 이야기를 자주 듣게 됩니다.
C나 C++ 같은 언어에서는 개발자가 직접 메모리를 할당하고 해제해야 하지만,
JavaScript는 자동 메모리 관리 기능을 제공하기 때문입니다.

이러한 자동 관리 시스템의 중심에는 Garbage Collection이라는 기능이 존재합니다.

Garbage Collection은 더 이상 사용되지 않는 데이터를 자동으로 제거하여
메모리를 효율적으로 관리하는 역할을 수행합니다.

덕분에 개발자는 메모리 해제 코드를 직접 작성하지 않아도 됩니다.

하지만 자동으로 관리된다고 해서 메모리 문제를 완전히 무시할 수 있는 것은 아닙니다.
잘못된 코드 구조는 메모리 누수(Memory Leak)를 유발할 수 있으며,
이는 성능 저하와 브라우저 멈춤 현상으로 이어질 수 있습니다.

따라서 JavaScript 개발자라면 Garbage Collection의 동작 원리와 메모리 관리 방식을 이해하는 것이 중요합니다.

메모리란 무엇인가

메모리는 프로그램이 데이터를 저장하고 사용하는 공간입니다.

변수를 선언하거나 객체를 생성하면
JavaScript 엔진은 메모리에 해당 데이터를 저장합니다.

숫자,
문자열,
배열,
객체,
함수 등 대부분의 데이터가 메모리를 사용합니다.

프로그램이 실행되는 동안 필요한 데이터는 계속 메모리에 유지됩니다.

하지만 사용이 끝난 데이터까지 계속 남아 있다면
메모리 사용량이 증가하게 됩니다.

결국 시스템 자원이 낭비되고 프로그램 성능에도 악영향을 주게 됩니다.

이 문제를 해결하기 위해 Garbage Collection이 필요합니다.

Garbage Collection이란 무엇인가

Garbage Collection은 더 이상 접근할 수 없는 데이터를 찾아 제거하는 과정입니다.

여기서 중요한 기준은 데이터가 실제로 사용되는지 여부가 아니라
현재 접근 가능한 상태인지 여부입니다.

어떤 객체가 프로그램 어디에서도 참조되지 않는다면
JavaScript 엔진은 해당 객체를 불필요한 데이터로 판단합니다.

이후 Garbage Collector가 이를 탐지하여 메모리에서 제거합니다.

개발자는 별도의 삭제 코드를 작성할 필요가 없습니다.

엔진이 자동으로 메모리를 회수하기 때문입니다.

이러한 구조 덕분에 JavaScript는 비교적 안전한 메모리 관리 환경을 제공합니다.

Reachability 개념이 중요한 이유

현대 JavaScript 엔진은 Reachability라는 개념을 기준으로 메모리를 관리합니다.

Reachability는 특정 데이터에 접근 가능한 경로가 존재하는지를 의미합니다.

전역 변수는 항상 접근 가능하므로 Reachable 상태입니다.

또한 전역 객체가 참조하는 데이터,
현재 실행 중인 함수가 참조하는 데이터 역시 Reachable 상태로 간주됩니다.

반대로 어떠한 경로로도 접근할 수 없는 데이터는 Unreachable 상태가 됩니다.

Garbage Collector는 이러한 데이터를 Garbage로 판단합니다.

즉 Reachability는 Garbage Collection의 핵심 판단 기준이라고 볼 수 있습니다.

Mark and Sweep 알고리즘

대부분의 JavaScript 엔진은 Mark and Sweep 알고리즘을 사용합니다.

먼저 전역 객체와 같은 Root 객체부터 탐색을 시작합니다.

접근 가능한 모든 객체를 찾아 표시하는 과정을 Mark 단계라고 합니다.

탐색이 완료되면 표시되지 않은 객체들을 확인합니다.

이 객체들은 접근 경로가 존재하지 않는 상태입니다.

이후 메모리에서 제거하는 과정을 Sweep 단계라고 부릅니다.

이러한 과정을 반복하면서 JavaScript 엔진은 사용하지 않는 메모리를 정리합니다.

현재 대부분의 브라우저 엔진 역시 이 방식을 기반으로 동작합니다.

객체와 참조의 관계

JavaScript에서 객체는 참조 형태로 관리됩니다.

변수에 객체를 저장한다고 해서 실제 객체가 변수 내부에 들어가는 것은 아닙니다.

변수는 객체가 위치한 메모리 주소를 참조하게 됩니다.

여러 변수가 동일한 객체를 참조할 수도 있습니다.

이 경우 하나의 참조만 제거된다고 해서 객체가 삭제되지는 않습니다.

모든 참조가 제거되어야 Garbage Collection 대상이 됩니다.

따라서 객체의 생명 주기는 참조 관계에 의해 결정된다고 볼 수 있습니다.

Closure가 메모리에 미치는 영향

Closure는 메모리 관리와 매우 밀접한 관계를 가집니다.

Closure가 외부 변수에 접근하고 있다면
JavaScript 엔진은 해당 데이터를 계속 유지합니다.

함수가 종료되었더라도 참조가 남아 있는 한
데이터는 Garbage Collection 대상이 되지 않습니다.

이러한 특성 덕분에 상태 관리와 데이터 은닉이 가능해집니다.

하지만 불필요한 객체를 Closure가 참조하고 있다면
예상치 못한 메모리 사용 증가가 발생할 수 있습니다.

따라서 Closure를 사용할 때는 참조 관계를 주의 깊게 관리해야 합니다.

메모리 누수는 왜 발생할까

메모리 누수는 더 이상 필요하지 않은 데이터가 메모리에 계속 남아 있는 현상을 의미합니다.

대표적인 원인으로는 전역 변수 남용,
불필요한 이벤트 리스너,
해제되지 않은 타이머,
과도한 Closure 사용 등이 있습니다.

특히 SPA 환경에서는 페이지 새로고침 없이 오랜 시간 동작하기 때문에
메모리 누수 문제가 더욱 중요하게 다뤄집니다.

메모리 누수가 누적되면 브라우저 성능이 저하되고
심한 경우 탭이 강제로 종료될 수도 있습니다.

따라서 참조가 필요 없는 객체는 적절히 정리하는 습관이 중요합니다.

실무에서 메모리 관리를 알아야 하는 이유

현대 웹 애플리케이션은 수많은 데이터를 처리합니다.
실시간 채팅,
대시보드,
대규모 리스트 렌더링,
파일 업로드 등은 모두 많은 메모리를 사용합니다.

Garbage Collection이 자동으로 동작하더라도
잘못된 참조 구조는 성능 문제를 발생시킬 수 있습니다.

Chrome DevTools와 같은 도구를 활용하면
메모리 사용량과 누수 여부를 분석할 수 있습니다.

특히 React,
Vue,
Angular 프로젝트에서는 컴포넌트 제거 시점의 메모리 관리가 매우 중요합니다.

결국 메모리 관리는 고성능 웹 애플리케이션을 구축하기 위한 필수 지식이라고 할 수 있습니다.

Summary

Garbage Collection

• 사용하지 않는 데이터를 자동으로 제거하는 기능.
• JavaScript의 자동 메모리 관리 시스템임.
• Reachability를 기준으로 동작함.
• 개발자가 직접 메모리를 해제할 필요가 없음.

Memory Management

• 객체는 참조를 통해 관리됨.
• 모든 참조가 제거되어야 메모리가 회수됨.
• Closure와 이벤트 리스너는 메모리 유지에 영향을 줌.
• 메모리 누수 예방은 실무에서 매우 중요함.


블로그 목록