WAS 성능 튜닝 — JVM 힙·GC·스레드 풀·커넥션 풀 기준값 가이드
WAS 성능 튜닝의 4대 축인 JVM 힙, GC, 스레드 풀, 커넥션 풀의 기준값과 판단 근거를 정리했습니다. -Xms/-Xmx 설계, Parallel·G1·ZGC 선택, GC 로그 읽는 법, 풀 산정 공식과 부하 테스트 검증 절차까지 다룹니다.
성능 튜닝은 왜 네 축으로 보는가 — 요청의 생애주기와 병목 지점
요청 한 건의 생애주기를 따라가면 네 축이 곧 네 개의 병목 후보임을 알 수 있습니다. 요청이 WAS에 도착하면 ① 스레드 풀에서 처리 스레드를 할당받고, ② 로직 실행 중 힙 메모리에 객체를 만들며, ③ GC가 그 메모리를 회수하는 동안 애플리케이션이 잠시 멈추고, ④ DB 작업이 필요하면 커넥션 풀에서 연결을 빌립니다. 네 지점 중 하나라도 막히면 전체 응답 시간이 늘어집니다.
축별 대표 증상은 이렇습니다. 스레드 풀이 부족하면 요청이 큐에서 대기하고, 힙이 부족하면 GC가 잦아지며, GC 정책이 맞지 않으면 멈춤 시간(pause)이 길어지고, 커넥션 풀이 부족하면 DB 대기가 쌓입니다. 반대로 각 풀을 무작정 키우면 메모리 낭비와 컨텍스트 스위칭 비용, DB 과부하라는 반대편 문제가 생깁니다. 튜닝은 “크게”가 아니라 “맞게”가 목표입니다. 웹서버–WAS 계층 구조에서 어느 계층의 문제인지 먼저 가르는 방법은 WAS와 웹서버의 차이 글을 참고하십시오.

그림 1. 요청 한 건의 생애주기 — 네 지점이 곧 네 개의 병목 후보
파라미터를 만지기 전에 짚어야 할 전제가 하나 더 있습니다. 같은 워크로드라도 어떤 WAS 제품을 쓰느냐에 따라 손댈 수 있는 범위가 다릅니다. 상용 WAS는 벤더가 권장하는 프로파일 안에서 조정하는 쪽이고, Tomcat 계열은 설정 파일을 직접 열어 폭넓게 손댈 수 있는 대신 기준값을 스스로 잡아야 합니다. 제품별 성격 차이는 Tomcat vs 상용 WAS, 국내에서 실제로 쓰이는 제품 구도는 국내 WAS 시장 지형 글에 정리해 두었습니다.
개발자·운영자를 위한 APM(Application Performance Monitoring)이란?
엔드투엔드(End-to-End) 요청 흐름 시각화부터 병목 소스코드 파악까지, 시스템의 건강 상태를 24/7 모니터링하는 기술의 모든 것을 정리했습니다.
JVM 힙 메모리는 어떻게 설계하는가 — -Xms·-Xmx와 영역 구조
힙 설계의 첫 원칙은 초기 크기(-Xms)와 최대 크기(-Xmx)를 동일하게 설정하는 것입니다. 두 값이 다르면 운영 중 힙 확장·축소가 일어나며 그때마다 불필요한 GC와 멈춤이 발생합니다. Oracle 공식 튜닝 가이드도 서버 애플리케이션에서 두 값을 같게 두는 설정을 기본 접근으로 안내합니다(출처: Oracle — HotSpot Virtual Machine Garbage Collection Tuning Guide).
힙 내부는 세대(generation)로 나뉩니다. 새 객체가 만들어지는 Young 영역(Eden + Survivor), 오래 살아남은 객체가 승격되는 Old 영역, 그리고 클래스 메타데이터를 담는 힙 밖의 Metaspace입니다. 웹 애플리케이션의 객체 대부분은 요청 처리가 끝나면 버려지는 단명 객체이므로, Young 영역이 지나치게 작으면 살아 있는 객체가 조기 승격되어 Old 영역을 압박하고 Full GC를 부릅니다.

