가비지 컬렉션

Yerim Son·2023년 9월 15일
0

1) 메모리 생존 주기

가비지 컬렉션의 대상인 메모리에 대해서 알아보자.
메모리는 다음과 같은 생존 주기를 지닌다.

1. 할당한다.

자바스크립트는 변수를 선언할 때 자동으로 메모리를 할당한다.
원시 타입 값들은 스택 영역에, 참조 타입의 값은 힙 영역에 저장되며, 그 주소값은 스택 영역에 저장된다.
또한 변수 식별자는 스택 영역 상의 실행 컨텍스트의 렉시컬 환경에 저장된다.

이미지 출처: https://fe-developers.kakaoent.com/2022/220519-garbage-collection/
const a = 10; // 원시 타입은 메모리 스택 영역에 저장
const b = [1, 2, 3]; // 배열, 함수, 객체는 힙 영역에 저장

2. 사용한다(참조).

v8 엔진에 의해 전역 실행 컨텍스트 렉시컬 환영에 있는 식별자 a, b를 참조한다.

console.log(a); // 10
console.log(b[0]); // 1

3. 필요 없으면 해제한다.

쓸모없는 메모리 영역을 자동으로 해제해주는 것이 바로 가비지 컬렉터(GC)이다.
그렇다면 GC는 어떤 기준으로 메모리 영역을 더 이상 쓸모없다고 판단할까?
어떤 원리로 가비지 컬렉션이 동작할까?



2) v8 엔진의 메모리 구조

출처: https://fe-developers.kakaoent.com/2022/220519-garbage-collection/

프로그램을 실행하면 메모리의 빈 공간이 할당되는데, 이 할당된 공간을 'Resident Set'이라고 한다.
Resident Set은 크게 스택 메모리와 힙 메모리로 나뉜다.
(자바스크립트는 싱글스레드여서 스택 메모리를 하나만 가진다.)

스택은 함수 호출이 끝난 후 자바스크립트 엔진에 의해 정리되지만, 힙 메모리는 그렇지 않다. 따라서 힙에 있는 쓸모없는 메모리가 해제되지 않는다면, 메모리 누수 가 발생하여 프로그램 속도는 점점 느려질 것이다.

1. New Space, Old Space

가비지 컬렉션이 일어나는 영역은 힙 메모리의 New spaceOld space이다.

New SpaceOld Space
- 새로 만들어진 모든 객체를 저장.
- 짧은 생명주기.
- 2개의 semi-space로 이루어짐.
- minor GC가 관리함.
- Minor GC가 두 번 발생한 뒤
"New 영역"에서 살아남은 객체들이 이동하는 영역.
- Major GC가 관리.
- Old pointer space와 Old data space로 나뉘어짐.


3) 가비지 컬렉션(Garbage Collection)의 동작원리

  • New Space는 2개의 semi space로 또 나뉜다.
  • 객체는 처음에 New Space의 첫 번째 semi space에 할당된다.
  • GC가 한 번 실행된 후, 생존한 객체는 다른 semi space로 이동한다.
  • GC가 또 한 번 실행된 후(총2번), 생존한 객체는 Old Space로 이동한다.
  • 여기서 Old Space는 다른 객체를 참조하는 갳체인 Pointer Space와 데이터만 갖는 Data Space 영역으로 한 번 더 나뉜다.

1. Minor GC

  • Minor GC는 새로운 영역에 있는 객체 중에서 더 이상 사용되지 않는(unreachable) 객체들을 식별하고 수거(가비지 컬렉션)하는 작업을 수행한다.
  • Mark-Sweep-Compact 알고리즘을 사용하여 살아남을 객체를 결정한다.
  • 마이너 GC가 실행되면 살아남은 객체들은 From Space에서 To Space로 이동한다. 객체가 차있는 Space가 되니 From Space로 이름을 바꾼다.
  • 그 후 새로운 객체는 변한 From Space에 추가된다.
  • 이렇게 semi space는 상황에 따라 From 과 To가 변경되며 동작한다.
  • 메모리 단편화를 주기적으로 방지하는 장점이 있다.

V8 마이너 GC에 대한 슬라이드

