자바스크립트는 눈에 보이지 않는 곳에서 메모리 관리를 수행
원시값, 객체, 함수 등 우리가 만드는 모든 것은 메모리를 차지합니다. 그렇다면 더는 쓸모 없어지게 된 것들은 어떻게 처리될까요? 지금부턴 자바스크립트 엔진이 어떻게 필요 없는 것을 찾아내 삭제하는지 알아보겠습니다.
자바스크립트는 도달 가능성 이라는 개념을 사용해 메모리 관리를 수행
도달 가능한 값은 쉽게 말해 어떻게든 접근하거나 사용할 수 있는 값을 의미합니다. 도달 가능한 값은 메모리에서 삭제되지 않습니다.
// user엔 객체 참조 값이 저장됩니다.
let user = {
name: "John"
};
이 그림에서 화살표는 객체 참조를 나타냅니다. 전역 변수 "user"는 {name:"John"} (줄여서 join)이라는 객체를 참조 John의 프로퍼티 "name"은 원시값을 저장하고 있기 때문에 객체 안에 표현
user의 값을 다른 값으로 덮어쓰면 참조(화살표)가 사라집니다.
user = null;
이제 John은 도달할 수 없는 상태가 되었다. John에 접근할 방법도, John을 참조하는 것도 모두 사라졌습니다.
가비지 컬렉터는 이제 John에 저장된 데이터를 삭제하고, John을 메모리에서 삭제
// user엔 객체 참조 값이 저장됩니다.
let user = {
name: "John"
};
let admin = user;
user = null;
function marry(man, woman) {
woman.husband = man;
man.wife = woman;
return {
father: man,
mother: woman
}
}
let family = marry({
name: "John"
}, {
name: "Ann"
});
함수 marry는 매개변수로 받은 두 객체를 서로 참조하게 하면서 '결혼'시키고, 두 객체를 포함하는 새로운 객체를 반환
메모리 구조는 아래와 같이 나타남
지금은 모든 객체가 도달 가능한 상태입니다.
이제 참조 두 개를 지워보겠습니다.
delete fmaily.father;
delete fmaily.mother.husband;
외부로 나가는 참조는 도달 가능한 상태에 영향을 주지 않는다. 외부에서 들어오는 참조만이 도달 가능한 상태에 영향을 줍니다. John은 이제 도달 가능한 상태가 아니기 때문에 메모리에서 제거 됩니다. John에 저장된 데이터 역시 메모리에서 사라집니다.
가비지 컬렉션 후 메모리 구조는 아래와 같습니다.
객체들이 연결되어 섬 같은 구조를 만드는데, 이 섬에 도달할 방법이 없는 경우, 섬을 구성하는 객체 전부가 메모리에서 삭제됩니다.
근원 객체 family가 아무것도 참조하지 않도록 해 봅시다.
family = null;
도달할 수 없는 섬 예제는 도달 가능성이라는 개념이 얼마나 중요한지 보여줍니다.
John과 Ann은 여전히 서로를 참조하고 있고, 두 객체 모두 외부에서 들어오는 참조를 갖고 있지만, 이것만으로는 충분하지 않다는걸 보여주죠.
famliy 객체와 루트의 연결이 사라지면 루트 객체를 참조하는 것이 아무것도 없게 됨. 섬 전체가 도달할 수 없는 상태가 되고, 섬을 구성하는 객체 전부가 메모리에서 제거되죠.
오른편에 도달할 수 없는 섬이 보이네요. 이제 가비지 컬렉터의 mark-and-sweep 알고리즘이 이것을 어떻게 처리하는지 봅시다.
첫 번째 단계에선 루트를 mark합니다.
루트에서 페인트를 들이붓는다고 상상하면 이 과정을 이해하기 쉽습니다. 루트를 시작으로 참조를 따라가면서 도달가능한 객체 모두에 페인트가 칠해진다고 생각하면 됨. 이때 페인트가 묻지 않는 객체는 메모리에서 삭제
지금까지 가비지 컬렉션이 어떻게 동작하는지에 대한 개념을 알아보았습니다. 자바스크립트 엔진은 실행에 영향을 미치지 않으면서 가비지 컬렉션을 더 빠르게 하는 다양한 최적화 기법을 적용
최적화 기법
위 내용은 javascipt.info 사이트에서 공부한 내용 정리
자세한 내용은 아래 링크를 참고 하세요
https://ko.javascript.info/garbage-collection