🎯1주차 Unit 5.4 — GC 종류와 선택 기준

Psj·2026년 5월 8일

F-lab

목록 보기
40/240

🎯 Unit 5.4 — GC 종류와 선택 기준 ★★★

F-lab Java 1주차 / Phase 5 / Unit 5.4 본격 학습 자료 — Phase 5 마무리!
9-섹션 마스터 프롬프트 형식으로 깊이 파헤친다.

선수 지식: Unit 5.3 (GC 알고리즘 4가지)
다음 Phase: Phase 6 — 데이터 다루기 (문자열·컬렉션)

이 Unit의 의미: 운영 환경에서 GC 를 선택하는 실용 가이드.
Serial, Parallel, CMS, G1, ZGC, Shenandoah 의 정확한 차이.
ILIC 운영에 어떤 GC 가 맞는지 결정 가능.


🌍 1. 세상 속 비유

GC 종류 = "다양한 청소 서비스"

큰 사무실의 청소 서비스 옵션:

1. 1인 청소부 (Serial GC)

  • 한 명이 모든 곳 청소
  • 청소 동안 모든 직원 대기 (긴 STW)
  • 장점: 비용 저렴
  • 단점: 느림
  • 적합: 작은 사무실 (1인 회사)

2. 청소 팀 (Parallel GC)

  • 여러 명이 같이 청소
  • 모든 직원 대기는 동일하지만 더 빨리 끝남
  • 장점: 처리량 ↑
  • 단점: 여전히 STW
  • 적합: 중간 규모, 처리량 우선

3. 동시 청소 + 작은 STW (CMS)

  • 청소부가 직원과 함께 일하면서 청소
  • 정말 필요할 때만 잠깐 멈춤
  • 장점: 응답성 ↑
  • 단점: 단편화, 복잡
  • 적합: 응답 시간 중요 (deprecated)

4. 구역별 청소 (G1)

  • 사무실을 여러 구역으로 나눔
  • 가장 더러운 구역부터 청소
  • 장점: 큰 사무실에서도 효과적
  • 단점: 구조 복잡
  • 적합: 일반 서버 (현재 기본)

5. 거의 멈춤 없는 청소 (ZGC)

  • 매우 빠른 부분 청소
  • 직원이 거의 인지 못 함
  • 장점: 매우 짧은 STW (~ms)
  • 단점: 메모리 약간 더 사용
  • 적합: 저지연 시스템

→ 이게 자바 GC 의 6가지 종류.


핵심 한 문장

"GC 는 알고리즘이 같아도 구현 (멀티 스레드, Concurrent, Region 기반) 에 따라 다양한 종류로 진화했다."

각 GC 의 trade-off:

  • 처리량 vs 응답성
  • 단순함 vs 복잡함
  • Heap 크기

비유 정리:

비유GC 종류적합
1인 청소부Serial작은 환경
청소 팀Parallel처리량 우선
동시 청소CMS응답성 (deprecated)
구역별 청소G1일반 (기본)
멈춤 없는 청소ZGC저지연

🔥 2. 탄생 배경

"한 가지 GC 로 모든 환경?" — 불가능

GC 의 핵심 trade-off:

[처리량 (Throughput)]  ←——————→  [응답성 (Latency)]
   배치, 대량 처리                   사용자 응답
   STW 길어도 OK                    STW 짧아야

한 가지 GC 로는 모든 환경 만족 불가:

  • 배치: 처리량 우선
  • 웹 서버: 응답성 우선
  • 메모리 제한: 효율 우선

→ 다양한 GC 가 등장.


Java 버전별 기본 GC ⭐

자바 버전마다 기본 GC 가 진화:

자바 버전기본 GC
1.0~1.4Serial
1.5~1.7Parallel (Heap 큰 경우)
8Parallel ⭐
9~G1 ⭐
11~G1 (ZGC 실험적)
15~G1 (ZGC 정식)
17~G1 (Generational ZGC 실험적)
21~G1 (Generational ZGC 정식)

박승제님의 Java 17 환경:

  • ILIC 가 Java 17 사용 시 → G1 GC 가 기본

GC 진화의 동기

1. Heap 크기 증가

  • 1990년대: 수십~수백 MB
  • 2000년대: GB 단위
  • 2010년대: 수십 GB
  • 2020년대: 수백 GB

→ 큰 Heap 에서도 효율적인 GC 필요.

2. 응답성 요구 증가

  • 옛날: 배치 처리 → STW 1초 OK
  • 지금: 웹 API → STW 100ms 도 부담
  • → 저지연 GC 필요.

3. 멀티 코어 시대

  • 옛날: 단일 CPU → Serial 만으로 OK
  • 지금: 수십 코어 → 병렬 GC 활용

각 GC 의 등장 이유

Serial GC (1995, Java 1.0)

  • 자바의 첫 GC
  • 단일 스레드
  • 작은 환경에 적합

Parallel GC (Java 1.4)

  • 멀티 코어 활용
  • 처리량 우선
  • Java 8 의 기본

CMS (Java 1.4)

  • Concurrent Mark-Sweep
  • STW 줄이기 위한 첫 시도
  • 단편화 + 복잡성으로 Java 9 에서 deprecated, Java 14 에서 제거

