Kim Seogyu
Backend

Go 가비지 컬렉터(GC) 이해와 튜닝 경험

Go GC 튜닝에서 실제로 효과가 큰 순서와 운영 체크포인트를 정리합니다.

Published 2025년 12월 30일2 min read231 words

Go 가비지 컬렉터(GC) 이해와 튜닝 경험

먼저 결론

GC 문제는 보통 파라미터 문제가 아니라 할당 패턴 문제입니다. 우선순위는 아래 순서가 맞습니다.

  1. 할당량 자체 줄이기
  2. GOMEMLIMIT 설정
  3. 마지막에 GOGC 미세 조정

관측 없이 튜닝하지 않기

GODEBUG=gctrace=1 ./myapp

함께 보는 지표:

  • go_gc_duration_seconds
  • go_memstats_heap_alloc_bytes
  • go_memstats_next_gc_bytes

핵심은 "GC가 자주 도는 이유"를 찾는 것입니다.

효과가 컸던 개선 4가지

1) 불필요한 할당 제거

  • append 대상 slice preallocate
  • 핫패스의 string <-> []byte 변환 최소화
  • 중간 객체 생성 줄이기

2) 객체 재사용

sync.Pool은 짧은 생명주기 버퍼에만 제한적으로 사용합니다. 영구 캐시 용도로 쓰면 오히려 디버깅 비용이 커집니다.

3) 메모리 한계 명시

GOMEMLIMIT=2GiB ./myapp

컨테이너 환경에서는 거의 필수입니다. OOM 직전 폭주 패턴을 완화합니다.

4) GOGC 조정

GOGC=100 # 기본
GOGC=50  # 메모리↓ CPU↑
GOGC=200 # 메모리↑ CPU↓

경험상 50~150 범위에서 트래픽 특성에 맞추는 경우가 많습니다.

실제 장애 패턴

  • p99 튐 + GC cycle 급증: 임시 객체 폭증
  • 배치 구간 OOM: batch size 과대 + 중간 결과 적재

해결은 공통적으로 "할당 구조 변경 + 한계값 설정"이었습니다.

하지 말아야 할 것

  • 요청 경로에서 runtime.GC() 호출
  • 근거 없는 극단값 설정 (GOGC=10, 1000)
  • 프로파일 없이 파라미터만 반복 변경

요약

Go GC 튜닝은 숫자 놀이가 아니라 메모리 설계 작업입니다. 할당 hot path를 먼저 고치고, 그 다음에 GOMEMLIMIT, 마지막으로 GOGC를 맞추는 순서가 가장 재현 가능했습니다.

Share

Related Articles

Comments

이 블로그는 제가 알고 있는 것들을 잊지 않기 위해 기록하는 공간입니다.
직접 작성한 글도 있고, AI의 도움을 받아 정리한 글도 있습니다.
정확하지 않은 내용이 있을 수 있으니 참고용으로 봐주세요.

© 2026 Seogyu Kim