가비지 컬렉션(Garbage Collection)이란 프로그래밍 언어에서 메모리 관리를 자동화하기 위한 기술입니다. 일반적으로 프로그램은 동적으로 메모리를 할당하여 사용하고, 더 이상 참조되지 않는 메모리는 해제해야 합니다. 그러나 이를 수동으로 관리하면 memory leaks나 invalid references와 같은 문제가 발생할 수 있습니다.
이러한 문제를 방지하기 위해 가비지 컬렉터(garbage collector)는 프로그램이 동적으로 할당한 메모리 중에서 더 이상 사용되지 않는 메모리를 식별하고 해제하는 작업을 자동으로 수행합니다.
가비지 컬렉션은 다양한 알고리즘과 방식으로 구현될 수 있으며, 일반적으로 사용되는 방법에는 "참조 계수(reference counting)"가 있습니다.
참조 계수 방식은 객체가 참조되는 횟수를 추적하여 해당 객체의 참조 계수가 0이 되면 메모리를 해제하는 방법입니다. 각 객체마다 참조 계수(reference counter)라고 불리는 정수형 변수를 가지며, 이 변수는 해당 객체를 참조하는 포인터의 개수를 나타냅니다. 객체가 생성될 때 참조 계수는 1로 초기화되며, 다른 변수가 그 객체를 참조할 때 참조 계수는 1씩 증가하고 참조가 해제될 때 1씩 감소합니다. 가비지 컬렉터는 이 참조 계수가 0인 객체를 메모리에서 자동으로 해제합니다.
가비지 컬렉션은 일반적으로 다음과 같은 매커니즘으로 동작합니다.
- Reachability (도달 가능성) 검사: 가비지 컬렉터는 메모리 상에서 어떤 객체에 접근할 수 있는지 여부를 판단합니다. 주어진 시작점으로부터 도달 가능한 모든 객체를 식별하고, 이들 객체에 대한 참조 체인을 따라가며 도달 가능한 객체로 마킹합니다.
- Marking (마킹): 도달 가능한 객체들은 가비지 컬렉터에 의해 마킹됩니다. 이 과정에서, 특정 알고리즘(예: 마크-앤-스위프, 세대별 가비지 컬렉션 등)을 사용하여 메모리 상에서 도달 가능한 객체를 식별합니다.
- Sweep (스위핑): 마킹 단계 이후에는 마킹되지 않은 객체를 가비지로 간주하고 메모리를 해제합니다. 메모리 해제는 이후에 재사용 가능한 자유 공간으로 표시됩니다.
- Compact (압축, 선택적): 일부 가비지 컬렉터는 메모리의 단편화를 최소화하기 위해 압축 단계를 수행합니다. 이 단계에서 메모리의 사용 상태를 조정하여 연속된 공간을 만듭니다. 압축은 메모리 할당과 해제의 효율성을 향상시키고, 객체 접근 시간을 개선할 수 있습니다.
GC가 제대로 동작되도록 코드를 작성하는 법
- 사용하지 않는 객체에 대한 참조를 명시적으로 제거한다.
- 큰 객체를 사용한 후에는 가능한 빨리 메모리를 해제한다.
- 순환 참조를 피한다.
- 메모리 누수를 방지한다.