20. 가비지 컬렉션
2026년 4월 11일
자바스크립트
1. 도달 가능성 (Reachability)
자바스크립트 메모리 관리의 핵심은 **"지금 이 값을 사용할 수 있는가?"**입니다. 이 기준을 **'도달 가능성'**이라고 부릅니다.
- 루트(Roots): 태생부터 도달 가능한 값들입니다. (삭제 불가)
- 현재 함수의 지역 변수, 매개변수
- 중첩 함수 체인의 변수들
- 전역 변수 등
- 도달 가능한 값: 루트에서 시작해 참조(화살표)를 따라가서 어떻게든 닿을 수 있는 값은 메모리에서 유지됩니다.
- 가비지 컬렉터: 모든 객체를 감시하며, 루트에서 도달할 수 없게 된 객체는 메모리에서 삭제합니다.
2. 도달할 수 없는 섬 (Unreachable Islands)
참조가 서로 얽혀 있어도 루트(Root)와의 연결이 끊어지면 메모리에서 통째로 사라집니다.
- 특징: 객체 A와 B가 서로를 참조하고 있더라도(순환 참조), 외부에서 이들을 참조하는 루트가 사라지면 가비지 컬렉션의 대상이 됩니다.
- 교훈: 객체 내부에서 서로를 참조하는 것보다, **"외부(루트)에서 들어오는 참조가 있는가"**가 훨씬 중요합니다.
3. 내부 알고리즘: Mark-and-Sweep
가비지 컬렉션이 실제로 동작하는 기본 알고리즘입니다. 엔진은 주기적으로 다음 단계를 거칩니다.
- Mark (마킹): 루트(Root) 정보를 수집하고 기억합니다.
- Visit (방문): 루트가 참조하는 객체들을 방문하여 마크합니다. 마크된 객체가 참조하는 다른 객체들도 계속 따라가며 마크합니다.
- Sweep (삭제): 마크되지 않은(페인트가 칠해지지 않은) 모든 객체를 메모리에서 삭제합니다.
🚀 4. 엔진의 최적화 기법
가비지 컬렉션은 CPU 리소스를 소모하므로, 모던 엔진(V8 등)은 성능 저하를 막기 위해 여러 기법을 씁니다.
| 기법 | 설명 |
|---|---|
| 세대별 수집 (Generational) | 신규 객체는 공격적으로 제거하고, 오래 살아남은 객체는 덜 감시합니다. |
| 점진적 수집 (Incremental) | 한 번에 다 하지 않고 작업을 쪼개서 수행해 실행 지연을 분산시킵니다. |
| 유휴 시간 수집 (Idle-time) | CPU가 한가할 때만 청소부(GC)를 돌립니다. |
🎙️ 기술 면접 대비 (Interview Questions)
Q1. 자바스크립트의 가비지 컬렉션 기준은 무엇인가요? (기초)
답변: **'도달 가능성(Reachability)'**을 기준으로 합니다. 루트(전역 변수, 지역 변수 등)에서 시작해 참조 체인을 통해 접근할 수 있는 객체는 유지하고, 어떤 경로로도 도달할 수 없게 된 객체는 메모리에서 자동으로 제거합니다.
Q2. '순환 참조'가 발생해도 가비지 컬렉션이 이루어질 수 있나요? (중급)
답변: 네, 가능합니다. 객체들이 서로를 참조하고 있더라도(도달할 수 없는 섬), 그 집합 자체가 전역 루트와 연결되어 있지 않다면 마크-앤-스윕 알고리즘에 의해 통째로 메모리에서 삭제됩니다.
Q3. 가비지 컬렉션으로 인한 성능 저하를 엔진은 어떻게 해결하나요? (심화)
답변: 모든 객체를 한 번에 검사하면 'Stop-the-world' 현상(실행 멈춤)이 발생하므로, 작업을 쪼개서 하는 점진적 수집, 객체의 수명에 따라 빈도를 조절하는 세대별 수집, CPU가 쉴 때만 동작하는 유휴 시간 수집 등의 최적화 기법을 사용합니다.
💡 기억해야 할 중요한 내용
- 수동 삭제는 불가능합니다.
user = null처럼 참조를 끊어 도달 불가능하게 만들 수는 있지만,delete user같은 명령어로 메모리를 즉시 직접 비울 수는 없습니다. 그건 전적으로 엔진의 몫입니다. - 루트를 조심하세요. 전역 변수는 프로그램 종료 시까지 메모리에 남으므로, 불필요한 전역 변수 남발은 메모리 누수의 주범이 됩니다.