Algorithm|Javascript Algorithm

표시하고 쓸기 알고리즘

0

크리스는 가비지 콜렉터(GC)가 "도달 가능성(Reachability)"을 기준으로 메모리를 관리한다는 것을 알았다.

하지만 궁금증이 또 생겼다.

"메모리 전체를 뒤져서 도달 가능한지 아닌지 확인하려면 시간이 꽤 걸릴 텐데? 게임을 하고 있는데 청소부가 갑자기 나타나서 '잠깐! 나 청소 좀 할게' 하고 1초 동안 화면을 멈춰버리면 어떡해?"

실제로 과거의 GC는 청소를 위해 프로그램 실행을 잠시 멈추는 "Stop-the-world" 현상이 심했다.

하지만 현대의 브라우저(V8 엔진 등)는 사용자가 눈치채지 못할 만큼 빠르고 똑똑하게 청소를 수행한다. 그 기반이 되는 알고리즘이 바로 **표시하고 쓸기(Mark-and-Sweep)**다.

1. 페인트통 들고 순찰하기

이 알고리즘의 동작 방식은 페인트 칠하기로 비유할 수 있다.

GC는 주기적으로 페인트통을 들고 메모리 영역을 순찰한다.

1단계: 표시하기 (Mark)

  • *루트(Root)**에서 시작한다. (전역 객체, 현재 실행 중인 함수의 변수 등)
  • 루트가 참조하는 모든 객체를 찾아가서 "살아있음(Alive)" 표시(Mark)를 남긴다.
  • 그 객체들이 또 참조하는 객체들을 찾아가서 표시를 남긴다.
  • 도달할 수 있는 모든 객체에 표시가 될 때까지 이 과정을 반복한다.
  • 2단계: 쓸어버리기 (Sweep)

  • 이제 메모리 전체를 훑는다.
  • "살아있음" 표시가 없는 객체들을 발견하면? 가차 없이 메모리에서 해제(삭제)한다.
  • 다음 청소를 위해 모든 표시를 지운다.
  • 2. 순환 참조의 종말

    지난 시간에 참조 카운팅(Reference Counting) 방식이 해결하지 못했던 '고립된 섬(순환 참조)' 문제를 기억하는가?

    JavaScript

    // 서로 참조하지만, 루트에서는 연결이 끊긴 상태 objA.friend = objB; objB.friend = objA; root.data = null; // 연결 끊음

    Mark-and-Sweep 알고리즘 앞에서는 이들도 짤없다.

  • GC가 루트에서 출발한다.
  • objAobjB로 가는 길이 없다.
  • 따라서 이들에는 **Mark(표시)**가 남지 않는다.
  • Sweep 단계에서 "표시가 없네? 쓰레기구나" 하고 둘 다 삭제된다.
  • 이 알고리즘 덕분에 자바스크립트 개발자들은 더 이상 순환 참조 메모리 누수 공포에 시달리지 않게 되었다.

    3. 최적화: 청소도 요령껏 (Generational Collection)

    "그래도 메모리가 몇 GB나 되면 다 훑는 데 오래 걸리지 않을까?"

    맞다. 그래서 V8 같은 최신 엔진은 무식하게 매번 전체를 훑지 않는다. **세대별 가비지 콜렉션(Generational Garbage Collection)**이라는 고급 기술을 쓴다.

    가설: "대부분의 객체는 금방 죽는다."

    함수 안에서 잠깐 쓴 변수나 임시 객체들은 만들자마자 할 일을 다하고 금방 쓰레기가 된다. 반면, 전역 설정이나 코어 데이터는 프로그램이 끝날 때까지 살아남는다.

    엔진은 메모리 영역을 두 개로 나눈다.

  • 새로운 세대 (Young Generation/Nursery):
  • 오래된 세대 (Old Generation):
  • 이렇게 하면 GC는 대부분의 시간을 크기가 작은 '새로운 세대'만 빠르게 훑고 지나가기 때문에, **브라우저 멈춤 현상(Freezing)**을 최소화할 수 있다.

    4. 우리가 할 일은?

    "엔진이 이렇게 똑똑하면 개발자는 아무것도 안 해도 되나?"

    아쉽게도 완벽하지는 않다. GC는 "참조가 남아있는 한" 절대 지우지 않는다.

    우리가 실수로 불필요한 참조를 남겨두면, GC는 "아, 개발자가 이거 쓰는구나"라고 오해하고 영원히 메모리에 남겨둔다. 이것이 바로 **메모리 누수(Memory Leak)**다.

    개발자가 흔히 저지르는 실수로 인해 GC가 청소를 못 하는 대표적인 시나리오들을 알아야 내 앱을 지킬 수 있다.

    7장의 마지막 주제, "[JavaScript] 그 밖의 메모리 누수 시나리오: 개발자의 실수들" 편에서 계속된다.


    🔗 참고 링크

  • V8 - Trash talk: the Orinoco garbage collector
  • JavaScript Memory Management Masterclass
  • 댓글 (0)

    0/1000
    댓글을 불러오는 중...