G1 (Java 7+, 9 default) ⭐

  • Garbage First
  • Region 기반
  • 큰 Heap 효율적
  • 현재 기본 GC

ZGC (Java 11+) ⭐

  • Z Garbage Collector
  • ms 단위 STW
  • 큰 Heap (수 TB) 도 가능
  • 저지연 우선

Shenandoah (Java 12+)

  • Red Hat 개발
  • ZGC 유사 (저지연)
  • OpenJDK 11+ 백포트

핵심 통찰

"GC 종류 선택은 '내 환경의 우선순위' 의 답이다."

처리량인가 응답성인가? 작은 Heap 인가 큰 Heap 인가? 단일 CPU 인가 멀티 CPU 인가?

모든 환경에 맞는 단일 GC 는 없다. 상황에 맞게 선택. 시니어 개발자라면 각 GC 의 특성을 알고 환경에 맞는 선택 가능해야.


💣 3. 없으면 생기는 문제

GC 종류를 모르면 운영 환경에서 다양한 문제 발생.

시나리오 1: "기본 GC 만 사용"

java -jar ilic.jar  # 기본 GC (Java 17 → G1)

알고 사용: 의도적 G1 선택 ✅
모르고 사용: 어떤 GC 인지도 모름 ❌

문제 시:

  • "GC 가 느려요" 라고만
  • 어떤 GC 인지 모름 → 분석 불가

시나리오 2: 잘못된 GC 선택

Case A: 작은 환경에 G1

java -XX:+UseG1GC -Xmx512m -jar small.jar

문제:

  • G1 의 Region 오버헤드
  • 작은 Heap 에는 비효율
  • Serial 또는 Parallel 이 더 적합

Case B: 응답성 중요한데 Parallel

java -XX:+UseParallelGC -jar webapp.jar

문제:

  • Full GC 시 5초 STW
  • 사용자 응답 5초 끊김
  • 매출 손실
  • → G1 또는 ZGC 가 적합

시나리오 3: ILIC 운영 환경

ILIC 서비스:
- Heap: 4GB
- API 응답 시간 SLA: P99 < 500ms
- 사용 GC: 모름 (기본)

문제:
가끔 응답 시간 2초 → SLA 위반

GC 종류 모르면:

  • "DB 가 느린가?" 추측

GC 종류 알면:

  • GC 로그 분석
  • "G1 의 Mixed GC 가 800ms"
  • → 튜닝 또는 ZGC 전환

시나리오 4: 면접 깊이 질문

"ILIC 에서 어떤 GC 사용했고, 왜 그 GC 인가요?"

답 못함:

  • "기본 GC 사용했어요"
  • → 시니어 자격 의심

잘 답함:

  • "Java 17 기본인 G1 사용. 4GB Heap 에 적합하고, MaxGCPauseMillis=200 으로 응답성 확보"
  • "만약 응답 시간이 더 중요해지면 ZGC 도 고려"
  • → 시니어 인식

시나리오 5: GC 튜닝 시 선택지 모름

문제: Full GC 빈번, STW 김

GC 종류 모르면:

  • 어떻게 해결할지 모름

GC 종류 알면:

  • 옵션 1: Heap 늘리기 (G1 유지)
  • 옵션 2: G1 튜닝 (MaxGCPauseMillis)
  • 옵션 3: ZGC 전환 (저지연)
  • 옵션 4: Parallel 전환 (배치라면)
  • → 상황별 선택

시나리오 6: Java 버전 업그레이드

Java 8 → Java 17 마이그레이션
기본 GC 변경: Parallel → G1

GC 종류 모르면:

  • 동작 차이 모름
  • 성능 변화에 당황

GC 종류 알면:

  • "Parallel 의 Throughput 우선 → G1 의 균형"
  • "기존 옵션 호환 확인"
  • → 계획적 마이그레이션

GC 종류 이해의 중요성

시나리오GC 종류 모르면GC 종류 알면
기본 GC 사용무지식의도 명확
GC 선택잘못 선택상황에 맞는 선택
운영 분석막막함정확한 진단
면접탈락시니어 인식
튜닝옵션 모름다양한 선택지
버전 업그레이드당황계획적

→ GC 종류 이해는 시니어 자바 개발자의 필수.


✅ 4. 해결책 — 6가지 GC 정확히

1. Serial GC ⭐

핵심 특징

  • 단일 스레드 GC
  • Stop-the-World
  • 가장 단순한 GC

알고리즘

  • Young: Copying GC
  • Old: Mark-Sweep-Compact

장점

  • 단순, 안정
  • 메모리 적게 사용
  • 단일 CPU에 효율

단점

  • 멀티 코어 활용 X
  • STW 김

적합

  • 작은 Heap (~수 MB)
  • 단일 CPU 환경
  • 클라이언트 애플리케이션
  • 컨테이너 (제한된 자원)

JVM 옵션

java -XX:+UseSerialGC -jar app.jar

2. Parallel GC ⭐

