오늘은 가비지 컬렉션(Garbage Collection)에 대해 이야기 해보겠습니다~
✅ 자바스크립트의 메모리 관리
JS는 자동 메모리 관리를 통해 개발자가 따로 신경 쓰지 않아도 메모리를 정리해줍니다.
더 이상 필요하지 않은 메모리를 자동으로 회수하 메모리의 누수를 방지해주죠!
이러한 역할을 하는게 '가비지 컬렉션' 이라고 할 수 있습니다.
그런데 "더 이상 필요하지 않은 데이터 라는 것을 자바스크립트가 어떻게 알아낼까?" 라는 의문이 들지 않나요??
저는 궁금했습니다ㅎㅎ
결론부터 이야기하자면 가비지 컬렉션은 다음 두 가지 기준에 따라 동작하게 됩니다.
- 도달 가능성(Reachability)
프로그램 내에서 참조되지 않는 객체를 식별하여 객체가 현재 코드에서 접근이 불가능하다면, 이 상태를 "도달할 수 없는 상태"로 간주하고 메모리에서 제거합니다. - 루트의 참조
객체가 전역 변수, 함수 호출 스택, 클로저 등에서 참조되고 있지 않으면 즉, 루트에서 참조되고 있지 않으면 도달 불가능한 상태로 간주되어 메모리에서 제거합니다.
✅ 도달 가능성(Reachability)
위에서 설명한 도달 가능한 값. 즉 어떤 방식으로든 접근 가능한 값을 알아볼까요?
< 도달 가능한 값의 예 >
1. 전역 변수
예)
let globalVar = { key: "value" };
2. 현재 실행 중인 함수의 지역 변수
예)
function greet() {
let name = "John"; // name은 도달 가능한 상태
console.log(name);
}
3. 중첩 함수에서 사용되는 변수
클로저로 인해 참조가 유지되는 경우.
- 🌟 즉, JS에서 어떤 방식으로든 접근이 가능하다고 판단 하는 값은 메모리에 자리를 차지하며 남아있고, 자바스크립트가 필요 없다고 판단한 값만 메모리에서 제거되는 것 입니다.
✅ 루트(Root)의 참조
두 번째 기준인 루트의 참조 입니다. 가비지 컬렉터는 루트에서 참조 되고 있는 값이라면 동작하지 않습니다.
그럼 일단 루트가 뭘까요?
대표적인 루트는 아래와 같습니다.
- 전역 객체 (브라우저 환경에서는 window, Node.js에서는 global)
- 스택에 저장된 함수 호출의 지역 변수 혹 매개변수
- 클로저로 유지되는 변수
이런 루트에서 직접 참조하거나, 루트가 참조하는 객체가 또 다른 객체를 참조하는 경우! 이러한 객체들은 모두 도달 가능한 상태로 간주되어서 가비지 컬렉션이 동작하지 않는 것 입니다~
반대로, 루트에서 직접적 혹은 간접적으로 참조할 수 없는 객체는 도달 불가능한 상태가 되어 메모리에서 제거되게 됩니다.
그래서 클로저를 사용하는 주요 이유 중 가비지 컬렉션에 의해 메모리가 제거되지 않게 하기 위함이 있었죠!
루트의 참조를 코드로 이해해 봅시다!
// 전역 객체에 객체를 할당
let rootObj = { name: "Root" };
// 새로운 객체를 rootObj가 참조
rootObj.child = { name: "Child" };
// 루트에서 간접적으로 참조 가능
console.log(rootObj.child.name); // "Child"
// 루트에서의 참조를 제거
rootObj = null;
// 이제 Child 객체는 도달할 수 없는 상태가 된다.
// 따라서 가비지 컬렉터에 의해 메모리에서 제거될 수 있다.
또, 아래 코드와 같이 서로 참조하고 있는 객체도 루트에서 참조하지 않으면 제거되게 됩니다.
function createFriends() {
let ju = { name: "Ju" };
let beom = { name: "Beom" };
// 서로 참조
ju.connectedFriend = beom;
beom.connectedFriend = ju;
return { bestFriend1: ju, bestFriend2: beom };
}
let friends = createFriends();
// 모든 객체는 도달 가능한 상태
console.log(friends);
// 루트에서의 참조 제거
friends = null;
// 이제 Ju와 Beom은 도달할 수 없는 상태가 되어 메모리에서 제거된다.
Ju와 Beom는 서로를 참조하고 있지만, 더 이상 루트에서 접근할 수 없으므로 메모리에서 제거되게 되는 것 입니다.
✅ 가비지 컬렉션 동작 방식
자바스크립트는 Mark-and-Sweep(마크-스윕) 알고리즘을 사용해 메모리를 정리합니다.
이 알고리즘은 아래와 같이 동작합니다.
- 루트부터 시작해 모든 도달 가능한 객체를 찾기
- 도달 가능한 객체들은 마킹(marking)하기 -> 마킹 된 객체들은 메모리가 정리되지 않음
- 도달 불가능한 객체는 메모리에서 제거(sweep)
위 gif처럼 동작하는 것 입니다.
✅ 마무리
오늘은 자바스크립트의 가비지 컬렉션에 대해 설명해보았습니다! 자바스크립트는 자동 메모리 관리 기능을 통해 더 이상 필요하지 않은 메모리를 정리하는데, 이러한 메모리 관리는 '도달 가능성(Reachability)'과 '루트의 참조' 라는 기준에 따라 이루어지게 됩니다.
우리 개발자들은 이 자동 메모리 관리 덕분에 자바스크립트의 메모리 누수를 걱정하지 않고 조금은 덜 귀찮게(?) 코드를 작성할 수 있게 된 것 이죠!
(참고)
'🦁부트캠프 > 🐯 JS 수업 정리' 카테고리의 다른 글
[Javascript] 옵셔널 체이닝(Optional Chaining) 이란? (1) | 2024.12.15 |
---|---|
Vite를 사용하는 이유 (0) | 2024.12.01 |
Ajax와 비동기 통신 (0) | 2024.11.23 |
[10/30] 엄격모드, 전역 객체, 오래된 var, 호이스팅, 데이터 타입(자료형) (0) | 2024.11.16 |
[10 / 29] JS란? | 코드 구조 | 변수와 상수 (3) | 2024.11.10 |