마인크래프트/서버 최적화
마인크래프트 서버 최적화는 마인크래프트 서버가 안정적인 TPS와 응답성을 유지하도록 설정, 월드, 플러그인, 하드웨어, 운영 작업을 조정하는 과정이다. 최적화는 단순히 램을 많이 주거나 플러그인을 추가하는 일이 아니다. 서버가 느려지는 원인을 측정하고, 실제 병목에 맞게 조정하는 작업이다.
Java Edition 서버에서는 Paper 계열 구동기가 성능 개선과 세부 설정을 제공하기 때문에 널리 사용된다. 다만 Paper를 사용하더라도 청크, 엔티티, 블록 엔티티, 플러그인, 지도 렌더링, 백업 작업이 과도하면 성능 저하가 발생할 수 있다.
기본 지표
서버 성능을 볼 때 자주 사용하는 지표는 TPS와 MSPT이다.
| 지표 | 설명 |
|---|---|
| TPS | 초당 서버 틱 수이다. 일반적으로 20 TPS가 정상 기준이다. |
| MSPT | 한 틱을 처리하는 데 걸리는 시간이다. 50ms를 넘으면 20 TPS를 유지하기 어렵다. |
| Ping | 플레이어와 서버 사이의 네트워크 지연 시간이다. |
| CPU 사용량 | 서버 틱 처리와 플러그인 작업에 영향을 준다. |
| 메모리 사용량 | 월드, 플러그인, 캐시, Java 힙 사용량에 영향을 준다. |
TPS가 낮다고 해서 항상 메모리가 부족한 것은 아니다. 마인크래프트 서버는 많은 작업이 메인 스레드에서 처리되므로, CPU 단일 코어 성능이 중요하다.
하드웨어
서버 하드웨어에서 중요한 요소는 다음과 같다.
- CPU 단일 코어 성능
- 충분한 메모리
- 빠른 SSD 또는 NVMe 저장 장치
- 안정적인 네트워크
- 백업 저장 공간
메모리를 지나치게 많이 할당하면 Java GC 동작에 따라 오히려 불안정할 수 있다. 서버 규모와 플러그인 수에 맞게 할당하고, 사용량을 관찰하면서 조정하는 것이 좋다.
Java와 실행 옵션
서버 구동기 버전에 맞는 Java 버전을 사용해야 한다. 26.1 이상은 Java 25를 요구하며, Java 17이나 21 환경에서는 구동되지 않는다.
가장 단순한 실행 명령은 다음과 같다.
java -Xms8G -Xmx8G -jar paper.jar --nogui
-Xms와 -Xmx를 같은 값으로 두는 것은 힙 크기가 실행 중에 오르내리며 발생하는 재조정 비용을 없애기 위한 것으로, 서버 환경에서는 일반적인 관행이다.
JVM 플래그는 서버 버전과 Java 버전에 따라 권장값이 달라진다. 특히 26.1에서 가비지 컬렉터 관련 상황이 크게 바뀌었으므로, 오래된 글에서 플래그를 그대로 복사하기 전에 아래 문단을 확인해야 한다.
가비지 컬렉터
자바 프로그램은 더 이상 쓰이지 않는 객체를 가비지 컬렉터(GC)가 정리한다. 마인크래프트 서버는 매 틱마다 많은 객체를 만들고 버리기 때문에, GC가 작업하는 동안 서버가 멈추는 '정지 시간(pause)'이 곧 TPS 하락으로 나타난다. 최적화에서 GC 선택이 중요한 이유다.
26.1의 변화
26.1에서 게임의 기본 메모리 할당량이 2GB에서 4GB로 올라갔고, 기본 가비지 컬렉터가 G1GC에서 ZGC로 바뀌었다.
이는 게임 자체의 기본값 변경이므로, JVM 플래그를 운영자가 직접 지정하는 전용 서버에서는 자동으로 적용되지 않는다. 다만 두 가지 이유로 서버 운영에도 의미가 있다.
- 26.1부터 요구되는 Java 25에서는 ZGC가 세대별(generational) 방식으로 동작하며, 과거에 ZGC가 메모리를 과하게 쓴다고 알려졌던 시절과 특성이 다르다.
- 모장이 기본값을 ZGC로 옮겼다는 것은 이후 버전이 ZGC 환경에서 우선 검증된다는 뜻이기도 하다.
G1GC와 ZGC
| 구분 | G1GC | ZGC |
|---|---|---|
| 특징 | 정지 시간을 목표치 안에서 관리 | 힙 크기와 무관하게 정지 시간을 매우 짧게 유지 |
| 튜닝 | 플래그 조정 여지가 크다 | 기본값으로 두는 것을 전제로 설계됨 |
| 메모리 | 상대적으로 적게 사용 | 여유 있게 할당해야 이점이 나온다 |
| 적합한 경우 | 8~12GB 이하, 기존 설정이 안정적으로 운영 중인 서버 | 12GB 이상, 대규모 월드 편집이나 지도 렌더링으로 순간 부하가 큰 서버 |
가장 흔한 실수는 두 방식의 플래그를 섞어 쓰는 것이다. 널리 알려진 이른바 'Aikar's Flags'는 G1GC를 전제로 세밀하게 조정된 값이므로, -XX:+UseZGC와 함께 쓰면 대부분 무시되거나 오히려 해가 된다.
실행 예시
G1GC 계열 (Aikar's Flags):
java -Xms10G -Xmx10G --add-modules=jdk.incubator.vector \ -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 \ -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch \ -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M \ -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 \ -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 \ -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 \ -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 \ -jar paper.jar --nogui
ZGC 계열:
java -Xms12G -Xmx12G \ -XX:+UseZGC -XX:+AlwaysPreTouch -XX:+DisableExplicitGC -XX:+PerfDisableSharedMem \ -jar paper.jar --nogui
ZGC는 세부 튜닝 없이 쓰도록 설계되었으므로 플래그가 짧다. 플래그가 적다고 해서 설정이 덜 된 것이 아니다.
전환할 때의 확인 절차
운영 중인 서버의 GC를 바꾸는 것은 되돌릴 수 있는 작업이지만, 체감 효과는 실제 부하에서만 드러난다.
- 변경 전 상태를 기록한다. spark 등으로 평시와 피크 시간의 MSPT·GC 정지 시간을 남긴다.
- 시험 서버에서 먼저 적용한다.
- 같은 시간대·같은 인원 조건에서 비교한다.
- 메모리 사용량이 늘어나는 것 자체는 ZGC에서 정상이다. 판단 기준은 사용량이 아니라 정지 시간과 MSPT다.
- 개선이 확인되지 않으면 되돌린다. GC 교체는 병목이 GC일 때만 효과가 있다.
view-distance와 simulation-distance
`view-distance`와 `simulation-distance`는 서버 성능에 큰 영향을 준다.
- `view-distance`: 플레이어에게 전송되는 청크 거리
- `simulation-distance`: 실제 게임 로직이 시뮬레이션되는 청크 거리
`view-distance`를 높이면 멀리 볼 수 있지만 네트워크와 청크 전송량이 늘어난다. `simulation-distance`를 높이면 몹, 레드스톤, 작물, 엔티티 처리량이 늘어난다. 공개 서버에서는 두 값을 무작정 높이기보다 서버 목적에 맞게 조정해야 한다.
청크 관리
청크 생성과 로딩은 서버 부하의 큰 원인이다. 새 월드를 탐험하거나 대형 지도 렌더링을 돌릴 때 청크 생성량이 크게 늘 수 있다.
청크 관련 최적화 방법은 다음과 같다.
- 월드 경계를 정한다.
- 필요한 지역을 미리 생성한다.
- 불필요한 청크 로딩 플러그인을 줄인다.
- 지도 렌더링 작업을 서버 피크 시간에 돌리지 않는다.
- 대규모 월드 편집 후 저장과 백업 시간을 고려한다.
도시건축 서버에서는 월드를 넓게 확장하기보다 실제 건축과 지도 렌더링 범위를 기준으로 관리하는 것이 좋다.
엔티티와 블록 엔티티
엔티티와 블록 엔티티는 서버 틱에 영향을 준다.
부하를 만들 수 있는 요소는 다음과 같다.
- 많은 수의 몹
- 아이템 엔티티
- 마인카트와 보트
- 액자와 아이템 프레임
- 호퍼
- 상자와 셜커 박스
- 복잡한 레드스톤 장치
엔티티를 무조건 제거하는 플러그인은 임시로 부하를 줄일 수 있지만, 원인을 숨길 수도 있다. 먼저 어떤 엔티티와 구역이 부하를 만드는지 확인하는 것이 좋다.
플러그인 최적화
플러그인은 서버 기능을 확장하지만 성능 문제의 원인이 되기도 한다.
점검할 항목은 다음과 같다.
- 오래된 플러그인
- 같은 기능을 중복 제공하는 플러그인
- 과도한 이벤트 리스너
- 반복 작업을 자주 실행하는 플러그인
- 데이터베이스 쿼리가 많은 플러그인
- 지도 렌더링 또는 통계 수집 플러그인
문제가 있을 때는 플러그인을 하나씩 제거해 추측하기보다, 프로파일러로 어떤 작업이 시간을 쓰는지 확인하는 것이 좋다. Paper 계열에는 spark 프로파일러가 내장되어 있어 /spark profiler start로 측정을 시작하고 /spark profiler stop으로 결과 링크를 받을 수 있다. /spark health는 TPS·MSPT·GC 정지 시간을 한 번에 보여주므로, 가비지 컬렉터 설정을 바꾸기 전후를 비교할 때 기준으로 삼을 수 있다.
지도 렌더링
Dynmap과 BlueMap 같은 지도 플러그인은 서버 월드를 웹에서 볼 수 있게 하지만, 초기 렌더링과 대규모 갱신 작업은 많은 CPU와 디스크 I/O를 사용할 수 있다.
지도 플러그인을 운영할 때는 다음을 고려한다.
- 렌더링 범위
- 렌더링 스케줄
- 타일 저장 위치
- 외부 웹서버 사용 여부
- 지도 데이터 백업 여부
- 서버 피크 시간 회피
도시건축 서버에서는 지도 품질과 서버 성능 사이의 균형이 중요하다.
백업과 저장
백업은 서버 안정성을 높이지만 실행 시점과 방식에 따라 성능에 영향을 줄 수 있다.
주의할 점은 다음과 같다.
- 피크 시간대에 무거운 백업 작업을 피한다.
- 월드 저장과 백업이 겹치지 않게 한다.
- 압축 작업이 CPU를 과도하게 사용하지 않는지 확인한다.
- 백업 대상과 보존 기간을 정한다.
- 복구 테스트를 주기적으로 한다.
피해야 할 방법
다음 방법은 문제를 더 복잡하게 만들 수 있다.
- 원인을 확인하지 않고 플러그인을 무작정 추가하기
- `/reload`로 플러그인을 다시 불러오기
- 메모리만 계속 늘리기
- 오래된 최적화 플러그인을 최신 서버에 그대로 사용하기
- 오류 로그를 무시하고 설정만 바꾸기
- 테스트 없이 Paper 또는 Java 버전을 올리기
- G1GC 전용 플래그를
-XX:+UseZGC와 함께 쓰기 — 대부분 무시되거나 역효과가 난다 - 병목을 확인하지 않고 가비지 컬렉터부터 바꾸기 — GC 교체는 병목이 GC일 때만 효과가 있다
같이 보기
- 마인크래프트 버전 체계
- 마인크래프트: 자바 에디션 26.1
- 마인크래프트/Vulkan 렌더러
- 마인크래프트/서버
- 마인크래프트/서버 운영
- 마인크래프트/서버 오류
- Paper(마인크래프트)
- 마인크래프트/플러그인
- 마인크래프트/청크
- 마인크래프트/엔티티
- 마인크래프트/플러그인/Dynmap
- BlueMap
- 플레이시티 블록/서버