들어가며
C++ STL 컨테이너를 보다 보면 이런 코드를 자주 보게 됩니다.
std::vector<int, std::allocator> numbers;
그런데 대부분의 경우, allocator는 직접 건드리지 않습니다.
왜냐하면, 기본 allocator만 사용해도 대부분 잘 동작하기 때문입니다.
그래서 처음 allocator를 접하면 이런 생각이 들기도 합니다.
“도대체 allocator는 왜 존재하는 걸까?”
혹은:
“실무에서는 allocator를 진짜 사용하는 걸까?”
이번 글에서는
- allocator의 기본 개념
- STL과 allocator의 관계
- 메모리 할당 분리 구조
- 실무에서 allocator가 중요한 이유
- 게임 엔진에서 사용하는 allocator 구조
를 중심으로 정리해보겠습니다.
allocator란?
allocator는 쉽게 말하면 메모리 할당 정책을 담당하는 객체입니다.
즉,
메모리를 어디서,
어떤 방식으로,
어떻게 할당할 것인가?
를 담당합니다.
C++ STL 컨테이너들은 메모리 관리를 allocator에 위임합니다.
std::vector v;
내부적으로는 사실
std::vector<int, std::allocator> v;
와 비슷한 형태입니다.
즉, allocator는 STL 내부 메모리 관리 핵심 구조 중 하나입니다.
왜 굳이 allocator를 분리했을까?
핵심 이유는 “컨테이너와 메모리 정책을 분리하기 위해서”입니다.
예를 들어 vector 자체는 배열 관리 / 삽입/삭제 / capacity 관리에 집중합니다.
반면, 메모리를 어디서 가져올지는 allocator가 담당합니다.
즉,
컨테이너
↓
데이터 구조 관리allocator
↓
메모리 관리
형태로 역할이 분리됩니다.
이 구조 덕분에 컨테이너는 메모리 정책과 독립적으로 동작할 수 있습니다.
기본 allocator는 결국 new/delete인가?
거의 그렇습니다.
기본 std::allocator는 내부적으로 결국 operator new / delete를 사용합니다.
예를 들어
T* ptr = allocator.allocate(n);
는 내부적으로 대략 이런 느낌입니다.
::operator new(sizeof(T) * n);
즉, 기본 allocator는 “STL 인터페이스 형태로 감싼 일반 힙 할당기”에 가깝습니다.
allocator가 중요한 진짜 이유
작은 프로젝트에서는 기본 allocator만 사용해도 충분합니다.
하지만 규모가 커지면 문제가 생깁니다.
대표적으로
- 메모리 단편화(Fragmentation)
- 할당 비용 증가
- 멀티쓰레드 lock 비용
- 캐시 효율 문제
같은 문제가 발생합니다.
특히 게임 엔진에서는 메모리 할당 자체가 성능 병목이 되는 경우가 많습니다.
왜 new/delete가 느려질까?
일반 힙 할당기는 굉장히 범용적으로 설계되어 있습니다.
- 크기 다양한 메모리 처리
- 멀티쓰레드 대응
- OS 메모리 관리 연동
등을 모두 고려해야 합니다.
그래서 내부적으로
- lock
- free list 탐색
- heap bookkeeping
같은 작업이 발생합니다.
즉, 반복적인 작은 메모리 할당에서는 비용이 커질 수 있습니다.
allocator의 핵심 아이디어
지금까지 설명한 allocator 구조와 메모리 관리 방식을 그림으로 정리해보면 다음과 같습니다.
핵심은 allocator는 단순 메모리 할당기가 아니라, 메모리 사용 패턴에 맞춰 성능 구조를 최적화하는 시스템이라는 점입니다.