핵심 특징

  • 여러 스레드 GC (멀티 코어 활용)
  • Stop-the-World (단축됨)
  • Throughput Collector 라고도 부름

알고리즘

  • Young: Parallel Copying
  • Old: Parallel Mark-Sweep-Compact

장점

  • 처리량 ↑
  • 멀티 코어 활용
  • 단순한 동작

단점

  • 여전히 STW (응답성 X)
  • Full GC 시 길어짐

적합

  • 처리량 우선 (배치, 데이터 처리)
  • Java 8 의 기본
  • 응답 시간 < 처리량

JVM 옵션

java -XX:+UseParallelGC -jar app.jar

# 처리량 목표
-XX:GCTimeRatio=99           # 1% 이내 GC
-XX:MaxGCPauseMillis=200     # 목표 STW

3. CMS (Concurrent Mark Sweep) — Deprecated

핵심 특징

  • Concurrent GC (Application Thread 와 동시 실행)
  • STW 최소화 시도
  • Java 9 에서 deprecated, Java 14 에서 제거

알고리즘

  • Young: Parallel Copying
  • Old: Concurrent Mark-Sweep (압축 X)

장점

  • 짧은 STW
  • 응답성 ↑

단점

  • 단편화 발생 (Compact 없음)
  • CPU 사용량 ↑
  • Promotion Failure 가능
  • 복잡한 구현
  • → Java 14 에서 완전 제거

적합

  • 응답성 중요한 시스템 (deprecated 이전)
  • → 현재는 G1 또는 ZGC 사용

JVM 옵션 (Java 14 이전만)

java -XX:+UseConcMarkSweepGC -jar app.jar  # ❌ Java 14+에서 사용 불가

4. G1 GC (Garbage First) ⭐⭐ (현재 기본)

핵심 특징

  • Region 기반
  • Heap 을 작은 Region 들 (1~32MB) 로 분할
  • 각 Region 이 동적 역할 (Eden/Survivor/Old)
  • Garbage 가 많은 Region 부터 청소

알고리즘

  • Concurrent Marking
  • Parallel Copying
  • Mixed GC (Young + 일부 Old)

Region 구조

[Heap]
├── Region 0 (Eden)
├── Region 1 (Survivor)
├── Region 2 (Old)
├── Region 3 (Humongous)
├── Region 4 (Free)
└── ... 수백~수천 Region

장점

  • 큰 Heap 효율적
  • 단편화 적음 (Region 단위 압축)
  • 목표 STW 설정 가능 (MaxGCPauseMillis)
  • 균형 잡힌 GC

단점

  • 매우 작은 Heap 에서는 오버헤드
  • 메모리 약간 더 사용 (Region 메타데이터)

적합 ⭐

  • 일반 백엔드 서버 (가장 많은 케이스)
  • Heap 4GB ~ 수십 GB
  • Java 9+ 의 기본

JVM 옵션

java -XX:+UseG1GC -jar app.jar

# 주요 튜닝 옵션
-XX:MaxGCPauseMillis=200      # 목표 STW (기본 200ms)
-XX:G1HeapRegionSize=4m       # Region 크기 (자동 계산도 OK)
-XX:InitiatingHeapOccupancyPercent=45  # Mixed GC 트리거
-XX:ConcGCThreads=2           # Concurrent 스레드 수

5. ZGC (Z Garbage Collector) ⭐ (저지연)

핵심 특징

  • 매우 짧은 STW (~10ms 이하)
  • 거의 모든 작업이 Concurrent
  • 큰 Heap (수 TB) 도 가능
  • Java 15+ 정식

알고리즘

  • Colored Pointers (포인터에 메타데이터)
  • Load Barrier (참조 시 자동 작업)
  • Region 기반 (G1 보다 큰 Region)

장점 ⭐

  • STW < 10ms (Heap 크기 무관)
  • 큰 Heap 에 효율
  • 저지연 시스템 적합

단점

  • CPU 사용량 ↑
  • 메모리 사용량 ↑ (Colored Pointer)
  • 처리량 약간 ↓
  • 작은 Heap 에서는 G1 보다 비효율

적합 ⭐

  • 응답성 매우 중요 (실시간 시스템)
  • 큰 Heap (32GB+)
  • Java 15+ 환경

JVM 옵션

java -XX:+UseZGC -jar app.jar

# Generational ZGC (Java 21+)
java -XX:+UseZGC -XX:+ZGenerational -jar app.jar

6. Shenandoah (Red Hat)

핵심 특징

  • ZGC 유사 (저지연)
  • OpenJDK 11+ 백포트 (ZGC 와 차별점)
  • Red Hat 개발

장점

  • 저지연
  • OpenJDK 8/11 에서도 사용 가능
  • ZGC 와 유사한 성능

단점

  • ZGC 와 비슷한 단점

JVM 옵션

java -XX:+UseShenandoahGC -jar app.jar

6가지 비교 표 ⭐⭐ (면접 답변 핵심)

