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

Psj·2026년 5월 8일

F-lab

목록 보기
40/239

🎯 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 BarrierSTW 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개의 댓글