allocator의 핵심은 “사용 패턴에 맞는 메모리 관리”입니다.
예를 들어
- 항상 같은 크기만 할당
- 프레임 단위로 전체 해제
- 한 번에 대량 할당
같은 패턴을 안다면 훨씬 빠른 allocator를 만들 수 있습니다.
즉, 범용 allocator보다 훨씬 효율적인 구조가 가능해집니다.
Pool Allocator
대표적인 allocator가 Pool Allocator입니다.
이 방식은 미리 큰 메모리 블록을 확보합니다.
그리고 같은 크기의 메모리를 빠르게 재사용합니다.
예
[64byte][64byte][64byte][64byte]
형태로 메모리를 관리합니다.
장점
- 빠른 할당/해제
- 단편화 감소
- 캐시 효율 향상
특히, 게임 오브젝트 관리에서 자주 사용됩니다.
Linear Allocator
또 다른 대표 구조는 Linear Allocator입니다.
이건 굉장히 단순합니다.
현재 포인터 위치 증가만 수행합니다.
즉, 메모리 할당이 사실상 pointer 증가만으로 끝납니다.
굉장히 빠릅니다.
대신 개별 해제가 어렵습니다.
그래서
- Frame Memory
- Temporary Buffer
같은 곳에서 자주 사용됩니다.
Stack Allocator
Stack Allocator는 LIFO 구조를 사용합니다.
즉, 마지막에 할당한 메모리부터 해제가능합니다.
일반 stack 메모리와 비슷한 개념입니다.
장점
- 매우 빠른 할당
- 매우 빠른 해제
단점
사용 순서 제약이 큽니다.
STL allocator 인터페이스
allocator는 특정 인터페이스를 만족하면 STL에 연결 가능합니다.
대표적으로
allocate() deallocate()
같은 함수들을 제공합니다.
예
template
class MyAllocator
{
public:
using value_type = T;
T* allocate(std::size_t n)
{
return static_cast<T*>(
::operator new(sizeof(T) * n));
}
void deallocate(T* ptr, std::size_t)
{
::operator delete(ptr);
}
};
그리고
std::vector<int, MyAllocator> v;
처럼 연결 가능합니다.
그런데 실무에서는 STL allocator를 많이 안 쓴다?
흥미로운 점은 실무 엔진 코드에서는 std::allocator 인터페이스를 직접 활용하지 않는 경우도 많다는 점입니다.
왜냐하면 엔진 레벨 메모리 시스템은 보통 STL보다 더 큰 범위를 관리하기 때문입니다.
예
- Frame Allocator
- Object Pool
- Job System Memory
- GPU Upload Buffer
즉, 엔진 전체 메모리 전략 자체를 설계하는 경우가 많습니다.
Unreal Engine도 allocator를 적극 사용한다
예를 들어 Unreal Engine도 독자적인 메모리 시스템을 사용합니다.
대표적으로:
- FMalloc
- Binned Allocator
- TInlineAllocator
같은 구조가 존재합니다.
특히, TInlineAllocator는 흥미로운 구조입니다.
일정 개수까지는 힙 할당 없이 stack/local memory를 사용합니다.
즉, 작은 메모리 할당 비용을 줄이는 최적화입니다.
allocator의 진짜 목적
처음 allocator를 배우면 “메모리 할당기를 바꿀 수 있는 기능”
정도로 보이기도 합니다.
하지만 실제 핵심은 “메모리 사용 패턴을 구조적으로 제어하는 것”에 가깝습니다.
즉
- 어디에 저장할지
- 언제 해제할지
- 어떤 비용 구조를 가질지
를 설계하는 문제입니다.
현대 엔진에서 allocator가 중요한 이유
현대 엔진은
- 멀티쓰레드
- 대규모 데이터
- 캐시 효율
- GPU 업로드
문제를 모두 고려해야 합니다.
즉, 단순 new/delete만으로는 한계가 생기기 쉽습니다.
그래서 게임 엔진들은 점점
전용 allocator / 메모리 arena / frame memory / custom pool 구조를 적극적으로 사용하게 됩니다.
핵심 정리
- allocator는 메모리 할당 정책을 담당하는 객체다
- STL 컨테이너는 메모리 관리를 allocator에 위임한다
- 기본 allocator는 사실상 new/delete 기반이다
- 실무에서는 메모리 단편화와 lock 비용 문제가 중요해진다
- Pool / Linear / Stack Allocator 같은 구조가 자주 사용된다
- 현대 게임 엔진은 독자적인 메모리 시스템을 적극적으로 사용한다
마무리
allocator는 처음 보면, 다소 추상적이고 어렵게 느껴질 수 있습니다.
왜냐하면 작은 프로젝트에서는 기본 allocator만 사용해도 큰 문제가 없기 때문입니다.
하지만 프로젝트 규모가 커질수록 메모리 할당 자체가 성능 문제와 직접 연결되기 시작합니다.
그리고 이 시점부터 allocator는 단순 문법이 아니라, “엔진 성능 구조의 일부”가 됩니다.
개인적으로 allocator를 공부할 때 중요한 건 단순 인터페이스 암기보다,
- 메모리 사용 패턴
- 캐시 효율
- 할당 비용 구조
를 함께 이해하는 것이라고 생각합니다.