GC등장알고리즘STW처리량적합 환경
Serial1.0단일 스레드김보통작은 환경, 단일 CPU
Parallel1.4멀티 스레드김 (단축)높음처리량 우선, 배치
CMS1.4Concurrent짧음보통(deprecated)
G17+, 9 defaultRegion보통높음일반 백엔드 ⭐
ZGC11+Colored Pointer매우 짧음보통저지연, 큰 Heap
Shenandoah12+Red Hat매우 짧음보통저지연, OpenJDK

선택 가이드 ⭐⭐⭐ (실용)

결정 트리

Heap 크기?
├── ~100MB
│   └── Serial (단순, 효율)
│
├── 100MB ~ 4GB
│   ├── 처리량 우선?
│   │   └── Parallel
│   └── 응답성 우선?
│       └── G1
│
├── 4GB ~ 32GB
│   └── G1 (기본 권장) ⭐
│
└── 32GB+
    └── 응답성 매우 중요?
        ├── YES: ZGC
        └── NO:  G1

ILIC 환경별 권장

Case 1: 일반 API 서버 (Heap 2~4GB):

java -XX:+UseG1GC \
     -Xms2g -Xmx2g \
     -XX:MaxGCPauseMillis=200 \
     -jar ilic.jar

Case 2: 배치 처리 (대용량 데이터):

java -XX:+UseParallelGC \
     -Xms8g -Xmx8g \
     -jar batch.jar

Case 3: 실시간 시스템 (저지연):

java -XX:+UseZGC \
     -Xms16g -Xmx16g \
     -jar realtime.jar

🏗️ 5. 내부 동작 원리

Serial GC 의 동작

1. STW 시작 (모든 Application Thread 정지)
2. 단일 GC 스레드가 Mark + Sweep + Compact
3. STW 종료

→ 단순. 작은 Heap 에서는 오히려 빠를 수 있음.


Parallel GC 의 동작

1. STW 시작
2. 여러 GC 스레드가 병렬로 Mark + Sweep + Compact
3. STW 종료

스레드 수:

기본: CPU 코어 수
조정: -XX:ParallelGCThreads=N

→ STW 시간 = Serial 의 1/N (N = 스레드 수).


G1 GC 의 자세한 동작 ⭐

Region 구조

[G1 Heap]
├── Eden Region (여러 개)
├── Survivor Region (여러 개)
├── Old Region (여러 개)
├── Humongous Region (큰 객체)
└── Free Region (사용 가능)

G1 의 GC 종류

1. Young GC (Minor GC):

  • Eden + Survivor 의 Live 객체를 다른 Region 으로 복사
  • 단편화 자동 해소

2. Concurrent Marking:

  • Application Thread 와 동시 실행
  • Old Region 의 Live 객체 마킹

3. Mixed GC:

  • Young Region + 일부 Old Region 청소
  • "Garbage 많은 Old Region" 부터 (이름 의미: Garbage First)

4. Full GC (피해야 할):

  • 모든 Region 청소
  • STW 길음

Garbage First 의 의미

[Heap]
├── Region A: 80% Garbage (target)
├── Region B: 30% Garbage
├── Region C: 90% Garbage (target)
├── Region D: 10% Garbage
└── ...

GC 우선 청소: Region A, C

→ 가장 효율적인 Region 부터 청소.

목표 STW 달성

-XX:MaxGCPauseMillis=200:

  • 목표 STW 200ms
  • G1 이 자동으로:
    • 청소할 Region 수 결정
    • 200ms 안에 끝낼 만큼만 처리

ZGC 의 자세한 동작 ⭐

Colored Pointers

일반 64-bit 포인터:
[       64 bits (주소)       ]

ZGC 의 Colored Pointer:
[ 4 bits (color) ][ 60 bits (주소) ]

Color 의미:
- Marked0: Live (이번 사이클)
- Marked1: Live (다음 사이클)
- Remapped: 재배치됨
- Finalizable: finalize 대상

→ 포인터 자체에 GC 정보 저장.

Load Barrier

// 사용자 코드
Customer c = customers.get(0);  // 객체 참조 시

// JVM 내부 (Load Barrier)
- 포인터 색상 확인
- 필요 시 동시 마킹
- 필요 시 재배치 처리

→ 매 참조 시 약간의 작업, 그러나 STW 거의 없음.

ZGC 단계

1. Pause Mark Start (~1ms)
   - GC Root 마킹

2. Concurrent Marking
   - Application 과 동시 실행
   - Heap 전체 마킹

3. Pause Mark End (~1ms)
   - 마킹 마무리

4. Concurrent Relocation
   - Live 객체 재배치
   - Application 과 동시

→ STW 는 수 ms 만. Heap 크기 무관.


G1 vs ZGC 비교

G1ZGC
Region 크기1~32MB~수 GB
STW~200ms (목표)~10ms 이하
Heap4GB~수백 GB수 TB 가능
CPU 사용보통약간 ↑
메모리 사용보통약간 ↑
처리량높음약간 ↓
적합일반 서버저지연

Concurrent GC 의 trade-off

Concurrent GC 의 장점:

  • STW 짧음
  • 응답성 ↑

Concurrent GC 의 단점:

  • CPU 사용량 ↑
  • 메모리 사용량 ↑
  • 복잡한 알고리즘
  • 처리량 약간 ↓

→ 응답성을 위해 다른 자원 더 사용.