그림 2. JVM 힙 영역 구조 — 어떤 옵션이 어느 경계를 정하는가
실무 기준값은 다음과 같습니다.
- -Xms = -Xmx: 동일 설정. 물리 메모리에서 OS·다른 프로세스 몫을 뺀 범위에서 결정합니다.
- 힙 크기 상한: 한 인스턴스에 수십 GB를 몰아주기보다, 힙을 적정 크기로 유지하고 인스턴스 수로 확장하는 편이 GC 멈춤 관리에 유리합니다.
- Metaspace: 기본은 자동 확장이지만, 메모리 누수 감지를 위해 -XX:MaxMetaspaceSize로 상한을 두는 운영이 안전합니다.
- OOM 대비: -XX:+HeapDumpOnOutOfMemoryError를 켜 두면 장애 후 원인 분석이 가능해집니다.
여기서 자주 놓치는 항목이 세션입니다. WAS가 사용자 세션을 자기 힙 안에 들고 있으면, 동시 접속자가 늘어날수록 세션이 Old 영역을 그대로 밀어 올립니다. 힙을 키워도 세션이 함께 커지기 때문에 Full GC 멈춤은 오히려 길어집니다. 이중화 구성에서 세션을 WAS끼리 복제하는 방식이면 문제가 더 커집니다. 각 인스턴스가 남의 세션까지 힙에 들고 있어야 하기 때문입니다. 세션을 외부 인메모리 데이터 그리드로 옮기면 힙은 요청 처리 객체만 담게 되고, 힙 크기와 GC 멈춤을 처음 설계한 수준으로 되돌릴 수 있습니다. OPENMARU가 이 구조를 제품으로 정리한 것이 OPENMARU Cluster입니다.

그림 3. 세션을 힙 안에 두는가 밖에 두는가 — GC에 미치는 영향 (출처: OPENMARU iAP 제품 소개 자료)
GC 알고리즘은 무엇을 선택하는가 — Parallel·G1·ZGC 트레이드오프
GC 선택은 처리량(throughput)과 지연(latency) 사이의 트레이드오프입니다. 세 가지 대표 컬렉터의 성격이 뚜렷이 다릅니다(출처: Oracle — Garbage Collection Tuning Guide).
| 컬렉터 | 지향점 | 특징 | 적합한 워크로드 |
|---|---|---|---|
| Parallel GC | 처리량 최대화 | 멈춤은 길지만 전체 처리 효율이 높음 | 배치 처리, 멈춤에 둔감한 백엔드 |
| G1 GC | 처리량·지연 균형 | 힙을 리전으로 나눠 멈춤 목표(-XX:MaxGCPauseMillis) 관리 | 일반 웹 서비스 (기본 선택) |
| ZGC | 초저지연 | 멈춤을 수 ms 이하로 억제, 큰 힙에 유리 | 지연에 민감한 대화형·대용량 힙 서비스 |

그림 4. GC 컬렉터 선택 — 처리량과 지연 사이 어디에 설 것인가
판단 기준은 세 가지입니다. 첫째, Java 버전입니다. JDK 9부터 G1이 기본 컬렉터가 되었으므로(출처: OpenJDK — JEP 248) 현행 버전에서는 G1을 기본값으로 두고 시작하는 것이 표준입니다. 둘째, 서비스 특성입니다. 응답 지연 목표(P99 등)가 엄격하면 G1의 멈춤 목표를 조정하거나 ZGC를 검토하고, 야간 배치처럼 처리량이 우선이면 Parallel GC가 여전히 유효합니다. 셋째, 힙 크기입니다. 수십 GB 이상 대형 힙에서는 ZGC 계열의 저지연 특성이 뚜렷해집니다. 무엇을 고르든 “바꾸고 나서 지표로 확인”이 원칙이며, 기본값에서 시작해 측정 근거가 있을 때만 조정하는 것이 안전합니다.
GC 로그는 어떻게 읽는가 — Full GC 빈도와 Stop-the-World 시간
GC 병목 진단의 두 핵심 지표는 Full GC 빈도와 Stop-the-World(STW, GC를 위해 애플리케이션 전체가 멈추는 구간) 시간입니다. 현행 JDK에서는 -Xlog:gc* 옵션으로 GC 로그를 남길 수 있으며, 로그에서 다음 신호를 읽습니다.
- Full GC가 반복된다: Old 영역이 계속 차오른다는 뜻입니다. 힙이 절대적으로 작거나, 조기 승격이 일어나거나, 메모리 누수가 진행 중일 가능성이 있습니다. Full GC 후에도 Old 사용량이 줄지 않으면 누수 쪽에 무게를 두고 힙 덤프를 분석합니다.
- STW 시간이 길다: 요청 타임아웃·순간적 TPS 하락으로 직결됩니다. G1이라면 멈춤 목표와 힙 크기의 균형을 조정하고, 그래도 목표에 못 미치면 컬렉터 변경을 검토합니다.
- GC 주기가 짧다: Young 영역이 작아 마이너 GC가 지나치게 잦은 경우입니다. 할당 속도(allocation rate) 대비 Young 크기를 확인합니다.
경험적 경고선은 “Full GC가 시간 단위로 반복되거나, STW가 수 초를 넘는 상황”입니다. 이 수준이면 튜닝이 아니라 구조(힙 설계·누수·인스턴스 분리)를 손봐야 합니다.
다만 GC 로그만으로는 “그때 무엇이 느려졌는지”까지 닿지 않습니다. 로그는 GC가 몇 초 멈췄다는 사실을 남길 뿐, 그 멈춤이 어느 요청의 응답시간을 얼마나 밀어냈는지는 알려주지 않습니다. 그래서 실무에서는 GC 이벤트와 트랜잭션 지연을 같은 시간축에 놓고 봅니다. OPENMARU APM은 JVM 힙과 스레드 상태, Full GC 이벤트를 WAS 내부에서 직접 계측해 트랜잭션 지연·로그와 상관 분석하므로, “GC 때문인지 DB 때문인지”를 추측이 아니라 화면에서 가릅니다.

