힙 자료구조와 런타임 메모리 힙의 동작

우선순위 큐로서의 힙과 런타임 메모리 힙의 구조, 할당·회수 방식, 성능과 안정성 고려 사항을 다룬다.

2026-08-14 · 최초 발행 2024-04-29

Heap이 가리키는 영역

컴퓨터 과학에서 Heap은 우선순위에 따라 원소를 꺼내는 자료구조와 동적 메모리가 할당되는 런타임 영역을 뜻한다. 하나는 순서와 연산 비용의 문제이고, 다른 하나는 할당·회수와 메모리 안정성의 문제다. 성능, 지연시간, 안정성을 다룰 때는 어느 Heap을 말하는지 먼저 구분해야 한다.

우선순위 큐로 쓰는 힙

자료구조 힙은 완전이진트리를 배열에 담고, 각 노드가 자식보다 작거나 최소 힙 또는 크도록 최대 힙 순서 속성을 유지한다. 배열 인덱스로 부모와 자식을 찾으며, 삽입 뒤에는 상향 이동(sift-up), 삭제 뒤에는 하향 이동(sift-down)으로 위치를 바로잡는다.

삽입(push)·삭제(pop)·상단 조회(peek)의 평균·최악 시간복잡도는 O(log n)이며, heapify는 O(n) 시간이다. 안정 정렬은 아니므로 같은 키를 가진 원소의 상대적 순서는 보장되지 않는다.

동적 할당이 일어나는 런타임 힙

런타임 메모리 힙은 프로세스나 VM에서 동적 메모리를 배정하는 영역이다. C/C++의 malloc/new와 JVM/CLR 객체 할당이 여기에 해당한다.

메모리는 allocator/arena에 의한 수동 관리나 가비지 컬렉션으로 회수한다. GC 방식에는 mark-sweep, copying, generational, region-based가 있으며, 단편화(fragmentation)와 이를 줄이는 전략, TLAB/Arena 같은 할당 최적화도 함께 다뤄진다.

우선순위 연산에서 확인할 특성

완전이진트리의 형태 덕분에 이진 힙은 배열 기반 부모-자식 관계를 유지한다. 연속 배열은 메모리 지역성이 좋고 캐시 친화적인 접근을 가능하게 한다. 다만 comparator나 key extractor의 기준이 일관되지 않으면 순서가 깨질 수 있다.

d-ary 힙은 자식을 d개로 두어 높이를 낮추고 pop 비용을 개선할 수 있다. Fibonacci 힙은 decrease-key에 관한 이론적 최적화를 제공한다. 병렬 환경에서는 스케치드/멀티큐 힙과 skiplist 기반 우선순위 큐도 대안이 된다.

동일 키의 안정성이 필요하면 tie-breaker를 둔다. decrease-key를 지원하지 않는 구현에서는 “lazy insertion + stale 제거” 패턴을 사용할 수 있다.

할당 경로와 회수 방식이 만드는 차이

런타임 힙의 빠른 경로(fast path)는 스레드 로컬 버퍼(TLAB/arena)에서 bump-pointer 방식으로 할당한다. 버퍼가 부족한 느린 경로(slow path)에서는 글로벌 락, 페이지 확대, GC 트리거를 처리한다.

회수에는 Young/Old 세대별 GC, 마크-스윕/컴팩트, G1/Region 같은 지역 기반 방식이 적용된다. 실시간 또는 저지연 요구가 있을 때는 concurrent/parallel 컬렉터 선택이 중요하다.

이중 해제, 유효기간 초과(use-after-free), 단편화는 계속 감시해야 한다. OOM이 발생했을 때 덤프와 지표를 수집하고, 할당 실패를 처리할 경로도 확보한다.

push와 pop에서 속성을 되찾는 과정

pushtruefalsepopyesnotruefalse입력: push/pop 요청연산 유형배열 끝에 노드 삽입상향 이동 조건(부모 비교)부모와 교환 속성 만족, 완료비어 있음?에러 반환/예외 발생루트와 마지막 노드 교환마지막 노드 제거하향 이동 조건(자식 비교) 우선인 자식과 교환

pop 요청 시 힙이 비어 있으면 에러를 반환하거나 예외가 발생한다. comparator 불변성이 깨지면 무한 루프나 잘못된 순서가 생길 수 있다.

힙 구현별 선택 지점