💻 6. 실전 코드 예시

예시 1: 현재 GC 확인

# 방법 1: PrintCommandLineFlags
java -XX:+PrintCommandLineFlags -version

# 출력 예시:
# -XX:+UseG1GC ← 사용 중인 GC

# 방법 2: GC 로그
java -Xlog:gc -jar myapp.jar
# 출력에서 GC 이름 확인

예시 2: ILIC 환경에 맞는 GC 설정

# 일반 백엔드 (Heap 2~4GB)
java -XX:+UseG1GC \
     -Xms2g -Xmx2g \
     -XX:MaxGCPauseMillis=200 \
     -XX:+HeapDumpOnOutOfMemoryError \
     -XX:HeapDumpPath=/var/log/heap-dump.hprof \
     -Xlog:gc*:file=/var/log/gc.log:time,uptime,level,tags \
     -jar ilic.jar

예시 3: GC 종류별 성능 측정

public class GCBenchmark {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        
        List<byte[]> survivors = new ArrayList<>();
        for (int i = 0; i < 1_000_000; i++) {
            byte[] data = new byte[1024];  // 1KB
            
            if (i % 1000 == 0) {
                survivors.add(data);
            }
        }
        
        long elapsed = System.currentTimeMillis() - start;
        System.out.println("Total time: " + elapsed + "ms");
    }
}

다른 GC 로 실행:

# Serial
java -XX:+UseSerialGC GCBenchmark
# 출력: ~3000ms (단일 스레드)

# Parallel
java -XX:+UseParallelGC GCBenchmark
# 출력: ~1500ms (병렬, 처리량 ↑)

# G1
java -XX:+UseG1GC GCBenchmark
# 출력: ~2000ms (균형)

# ZGC
java -XX:+UseZGC GCBenchmark
# 출력: ~2200ms (응답성, 처리량 약간 ↓)

→ GC 선택이 성능에 직결.


예시 4: 이상적인 GC 옵션 (ILIC 운영)

# 운영 환경 — 검증된 설정
java \
    # GC 알고리즘
    -XX:+UseG1GC \
    
    # Heap 크기 (고정 권장)
    -Xms4g -Xmx4g \
    
    # 목표 STW
    -XX:MaxGCPauseMillis=200 \
    
    # OOM 시 자동 덤프
    -XX:+HeapDumpOnOutOfMemoryError \
    -XX:HeapDumpPath=/var/log/heap-dump-%t.hprof \
    
    # GC 로그
    -Xlog:gc*:file=/var/log/gc.log:time,uptime,level,tags:filecount=10,filesize=100M \
    
    # 추가 모니터링
    -XX:+PrintTenuringDistribution \
    -XX:+UnlockExperimentalVMOptions \
    
    -jar ilic.jar

예시 5: Java 17 기본 GC 활용

박승제님이 Java 17 사용 시:

  • 기본: G1 GC
  • 권장 옵션:
java \
    -Xms2g -Xmx2g \
    -XX:MaxGCPauseMillis=200 \
    -Xlog:gc*:file=/var/log/gc.log \
    -jar ilic.jar

→ 기본 G1 사용. 명시적 UseG1GC 옵션 불필요.


예시 6: ZGC 전환 (Java 17+)

저지연 필요 시:

# Java 17+ 의 ZGC
java \
    -XX:+UseZGC \
    -Xms8g -Xmx8g \
    -Xlog:gc*:file=/var/log/gc.log \
    -jar ilic.jar

Java 21 이상:

# Generational ZGC (더 효율적)
java \
    -XX:+UseZGC \
    -XX:+ZGenerational \
    -Xms8g -Xmx8g \
    -jar ilic.jar

예시 7: GC 모니터링 도구

# 1. JConsole
jconsole <pid>

# 2. VisualVM
visualvm

# 3. JFR (Java Flight Recorder)
java -XX:StartFlightRecording=duration=60s,filename=recording.jfr -jar app.jar

# 4. JMC (Java Mission Control) 로 분석
jmc

# 5. GC 로그 분석 도구
# - GCViewer (오픈소스)
# - gceasy.io (웹 서비스)

⚠️ 7. 주의사항 & 흔한 실수

실수 1: 기본 GC 가 항상 옳다고 생각

java -jar myapp.jar  # 무조건 기본

문제:

  • Java 8 의 Parallel = 처리량 우선
  • 웹 API 에는 응답성 부족 → 사용자 영향

권장: 상황에 맞는 GC 명시적 선택.


실수 2: CMS 사용 시도 (Java 14+)

java -XX:+UseConcMarkSweepGC -jar app.jar  # ❌ Java 14+에서 제거

대체:

  • G1 (저지연 OK)
  • ZGC (매우 저지연)

실수 3: 무조건 ZGC

"저지연 = ZGC = 좋다"

진실:

  • 작은 Heap 에서는 오버헤드
  • CPU/메모리 사용 ↑
  • 처리량 약간 ↓

원칙: Heap 크기 + 우선순위 에 맞게.


실수 4: -Xmx 만 설정, 다른 옵션 무시

java -Xmx8g -jar myapp.jar