그림 5. GC 이벤트와 트랜잭션 지연을 같은 시간축에서 잇는 계측 구조 (출처: OPENMARU iAP 제품 소개 자료)
GC 로그·스레드 덤프·힙 덤프를 함께 놓고 원인을 좁히는 작업 자체를 맡기려면 시스템 진단 서비스를, 이 분석을 자연어 질의로 자동화한 사례는 프롬프트로 WAS 장애 분석 — OPENMARU APM AI Agent 데모를 참고하십시오.
스레드 풀과 커넥션 풀은 어떻게 산정하는가 — 공식과 흔한 실수
두 풀의 산정 원칙은 “동시 처리량의 병목을 어디에 둘 것인가”입니다. 기준값과 근거는 다음과 같습니다.
스레드 풀(Thread Pool) — Tomcat의 maxThreads 기본값은 200입니다(출처: Apache Tomcat — Executor 설정 문서). 이 값은 출발점일 뿐이며, 적정값은 워크로드 성격에 따라 갈립니다. CPU 연산 중심이면 코어 수에 가깝게 줄이는 편이 낫고, DB·외부 API 대기가 많은 I/O 중심이면 늘릴 여지가 있습니다. 과대 설정의 증상은 컨텍스트 스위칭 증가로 CPU는 바쁜데 처리량이 늘지 않는 상태, 과소 설정의 증상은 CPU 여유가 있는데도 요청이 큐에 쌓이는 상태입니다.
커넥션 풀(Connection Pool) — 흔한 오해와 달리 “스레드 수만큼 커넥션”은 과대 설정입니다. 커넥션 풀 라이브러리 HikariCP의 산정 가이드는 코어 수 × 2 + 유효 디스크 수를 출발점으로 제시하며, 실측에서 작은 풀이 더 높은 처리량을 내는 경우가 많다고 설명합니다(출처: HikariCP — About Pool Sizing). DB 서버의 동시 처리 능력이 상한이므로, WAS 인스턴스 수 × 풀 크기의 총합이 DB 최대 연결 수 안에 들어오는지도 반드시 확인해야 합니다.
흔한 설정 실수 세 가지를 짚어 두면 이렇습니다. ① 스레드 200개에 커넥션 20개 — 대기 스레드가 커넥션을 기다리며 쌓입니다(풀 대기 타임아웃 필수). ② 커넥션 풀만 계속 증설 — DB 쪽 병목이면 오히려 DB를 밀어붙여 전체가 느려집니다. ③ 타임아웃 미설정 — 연결 대기·검증 타임아웃이 없으면 장애가 전 계층으로 전파됩니다.
두 값을 어디에 적어 넣는지, 설치 방식에 따라 설정 파일이 어디에 놓이는지는 Apache Tomcat 설치의 모든 것에 정리해 두었습니다. 인스턴스가 여러 대로 늘어난 뒤에는 “지금 어느 서버에 어떤 값이 들어가 있는가”를 사람이 기억하기 어려워집니다. 설치·설정 현황을 서버별로 자동 수집해 보고서로 남기는 방법은 Apache·Tomcat·JBoss·WildFly 설치 보고서 글에서 다룹니다.
튜닝 전후는 어떻게 검증하는가 — 부하 테스트와 지표 기반 평가
튜닝의 완성은 설정 변경이 아니라 검증입니다. 절차는 네 단계입니다.
- 기준선(baseline) 측정: 변경 전 상태에서 부하 테스트로 TPS(초당 처리 건수), 평균·P99 응답시간, GC 멈춤 시간, 스레드·커넥션 사용률을 기록합니다.
- 한 번에 한 축만 변경: 힙·GC·스레드·커넥션을 동시에 바꾸면 효과의 원인을 알 수 없습니다. 한 파라미터씩 바꾸고 같은 시나리오로 재측정합니다.
- 목표 지표로 판정: “P99 응답시간 N ms 이하, GC 멈춤 N ms 이하, 목표 TPS 달성” 같은 수치 목표를 사전에 정하고, 달성 여부로 채택을 판정합니다.
- 운영 모니터링으로 상시화: 부하 테스트는 스냅샷일 뿐입니다. 운영 트래픽에서 같은 지표를 상시 관측해야 설정과 실제 워크로드의 어긋남을 조기에 잡을 수 있습니다.
3단계의 “목표 지표”를 어떤 기준으로 잡을지가 실무에서 가장 자주 막히는 지점입니다. 평균 응답시간 대신 p95·p99를 보는 이유, TPS와 응답시간을 반드시 함께 읽어야 하는 이유, 에러율을 5xx·예외·타임아웃으로 나눠 집계해야 하는 이유는 APM 핵심 지표 읽는 법에 수치 기준과 함께 정리해 두었습니다.
이 상시 관측 구간이 APM의 영역입니다. APM(Application Performance Management, 애플리케이션 성능 관리)이 무엇이고 어떤 지표를 보는지는 기준 문서인 APM 글에서, 로그·지표·추적을 모아 두는 옵저버빌리티와의 역할 차이는 APM 옵저버빌리티 차이 글에서 다룹니다. OPENMARU APM은 트랜잭션 단위로 요청 경로를 추적해 “느린 요청이 스레드 대기·GC·DB 중 어디서 시간을 썼는지”를 구간별로 보여 주므로, 튜닝 전후 비교와 병목 재발 감지를 같은 화면에서 할 수 있습니다. 요청 한 건을 구간 단위로 따라가는 원리 자체는 트랜잭션 추적이란 글에서 별도로 설명합니다.