유형 성능(삽입/삭제/heapify) 확장성(대규모 N/배치) 일관성(우선순위/타이브레이크) 안정성(메모리 지역성/예측 가능성) 운영 편의(구현/튜닝)
이진 힙(Binary) O(log n)/O(log n)/O(n) 대규모 N 안정적, batch heapify 유리 우선순위 보장, 안정 정렬 아님 연속 배열, 캐시 우수 구현 용이, 표준 라이브러리 풍부
d-ary 힙 O(log_d n)/O(d·log_d n)/O(n) d 조절로 캐시/분기 최적화 동일 자식 선택 비용 증가 파라미터 튜닝 필요
Fibonacci 힙 amortized O(1)/O(log n) 대규모 그래프 + decrease-key 최적 동일 포인터 구조, 캐시 불리 구현 복잡, 실전 이점 제한

멀티스레드 환경에서는 Binary Heap + sharding/multi-queue가 실무 친화적 선택이다.

우선순위와 메모리 수명에 적용하는 패턴

자료구조 힙은 지연 실행 타이머의 시간 기반 키, 태스크 우선순위 실행, 이벤트 시뮬레이터의 다음 이벤트 선택에 사용할 수 있다. Dijkstra/A* 최단경로에서는 최솟값을 꺼내며, decrease-key가 지원되지 않으면 (거리, 노드)를 재삽입하고 방문 여부를 확인하는 방식으로 대체한다.

스트리밍 Top-K와 Median에도 쓸 수 있다. 고정 크기 최대 힙 또는 최소 힙으로 상위 K를 유지하고, 중앙값은 두 힙으로 유지한다. Top-K에서는 힙 크기를 K로 초기화해 처음 K개를 넣고, 이후 원소 x가 힙 최소값보다 크면 pop→push로 교체한다. 종료 시 힙에는 Top-K가 남는다.

import heapq

def top_k(iterable, k):
    if k <= 0:
        return []
    it = iter(iterable)
    heap = []
    for _ in range(k):
        try:
            heap.append(next(it))
        except StopIteration:
            break
    heapq.heapify(heap)  # min-heap
    for x in it:
        if heap and x > heap[0]:
            heapq.heapreplace(heap, x)  # pop+push 원자적
    return sorted(heap, reverse=True)

# 예외 처리: 빈 자료에 pop 시 IndexError 발생 → 호출부에서 조건 검사 권장

메모리 힙에서는 JVM 서비스의 Young:Old 비율, TLAB 크기, 컬렉터(G1/ZGC) 선택이 p99 지연시간에 영향을 준다. 객체 재사용(pool)과 off-heap 캐시는 GC 부하를 완화하는 방법이다.

네이티브 서버(C/C++)에서는 jemalloc/tcmalloc를 통해 arena 기반 다중 스레드 확장성을 확보할 수 있다. 지역적 수명의 객체는 지역 풀(pool/arena)로 일괄 해제한다. 대규모 배치의 스트리밍 파이프라인에서는 chunked allocator로 단편화를 줄이고, ASan/Valgrind를 통한 메모리 누수 탐지와 OOM 퇴피 전략을 마련한다.

할당과 회수 흐름은 스레드가 n바이트를 요청하고 TLAB 여유 공간을 검사하는 데서 시작한다. 공간이 있으면 bump-pointer로 즉시 반환하며, 부족하면 새 버퍼를 요청한다. 잠금 또는 원자 연산 뒤에도 할당이 되지 않으면 GC를 트리거하거나 힙을 확장하고, 결국 실패하면 OOM 예외 또는 에러 코드를 반환한다.

비교량과 지연시간에서 기대할 수 있는 변화

n=10,000,000, k=100,000인 Top-K 예에서는 전체 정렬이 n log2 n ≈ 10^7 × 23.25 ≈ 232.5M 비교를 수행한다. 힙 기반 방식은 n log2 k ≈ 10^7 × 16.61 ≈ 166.1M 비교이며, 비교량은 약 28.6% 감소한다. 메모리 이동 감소에 따른 캐시 적중률 개선도 기대할 수 있다.

JVM에서 G1을 사용할 때 Young GC 병렬화는 STW를 줄일 수 있다. 객체 크기와 할당율을 최적화하면 p99 지연시간을 수 ms 수준으로 단축할 수 있으나, 이는 워크로드와 버전에 의존하므로 최신 정보 확인이 필요하다.

arena와 풀은 단편화와 락 경합을 줄이고 OOM 빈도를 낮추는 데 쓰인다. 우선순위 연산이 빈번한 서비스, 대규모 그래프·스트리밍 처리, 메모리에 민감한 시스템에서는 프로파일과 메트릭을 바탕으로 적용 여부를 판단할 수 있다.

우선순위 큐가비지 컬렉션메모리 관리자료구조