누락:

  • -Xms (초기 Heap) — 초기 작으면 동적 확장 비용
  • -Xlog:gc (로그) — 분석 불가
  • -XX:+HeapDumpOnOutOfMemoryError — 사고 시 덤프 X

권장 최소 옵션:

java -Xms4g -Xmx4g \
     -Xlog:gc*:file=/var/log/gc.log \
     -XX:+HeapDumpOnOutOfMemoryError \
     -XX:HeapDumpPath=/var/log/ \
     -jar myapp.jar

실수 5: -Xms ≠ -Xmx

java -Xms512m -Xmx4g -jar myapp.jar

문제:

  • 초기 512MB → 동적 확장 시 비용
  • GC 가 작은 Heap 에서 자주 발생
  • → 점진적 성능 저하

권장: Xms == Xmx (동일 값)

java -Xms4g -Xmx4g -jar myapp.jar

실수 6: GC 로그 무설정

운영 환경:

  • GC 로그 X
  • 사고 발생 → 분석 불가

해결: 항상 GC 로그 활성화.


실수 7: G1 의 Region 크기 잘못 설정

java -XX:+UseG1GC -XX:G1HeapRegionSize=64m -Xmx2g -jar app.jar

문제:

  • 2GB Heap 에 64MB Region → 32개만
  • G1 의 효율 X

권장: G1 자동 계산 사용 (옵션 생략).


🔗 8. 연관 개념 맵

Phase 5 (GC) 완성 ⭐

[Unit 5.1: GC 기본 + 약한 세대 가설] ✓
        ↓
[Unit 5.2: Heap 의 세대 구조] ✓
        ↓
[Unit 5.3: GC 알고리즘 4가지] ✓
        ↓
[Unit 5.4: GC 종류와 선택 기준] ← 지금 여기 ★
        ↓
[Phase 5 완료!] 🎉

→ Phase 5 완료. 다음은 Phase 6 데이터 다루기.


Phase 4 와의 통합

학습GC 선택 관점
Unit 4.1 (Heap 영역)GC 의 무대
Unit 4.2 (Pass by Value)객체 참조 → GC 영향
Unit 5.1 (약한 세대)Generational 의 기반
Unit 5.2 (세대 구조)G1 의 Region 이해
Unit 5.3 (알고리즘)GC 종류의 토대

미래 주차와의 연결

4주차 (동시성):

  • 멀티스레드 + GC
  • Concurrent GC (G1, ZGC) 가 Application Thread 와 동시

5주차 (Spring DI):

  • Bean Singleton → Old Generation
  • GC 영향 적음

11-12주차 (JPA):

  • 영속성 컨텍스트 → 트랜잭션 단위
  • 트랜잭션 종료 시 GC

13-14주차 (DB/Cache):

  • 큰 캐시 = Heap 압박
  • WeakHashMap, Caffeine 활용

17주차 (MSA):

  • 각 서비스 별도 JVM
  • 서비스마다 GC 선택

19주차 (테스트):

  • 테스트 환경 GC (보통 Serial 도 OK)

운영 GC 선택 가이드 ⭐ (실용)

새 ILIC 서비스 시작
        ↓
Java 버전?
  ├── 8: Parallel 기본 (변경 권장 — G1)
  └── 11+: G1 기본 (대부분 그대로)
        ↓
응답 시간 SLA?
  ├── 1초+ OK: G1 (기본)
  ├── 200ms 목표: G1 + MaxGCPauseMillis=200
  └── 100ms 미만: ZGC 고려
        ↓
Heap 크기?
  ├── ~4GB: G1
  ├── 4~32GB: G1 (튜닝 가능)
  └── 32GB+: ZGC 강력 권장
        ↓
Java 21+?
  └── ZGC 사용 시 +ZGenerational

면접 단골 질문 매핑

질문이 Unit에서의 답
"GC 종류?"Serial, Parallel, CMS (deprecated), G1, ZGC, Shenandoah
"Java 8/9 기본 GC 변화?"Parallel → G1
"G1 vs ZGC?"G1 = 균형, ZGC = 저지연
"ILIC 에서 어떤 GC?""G1 사용했고, MaxGCPauseMillis=200"
"CMS 가 deprecated 된 이유?"단편화 + 복잡성

📝 9. 핵심 요약 — 3줄 정리

1️⃣ 자바 GC 는 6가지 — Serial, Parallel, CMS (deprecated), G1, ZGC, Shenandoah.

Serial = 단일 스레드 (작은 환경), Parallel = 멀티 스레드 (Java 8 기본, 처리량), CMS = Concurrent (Java 14에서 제거), G1 = Region 기반 (Java 9+ 기본, 일반 백엔드), ZGC = Colored Pointer (저지연, 큰 Heap), Shenandoah = Red Hat 의 ZGC 유사품. 모두 Generational + 추가 최적화.

2️⃣ G1 은 일반 백엔드의 표준, ZGC 는 저지연의 답.