2. Major GC

  • Mark-Sweep-Compact 알고리즘과 Tri-color 알고리즘을 사용한다.
  • 깊이 우선 탐색(DFS)으로 순회하며 Tri-color(white, gray, black)로 마킹하는 방식으로 가비지를 판단한다.
  • 마킹, 스위핑, 압축이라는 3단계를 거친다.
  • 참고 블로그: 자바스크립트 v8 엔진의 가비지 컬렉션 동작 방식



🤔 궁금증

실행 컨텍스트의 렉시컬 환경?

'실행 컨텍스트(Execution Context)'는 JavaScript 코드가 실행될 때 생성되는 환경을 나타낸다. 각 함수 호출, 블록 스코프, 전역 스코프 등 JavaScript 코드의 실행 맥락은 실행 컨텍스트로 표현된다. 실행 컨텍스트는 코드 실행에 필요한 여러 정보와 변수를 담고 있으며, 변수 식별자와 그 값들이 저장되는 환경을 가리킨다.

'렉시컬 환경(Lexical Environment)'은 실행 컨텍스트 내부의 일부로서, 변수와 함수의 식별자와 해당 변수 또는 함수의 값(또는 참조)을 관리하는데 사용된다.
이 렉시컬 환경은 스코프 체인과 함께 클로저, 스코프 규칙, 변수 및 함수의 스코프 등을 정의하는 데 중요한 역할을 한다.

따라서 문장 "변수 식별자 a 자체는 콜스택 상의 '실행 컨텍스트의 렉시컬 환경'이라는 곳에 저장된다"는 변수 'a'가 속한 스코프(실행 컨텍스트) 내의 렉시컬 환경에 저장된다는 의미다.
이 렉시컬 환경은 변수 'a'와 해당 값 또는 참조를 관리하며, 변수 'a'의 스코프에 대한 정보도 여기에 저장된다. 이러한 내부 환경은 변수와 함수의 스코프 결정 및 변수 식별자 해석에 사용된다.


스택 메모리와 힙 메모리의 차이점?

  1. 스택(Stack) 메모리

    스택 메모리는 함수 호출(call)과 관련된 데이터를 저장하는 데 사용된다. 함수가 호출될 때, 해당 함수의 로컬 변수, 매개변수 및 함수 내에서 사용되는 임시 데이터가 스택 메모리에 저장된다.
    스택은 후입선출(Last-In, First-Out, LIFO) 구조를 가지며, 가장 나중에 호출된 함수가 가장 먼저 실행을 완료하고 메모리에서 제거된다.
    따라서 스택은 함수의 호출과 반환을 관리하며, 함수가 끝나면 해당 함수와 연관된 데이터가 스택에서 제거된다.
    이 과정은 자바스크립트 엔진 내에서 자동으로 이루어진다. 즉, 개발자가 직접 메모리를 해제할 필요가 없다.

  1. 힙(Heap) 메모리

    힙 메모리는 동적으로 할당된 데이터와 객체를 저장하는 데 사용된다. 이러한 데이터는 함수 호출과는 관계없이 생성 및 소멸할 수 있다.
    힙 메모리는 스택과는 다르게 개발자가 직접 메모리 할당 및 해제를 관리해야 한다.
    메모리 할당은 개발자가 new 키워드나 다른 메모리 할당 메서드를 사용하여 이루어진다.
    메모리 해제는 개발자가 필요 없는 데이터를 더 이상 참조하지 않을 때, 해당 데이터에 대한 참조를 제거하거나 더 이상 필요하지 않은 객체에 대한 참조를 제거함으로써 이루어진다.
    일반적으로 가비지 컬렉션(Garbage Collection)이라는 메커니즘을 사용하여 더 이상 필요하지 않은 데이터를 정리하고 메모리 누수를 방지한다.

  2. 결론

    스택 메모리의 경우 자바스크립트 엔진이 함수 호출과 관련된 데이터를 자동으로 정리하고 메모리 관리를 처리하며, 힙 메모리의 경우 개발자가 메모리 할당과 해제를 직접 관리해야 한다는 차이점이 있다.


참고

0개의 댓글