자바스크립트는 눈에 보이지 않는 곳에서 메모리 관리를 수행한다.
코드를 동작시키면 결국 거의 모든것은 메모리를 사용하게 된다. 값 , 변수 , 함수 ,배열 , 객체 등등 우리가 코드를 짜면서 사용하게 되는 거의 모든 것들 말이다.
그렇다면 쓸모없어진 값들을 처리하는 방법이 필요할 것인데 JS 엔진은 어떤 방식으로 이를 해결할까?
JS는 reachability ( 도달 가능성 ) 이란 개념을 활용해서 메모리를 관리한다.
쉽게 생각해서 현재 접근할 수 있는 값이라면 삭제하지 않는다.
현재 함수의 지역 변수와 매개변수
중첩 함수의 체인에 있는 함수에서 사용되는 변수와 매개변수
전역 변수
기타 등등
위 값들은 선언 하면서부터 사라질 일이 없기때문에 명백한 이유 없이는 절대 삭제되지 않는다.
이런 값들을 루트 라고도 한다.
만약 전역 변수에 객체가 저장되어 있고, 그객체가 다른 객체를 참조하고 있다고 생각해보자.
도달할 수 있는 객체가 참조하기에 해당 객체도 도달할 수 있는 객체가 된다.
아래 예시를 보자.
// user엔 객체 참조 값이 저장됩니다.
let user = {
name: "John"
};
user란 변수에 객체를 저장하였다.
user = null;
그런데 위와 같이 user의 값을 덮어쓰면 원래 있던 객체는 도달할 수 없는 값이되어 더이상 접근할 수 없기에 해당 객체는 메모리에서 삭제하게 되는 것이다.
// user엔 객체 참조 값이 저장됩니다.
let user = {
name: "John"
};
let admin = user;
만약 위처럼 두개의 변수에 같은 참조값을 넣어 둔다면
user = null;
user을 비운다 해도 John이 담긴 객체가 사라지지 않을 것이다.
조금더 복잡한 경우를 살펴보자.
function marry(man, woman) {
woman.husband = man;
man.wife = woman;
return {
father: man,
mother: woman
}
}
let family = marry({
name: "John"
}, {
name: "Ann"
});
다음과 같이 두 객체를 연결해보자.
delete family.father;
delete family.mother.husband;
이 경우 이름이 John인 객체의 참조를 모두 지워보자.
물론 John.wife는 Ann을 가리키고 있겠지만, John을 가리키는 그 어떤 요소도 없기 때문에 John은 메모리에서 제거되게 된다.
즉, 가비지 컬렉션은 도달 가능성을 체크한 이후, 도달가능성이 없는 모든 메모리를 삭제하는 과정을 거친다.
가비지 컬렉터는 루트(root) 정보를 수집하고 이를 ‘mark(기억)’ 합니다.
루트가 참조하고 있는 모든 객체를 방문하고 이것들을 ‘mark’ 합니다.
mark 된 모든 객체에 방문하고 그 객체들이 참조하는 객체도 mark 합니다. 한번 방문한 객체는 전부 mark 하기 때문에 같은 객체를 다시 방문하는 일은 없습니다.
루트에서 도달 가능한 모든 객체를 방문할 때까지 위 과정을 반복합니다.
mark 되지 않은 모든 객체를 메모리에서 삭제합니다.
해당 과정을 도식화하면 위와 같다.
가비지 컬렉션을 좀더 빠르게 수행하는 몇가지 기법이 존재하지만 이번 글에서는 가비지 컬렉션에 대한 간단한 정의만 정리해보았다.
'FrontEnd > JavaScript' 카테고리의 다른 글
[JS] Symbol (0) | 2023.06.09 |
---|---|
[JS] 옵셔널 체이닝 ?. (1) | 2023.06.08 |
[JS] 폴리-필(Polyfill) , 바벨 (0) | 2023.05.26 |
[JS] 정수로 만들어주는 3가지 방법 비교 (0) | 2023.05.09 |
28_타입스크립트 보다 자세한 문법 (0) | 2022.01.08 |