G1 의 Region 기반 + Garbage First 전략으로 목표 STW 설정 (MaxGCPauseMillis=200) 가능. 큰 Heap 에서도 효율적. ZGC 의 Colored Pointer + Load Barrier 로 STW 10ms 이하 (Heap 크기 무관). 응답성 vs 처리량/메모리의 trade-off — 박승제님의 Java 17 + ILIC 4GB Heap 환경이라면 G1 이 정답.

3️⃣ GC 선택은 Heap 크기 + 우선순위의 답이다.

~100MB → Serial, ~4GB → G1 (또는 처리량 우선이면 Parallel), 4~32GB → G1, 32GB+ 또는 저지연 → ZGC. 운영 시 항상 GC 로그 활성화 + HeapDumpOnOutOfMemoryError + Xms=Xmx 권장. Java 14+ 에서 CMS 사용 시도는 X. 이런 명확한 기준으로 GC 선택할 수 있어야 시니어 자바 개발자.


🎓 학습 자기 점검

기본 이해

  • 6가지 GC 종류를 나열할 수 있다
  • 각 GC 의 특징을 설명할 수 있다
  • Java 버전별 기본 GC 의 변화를 안다
  • CMS 가 deprecated 된 이유를 안다

실전 적용

  • ILIC 환경에 맞는 GC 를 선택할 수 있다
  • JVM 옵션으로 GC 를 명시적 설정할 수 있다
  • GC 로그에서 사용 GC 를 확인할 수 있다
  • Heap 크기에 맞는 GC 를 권장할 수 있다

면접 대비 (5분 답변)

  • "GC 종류?" 답변 가능
  • "G1 vs ZGC?" 답변 가능
  • "ILIC 에서 어떤 GC?" 답변 가능
  • "Java 9 기본 GC 변경 이유?" 답변 가능

자기 점검 질문 답변

Q1: G1 GC 가 큰 Heap 에 적합한 이유는?

한 줄 답: Region 기반 + Garbage First 전략 + 목표 STW 설정 가능 으로 큰 Heap 에서도 STW 짧게 유지.

상세 설명:

전통 Generational GC 의 문제

기존 (Parallel, Serial) GC:

[Heap 16GB]
├── Young (5GB)
└── Old (11GB)

Old GC (Major GC) 시:

  • 11GB 전체 마킹 + 압축
  • 단일 작업으로 처리
  • → STW 매우 김 (수 초)

큰 Heap = 긴 STW ⚠️.


G1 의 해결 — Region 분할

[Heap 16GB]
├── Region 0 (4MB)
├── Region 1 (4MB)
├── Region 2 (4MB)
├── ... 4000개 Region
└── Region 3999

Region 의 의미:

  • Heap 을 4MB Region 들로 분할
  • 각 Region 이 동적 역할 (Eden/Survivor/Old/Humongous)
  • 한 번에 일부 Region 만 처리

Garbage First 전략

GC 시 결정:
"어떤 Region 부터 청소할까?"

각 Region 의 Garbage 비율 분석:
- Region A: 80% Garbage
- Region B: 20% Garbage
- Region C: 90% Garbage
- Region D: 10% Garbage

선택: 효율 높은 순서
- Region C (90%)
- Region A (80%)
- Region B (20%) — 효율 낮음 → 스킵

효과:

  • Garbage 가 많은 Region = 청소 비용 대비 회수량 많음
  • → 시간 대비 효율 ↑

목표 STW 설정

-XX:MaxGCPauseMillis=200   # 목표 STW 200ms

G1 의 동작:
1. 200ms 안에 끝낼 수 있는 Region 수 계산
2. 그만큼만 청소
3. 다음 GC 에서 나머지 처리

예시:

  • 200ms 안에 50 Region 청소 가능 추정
  • 효율 높은 50 Region 선정
  • 청소 후 STW 종료

→ 항상 200ms 안에 GC 완료.


Concurrent Marking

G1 은 일부 작업을 Application Thread 와 동시 실행:

1. Initial Mark (STW, 짧음)
2. Concurrent Mark (Application 과 동시) ⭐
3. Remark (STW, 짧음)
4. Cleanup (Concurrent + 짧은 STW)
5. Mixed GC (Young + 일부 Old)

효과:

  • 큰 Heap 의 마킹 작업이 Concurrent 로 처리
  • STW 는 짧은 단계만

큰 Heap 에서의 효과 비교

Heap 16GB, Old 가득:

Parallel GC:

Full GC:
- 16GB 전체 마킹 (수 초)
- 압축 (수 초)
- 총 STW: 5~10초 ⚠️

G1 GC:

Mixed GC:
- Concurrent Mark (수 초, 동시 실행)
- 200ms 만큼 Region 청소
- 부족하면 다음 GC 에서 더
- 총 STW: 200ms ✅

→ 큰 Heap 일수록 G1 의 효과 ↑.


Humongous Object 처리

G1 만의 특수 처리:

  • Region 의 절반 이상 객체 = Humongous
  • 별도 Humongous Region
  • 큰 객체 효율적 처리

결론

"G1 의 Region 기반 설계와 Garbage First 전략이 큰 Heap 에서 STW 를 짧게 유지.
Concurrent Marking 으로 Application 과 동시 작업 + 목표 STW 설정 으로 응답성 보장.
그래서 4GB 이상 큰 Heap 에 적합."