그림 6. 느린 요청이 어느 구간에서 시간을 썼는지 가르는 End-to-End 추적 (출처: OPENMARU iAP 제품 소개 자료)
또한 OPENMARU iAP(Intelligent Application Platform)는 엔터프라이즈·공공의 기존 서버·가상화(VM) 환경을 대상으로 Web/WAS 설치·구성·튜닝 자동화와 성능관리·운영관리를 통합 제공하므로, 인스턴스마다 수작업으로 반복하던 튜닝 기준을 플랫폼 차원에서 표준화할 수 있습니다. WAS라는 계층 자체의 구조와 제품 선택 기준을 먼저 잡고 싶다면 WAS란 무엇인가 글이 출발점입니다.
튜닝으로 단일 인스턴스 성능을 확보한 다음 단계는 인스턴스 확장이며, 이때 세션 공유 문제가 새로 등장합니다. 앞서 본 것처럼 세션을 WAS 힙에 두는 한 인스턴스를 늘릴수록 복제 부하와 Full GC 위험이 함께 늘어나므로, 확장 설계는 세션을 외부로 분리하는 OPENMARU Cluster 방식과 이어서 검토하는 편이 좋습니다.
자주 묻는 질문 (FAQ)
Q. WAS 성능 튜닝은 무엇부터 시작해야 하나요?
현재 상태 측정부터 시작합니다. 부하 테스트나 운영 지표로 TPS·응답시간·GC 멈춤·스레드/커넥션 사용률의 기준선을 잡고, 병목이 나타나는 축(힙·GC·스레드 풀·커넥션 풀)을 특정한 뒤 한 번에 한 파라미터씩 조정합니다.
Q. -Xms와 -Xmx는 왜 같게 설정하나요?
두 값이 다르면 운영 중 힙 확장·축소가 반복되며 그때마다 불필요한 GC 부하와 멈춤이 발생합니다. 서버 애플리케이션은 시작 시점에 최대 힙을 확보해 고정하는 것이 안정적이며, Oracle 튜닝 가이드의 기본 접근이기도 합니다.
Q. GC 알고리즘은 무엇을 선택해야 하나요?
JDK 9 이후 기본값인 G1에서 시작하는 것이 표준입니다. 응답 지연 요구가 엄격하거나 힙이 수십 GB 이상이면 ZGC를, 멈춤에 둔감한 배치·처리량 중심 워크로드면 Parallel GC를 검토합니다. 변경은 반드시 지표 측정과 함께 진행합니다.
Q. 커넥션 풀 크기는 스레드 수와 같아야 하나요?
아닙니다. 커넥션 풀은 DB의 동시 처리 능력에 맞추는 것이 원칙이며, HikariCP 가이드는 코어 수 × 2 + 유효 디스크 수를 출발점으로 제시합니다. 실측에서는 작은 풀이 더 높은 처리량을 내는 경우가 많고, 인스턴스 수 × 풀 크기 총합이 DB 최대 연결 수를 넘지 않아야 합니다.
Q. Full GC가 자주 발생하면 어떻게 진단하나요?
GC 로그에서 Full GC 후 Old 영역 사용량을 확인합니다. 사용량이 회복되면 힙 부족·조기 승격 문제이므로 힙·Young 영역 크기를 조정하고, 회복되지 않고 우상향하면 메모리 누수 가능성이 크므로 힙 덤프를 떠서 객체 점유를 분석합니다.
참고 리소스
WAS 시리즈 (openmaru.io)
– WAS란 무엇인가 — 구조와 기능, 제품 선택 기준까지
– WAS와 웹서버의 차이 — 요청 흐름부터 분리 배치 이유까지
– Tomcat vs 상용 WAS — 기능·지원·TCO로 가르는 선택 기준
– 국내 WAS 시장 지형 — 국산·외산·오픈소스 구도와 교체 검토 기준
– Apache Tomcat 설치의 모든 것 — 이것만 알면 설치는 끝
– Apache·Tomcat·JBoss·WildFly 설치 보고서 — 설치·설정 현황 자동 수집
– JBoss EAP와 WildFly 차이점 비교 분석
성능 관측 시리즈 (openmaru.io)
– APM이란 무엇인가 — 서버 모니터링으로 못 잡는 장애
– APM 핵심 지표 읽는 법 — 응답시간·TPS·에러율의 의미
– 트랜잭션 추적이란 — 느린 요청을 코드 레벨까지 따라가는 기술
– APM 옵저버빌리티 차이 — 무엇이 다르고, 무엇부터 갖춰야 하나
– 프롬프트로 WAS 장애 분석 — OPENMARU APM AI Agent 데모
제품·서비스 (자사)
– 시스템 진단 서비스 — 장애 해결과 성능 개선
– OPENMARU Cluster — 세션 클러스터링 솔루션
– OPENMARU APM — 애플리케이션 성능 관리
– 조달물품 OPENMARU iAP — 제품 소개
– Web/WAS 비용 절감의 해법 — OPENMARU iAP 백서
표준·공식 문서 (외부)
– HotSpot Virtual Machine Garbage Collection Tuning Guide — Oracle
– JEP 248: Make G1 the Default Garbage Collector — OpenJDK
– The Executor (thread pool) — Apache Tomcat Configuration Reference
– Java HotSpot VM Options — Oracle
– About Pool Sizing — HikariCP
문의
WAS 성능 튜닝과 오픈소스 전환, 운영 모니터링이 필요하시면 OPENMARU가 도와드립니다.
- OPENMARU iAP 제품 알아보기 — https://www.openmaru.io/iap/
- OPENMARU APM 무료 체험 — https://www.openmaru.io/product/openmaru-cloud-apm/
- 도입 레퍼런스 확인 — https://www.openmaru.io/clients/
- 오픈소스 WAS·Red Hat 제품 문의 — https://www.openmaru.io/request-for-quote/





AI Native News | AI 시대, 이제 안 바뀌는 게 없습니다. | 인프라·개발·운영·사람의 진짜 변화
/카테고리: APM/작성자: 오픈마루 마케팅3AI Native News | 아직도 감으로 서버 늘리세요? AI·데이터로 바꾸는 IT 실무 4가지
/카테고리: APM/작성자: 오픈마루 마케팅3오픈마루, 2026 공공 AI 박람회 참가 (6/23~24, 일산 킨텍스)
/카테고리: OPENMARU/작성자: marketing2