Q2: ZGC 와 G1 의 가장 큰 차이는?

한 줄 답: STW 길이의 차원이 다름 — G1 ~200ms vs ZGC ~10ms 이하.

상세 비교:

1. STW 시간

G1ZGC
목표 STW~200ms~10ms 이하
Heap 크기와 관계어느 정도 비례무관
큰 Heap 에서STW 길어짐STW 그대로

ZGC 의 마법 — Heap 이 100GB 든 1TB 든 STW 동일 (~10ms).


2. 동작 메커니즘

G1:

  • Region 기반
  • Concurrent Marking + 부분 GC
  • 일부 작업은 STW

ZGC:

  • Colored Pointers (포인터에 메타데이터)
  • Load Barrier (참조 시 자동 처리)
  • 거의 모든 작업이 Concurrent
  • STW 는 매우 짧은 단계만

3. 메모리/CPU 사용

G1ZGC
메모리 오버헤드보통약간 ↑
CPU 사용보통약간 ↑
처리량높음약간 ↓

→ ZGC 는 응답성을 위해 다른 자원 더 사용.


4. Heap 크기 권장

G1:

  • 4GB ~ 수십 GB
  • 매우 작은 Heap 에서는 오버헤드

ZGC:

  • 수 GB ~ 수 TB (16TB 까지 검증됨)
  • 큰 Heap 에서 진가 발휘
  • 작은 Heap (~수 GB) 에서는 G1 보다 비효율

5. 등장 시기와 성숙도

G1:

  • Java 7 도입 (2011)
  • Java 9 기본 (2017)
  • 매우 성숙, 기본 권장

ZGC:

  • Java 11 실험적 (2018)
  • Java 15 정식 (2020)
  • Java 21 Generational ZGC (2023)
  • 빠르게 성숙 중

6. 적합 환경

G1 의 영역:

  • 일반 백엔드 (대부분의 ILIC 같은 시스템)
  • 4GB ~ 32GB Heap
  • 응답성 중요하지만 ms 단위는 아님

ZGC 의 영역:

  • 저지연 시스템 (실시간 거래, 게임 서버)
  • 큰 Heap (32GB+)
  • ms 단위 응답성 필수

비유 — 청소 서비스

G1 = 정기 청소:

  • 사무실 잠깐 멈추고 (200ms)
  • 효율적으로 청소
  • 비용 합리적

ZGC = 24시간 청소부:

  • 거의 멈추지 않고
  • 항상 배경에서 작업
  • 인지 못 함 (10ms 정도만)
  • 비용 더 듦 (CPU/메모리)

ILIC 시나리오별 선택

Case 1: 일반 ILIC API (Heap 4GB):

G1 ⭐
- 충분한 응답성 (200ms)
- 단순한 운영
- Java 17 기본

Case 2: ILIC 실시간 알림 (Heap 8GB):

G1 가능, ZGC 도 OK
- G1 + MaxGCPauseMillis=100 시도
- 부족하면 ZGC 전환

Case 3: ILIC 대용량 데이터 분석 (Heap 64GB):

ZGC ⭐
- 큰 Heap 에서 STW 안정
- 처리량 약간 손실 OK

결론

"G1 = 일반 백엔드의 균형 (응답성 + 처리량),
ZGC = 저지연 시스템의 답 (응답성 최우선).
차이는 STW 의 차원 과 Heap 크기 의존성.
ILIC 같은 일반 백엔드는 G1 가 정답, 저지연 필요 시 ZGC 검토."


🎉 Phase 5 완료 축하!

학습한 4개 Unit

Unit주제핵심
5.1GC 기본 + 약한 세대 가설 ★★★Reachability, GC Root, STW
5.2Heap 의 세대 구조 ★★★Eden/Survivor/Old, Promotion
5.3GC 알고리즘 4가지RC, Mark-Sweep, MSC, Generational
5.4GC 종류와 선택 기준 ★★★Serial/Parallel/G1/ZGC

Phase 5 의 핵심 통찰

"GC 는 자바의 정수다. 세대 가설 → 세대 구조 → 알고리즘 → 종류 → 선택 — 모두 한 흐름."

약한 세대 가설이라는 통찰이 Heap 의 세대 구조를 만들고, 영역마다 다른 알고리즘을 적용하고, 각 환경에 맞는 GC 종류로 진화. Phase 4 + Phase 5 가 자바 메모리 관리의 완전한 이해.

Phase 6 미리보기 — 데이터 다루기

다음은 자바에서 데이터를 다루는 방법:

  • String, StringBuilder, StringBuffer — 문자열의 진실
  • String Constant Pool — 메모리 효율
  • ArrayList vs LinkedList — 컬렉션 선택
  • HashMap, TreeMap, LinkedHashMap — Map 의 종류

→ 메모리 모델 (Phase 4-5) 이해 위에서 자료구조를 다룸.


다음 학습으로

  • Phase 6 학습 준비 완료
  • String Constant Pool, 컬렉션 자료구조가 궁금하다
  • HashMap 의 내부 동작을 만날 준비 완료
profile
Software Developer

0개의 댓글