마인크래프트 1.20.6 Paper 서버 구축 및 관리 가이드 (AWS Lightsail, Ubuntu 22.04 LTS, Java 21)

Posted by

마인크래프트 1.20.6 Paper 서버 구축 및 관리 가이드 (AWS Lightsail, Ubuntu 22.04 LTS, Java 21)

목차:

  1. AWS Lightsail 인스턴스 생성
  2. 기본 시스템 설정
  3. Java 21 설치
  4. 마인크래프트 Paper 서버 설치
  5. 서버 구성 및 최적화
  6. 시작 스크립트 생성
  7. 서버 업데이트 관리
  8. 서버 유지보수 및 백업
  9. 문제 해결 및 로깅
  10. 보안 설정
  11. 성능 모니터링 및 튜닝
  12. 플러그인 관리
  13. 커스텀 맵 및 게임모드
  14. 멀티월드 설정
  15. 백업 및 복구 전략

1. AWS Lightsail 인스턴스 생성

AWS Lightsail에서 Ubuntu 22.04 LTS 인스턴스를 생성하는 과정을 상세히 설명합니다.

  1. AWS 계정 로그인:

  2. Lightsail 서비스 선택:

    • AWS 콘솔에서 "Lightsail"을 검색하거나 서비스 목록에서 선택합니다.
  3. 인스턴스 생성:

    • Lightsail 대시보드에서 "인스턴스 생성" 버튼을 클릭합니다.
  4. 인스턴스 플랜 선택:

    • 지역: 서버를 운영할 지역을 선택합니다. 대부분의 경우 사용자와 가까운 지역을 선택하는 것이 좋습니다.
    • 플랫폼: "Linux/Unix"를 선택합니다.
    • 블루프린트: "OS 전용"을 선택한 후 "Ubuntu 22.04 LTS"를 선택합니다.
  5. 인스턴스 플랜 선택:

    • 마인크래프트 서버의 경우 최소 2GB RAM이 권장됩니다.
    • 예산과 예상 플레이어 수에 따라 적절한 플랜을 선택합니다.
    • 초기에는 2GB RAM / 1 vCPU 플랜으로 시작하고, 필요에 따라 업그레이드할 수 있습니다.
  6. 인스턴스 이름 지정:

    • 식별하기 쉬운 이름을 지정합니다 (예: "minecraft-paper-server").
  7. 인스턴스 생성:

    • "인스턴스 생성" 버튼을 클릭하여 인스턴스를 생성합니다.
  8. 인스턴스 시작:

    • 인스턴스 생성이 완료되면 자동으로 시작됩니다. 상태가 "실행 중"으로 변경될 때까지 기다립니다.
  9. 고정 IP 할당:

    • 인스턴스 관리 페이지에서 "네트워킹" 탭으로 이동합니다.
    • "고정 IP 생성" 버튼을 클릭하여 고정 IP를 할당합니다.
  10. 방화벽 설정:

    • "네트워킹" 탭에서 방화벽 설정을 확인합니다.
    • SSH(포트 22)와 마인크래프트 서버(기본 포트 25565)에 대한 인바운드 규칙이 있는지 확인합니다.
    • 마인크래프트 포트가 없다면 "규칙 추가"를 클릭하고 "사용자 지정" TCP 25565를 추가합니다.
  11. SSH 접속 준비:

    • 인스턴스 관리 페이지에서 "연결" 탭으로 이동합니다.
    • SSH 사용을 위한 사용자 이름(기본값: ubuntu)과 IP 주소를 확인합니다.

이제 AWS Lightsail 인스턴스가 준비되었습니다. 다음 단계에서는 이 인스턴스에 SSH로 접속하여 서버 설정을 진행하겠습니다.

2. 기본 시스템 설정

AWS Lightsail 인스턴스에 SSH로 접속한 후, 기본적인 시스템 설정을 진행합니다.

  1. SSH 접속:

    • Windows 사용자: PuTTY나 Windows Terminal을 사용합니다.
    • macOS/Linux 사용자: 터미널에서 다음 명령어를 사용합니다:
      ssh ubuntu@your_instance_ip
  2. 시스템 업데이트:

    sudo apt update
    sudo apt upgrade -y
  3. 필수 패키지 설치:

    sudo apt install -y curl wget unzip screen htop
  4. 시간대 설정:

    sudo timedatectl set-timezone Asia/Seoul
  5. 방화벽 설정:

    sudo ufw allow OpenSSH
    sudo ufw allow 25565/tcp
    sudo ufw enable
  6. 스왑 파일 생성 (선택사항, RAM이 4GB 미만인 경우 권장):

    sudo fallocate -l 4G /swapfile
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
    echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
  7. 시스템 리소스 제한 조정:

    sudo nano /etc/security/limits.conf

    파일 끝에 다음 내용을 추가:

    * soft nofile 24000
    * hard nofile 40000
  8. sysctl 설정 최적화:

    sudo nano /etc/sysctl.conf

    파일 끝에 다음 내용을 추가:

    net.ipv4.tcp_fin_timeout = 30
    net.ipv4.tcp_keepalive_time = 1200
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_max_syn_backlog = 8192
    net.ipv4.ip_local_port_range = 10000 65535
    net.core.netdev_max_backlog = 65536
  9. 변경사항 적용:

    sudo sysctl -p
  10. 재부팅:

    sudo reboot

재부팅 후 SSH로 다시 접속하여 다음 단계를 진행합니다.

3. Java 21 설치

Paper 서버를 실행하기 위해 Java 21을 설치합니다.

  1. Java 21 저장소 추가:

    sudo add-apt-repository ppa:linuxuprising/java
  2. 시스템 업데이트:

    sudo apt update
  3. Java 21 설치:

    sudo apt install oracle-java21-installer
  4. Java 버전 확인:

    java -version

    출력 예시:

    java version "21.0.1" 2023-10-17 LTS
    Java(TM) SE Runtime Environment (build 21.0.1+12-LTS-29)
    Java HotSpot(TM) 64-Bit Server VM (build 21.0.1+12-LTS-29, mixed mode, sharing)
  5. JAVA_HOME 환경 변수 설정:

    echo 'export JAVA_HOME=/usr/lib/jvm/java-21-oracle' >> ~/.bashrc
    echo 'export PATH=$JAVA_HOME/bin:$PATH' >> ~/.bashrc
    source ~/.bashrc
  6. JAVA_HOME 확인:

    echo $JAVA_HOME

이제 Java 21이 성공적으로 설치되었습니다. 다음으로 마인크래프트 Paper 서버를 설치하겠습니다.

4. 마인크래프트 Paper 서버 설치

Paper 서버는 Spigot의 고성능 포크로, 더 나은 성능과 최적화를 제공합니다. 여기서는 마인크래프트 1.20.6 버전의 Paper 서버를 설치하겠습니다.

  1. 서버 디렉토리 생성:

    mkdir ~/minecraft-server
    cd ~/minecraft-server
  2. Paper 서버 JAR 파일 다운로드:

    wget https://api.papermc.io/v2/projects/paper/versions/1.20.6/builds/320/downloads/paper-1.20.6-320.jar

    주의: 위 URL은 변경될 수 있습니다. 최신 버전은 https://papermc.io/downloads 에서 확인할 수 있습니다.

  3. 서버 시작 스크립트 생성:

    nano start.sh

    다음 내용을 입력합니다:

    #!/bin/bash
    java -Xms2G -Xmx2G -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 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true -jar paper-1.20.6-320.jar nogui

    이 스크립트는 Aikar's Flags를 사용하여 서버 성능을 최적화합니다.

  4. 스크립트에 실행 권한 부여:

    chmod +x start.sh
  5. EULA 동의:
    서버를 처음 실행하면 EULA에 동의해야 합니다.

    ./start.sh

    서버가 중단되면 다음 명령어로 EULA에 동의합니다:

    echo "eula=true" > eula.txt
  6. 서버 재시작:

    ./start.sh

이제 마인크래프트 Paper 서버가 설치되고 실행되었습니다. 다음 단계에서는 서버 구성 및 최적화를 진행하겠습니다.

5. 서버 구성 및 최적화

마인크래프트 서버의 성능을 최적화하고 원하는 대로 구성하기 위해 여러 설정을 조정할 수 있습니다.

  1. server.properties 설정:

    nano server.properties

    주요 설정:

    server-port=25565
    max-players=20
    view-distance=10
    simulation-distance=6
    spawn-protection=16
    max-world-size=29999984
    network-compression-threshold=256
    online-mode=true
    allow-flight=false
    white-list=false

    각 설정에 대한 설명:

    • server-port: 서버 포트 (기본값: 25565)
    • max-players: 최대 동시 접속 플레이어 수
    • view-distance: 플레이어가 볼 수 있는 청크 거리
    • simulation-distance: 서버가 시뮬레이션하는 청크 거리
    • spawn-protection: 스폰 지역 보호 반경
    • max-world-size: 월드의 최대 크기
    • network-compression-threshold: 네트워크 압축 임계값
    • online-mode: 정품 인증 여부
    • allow-flight: 플라이 허용 여부
    • white-list: 화이트리스트 사용 여부
  2. spigot.yml 설정:

    nano spigot.yml

    주요 설정:

    settings:
     save-user-cache-on-stop-only: true
     moved-wrongly-threshold: 0.0625
     moved-too-quickly-multiplier: 10.0
    world-settings:
     default:
       merge-radius:
         item: 2.5
         exp: 3.0
       item-despawn-rate: 6000
       view-distance: 10
       entity-activation-range:
         animals: 32
         monsters: 32
         raiders: 48
         misc: 16
       tick-inactive-villagers: false
       mob-spawn-range: 6
  3. paper-world-defaults.yml 설정:

    nano config/paper-world-defaults.yml

    주요 설정:

    entities:
     behavior:
       disable-chest-cat-detection: true
     spawning:
       despawn-ranges:
         ambient:
           soft: 32
           hard: 128
         axolotls:
           soft: 32
           hard: 128
         creature:
           soft: 32
           hard: 128
         misc:
           soft: 32
           hard: 128
         monster:
           soft: 32
           hard: 128
         underground_water_creature:
           soft: 32
           hard: 128
         water_ambient:
           soft: 32
           hard: 64
         water_creature:
           soft: 32
           hard: 128
    chunks:
     max-auto-save-chunks-per-tick: 6
    tick-rates:
     mob-spawner: 2
     container-update: 1
     grass-spread: 4
     bed-search-radius: 1
  4. bukkit.yml 설정:

    nano bukkit.yml

    주요 설정:

    settings:
     allow-end: true
     warn-on-overload: true
     permissions-file: permissions.yml
     update-folder: update
     plugin-profiling: false
     connection-throttle: 4000
     query-plugins: true
     deprecated-verbose: default
     shutdown-message: Server closed
    spawn-limits:
     monsters: 70
     animals: 10
     water-animals: 5
     water-ambient: 20
     water-underground-creature: 5
     ambient: 15
    chunk-gc:
     period-in-ticks: 600
    ticks-per:
     animal-spawns: 400
     monster-spawns: 1
     water-spawns: 1
     water-ambient-spawns: 1
     water-underground-creature-spawns: 1
     ambient-spawns: 1
  5. paper-global.yml 설정:

    nano config/paper-global.yml

    주요 설정:

    proxies:
     velocity:
       enabled: false
       online-mode: true
       secret: ''
    timings:
     enabled: true
     verbose: true
     server-name-privacy: false
     hidden-config-entries:
     - database
     - settings.bungeecord-addresses
    messages:
     kick:
       authentication-servers-down: 인증 서버가 다운되었습니다. 나중에 다시 시도해주세요.
       connection-throttle: 너무 빨리 재접속했습니다! 잠시 후 다시 시도해주세요.
       flying-player: 비행이 허용되지 않습니다
       flying-vehicle: 비행이 허용되지 않습니다

이러한 설정들은 서버의 성능과 동작을 크게 향상시킬 수 있습니다. 하지만 각 서버의 하드웨어 사양과 플레이어 수에 따라 최적의 설정이 다를 수 있으므로, 필요에 따라 조정해야 합니다.

6. 시작 스크립트 생성

Paper 서버를 더 쉽게 관리하고 자동으로 재시작할 수 있도록 시작 스크립트를 만들어 보겠습니다. 이 스크립트는 https://docs.papermc.io/misc/tools/start-script-gen 에서 제공하는 도구를 기반으로 합니다.

  1. 시작 스크립트 생성:

    nano start.sh
  2. 다음 내용을 붙여넣습니다:

#!/bin/bash

# 서버 JAR 파일 이름
SERVER_JAR="paper-1.20.6-320.jar"

# 서버에 할당할 최소 및 최대 메모리
MIN_RAM="2G"
MAX_RAM="2G"

# 백그라운드에서 실행할지 여부 (true/false)
BACKGROUND="false"

# 자동 재시작 여부 (true/false)
RESTART="true"

# 충돌 시 재시작 대기 시간 (초)
CRASH_TIMER=10

# JVM 인자
JVM_ARGS="-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 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true"

# 서버 디렉토리
SERVER_DIR="$HOME/minecraft-server"

cd $SERVER_DIR

while true; do
    if [ "$BACKGROUND" == "true" ]; then
        screen -dmS minecraft java -Xms$MIN_RAM -Xmx$MAX_RAM $JVM_ARGS -jar $SERVER_JAR nogui
    else
        java -Xms$MIN_RAM -Xmx$MAX_RAM $JVM_ARGS -jar $SERVER_JAR nogui
    fi

    if [ "$RESTART" != "true" ]; then
        exit 0
    fi

    echo "서버가 중지되었습니다. $CRASH_TIMER초 후 재시작합니다."
    sleep $CRASH_TIMER
done
  1. 스크립트에 실행 권한 부여:

    chmod +x start.sh
  2. 스크립트 실행:

    ./start.sh

이 스크립트는 서버를 시작하고, 충돌이 발생하면 자동으로 재시작합니다. 백그라운드에서 실행하려면 BACKGROUND="true"로 설정하세요.

7. 서버 업데이트 관리

Paper 서버를 최신 버전으로 유지하는 것은 중요합니다. 새로운 기능, 버그 수정, 보안 패치를 받을 수 있기 때문입니다. 다음은 서버를 업데이트하는 방법입니다.

  1. 현재 서버 중지:
    서버 콘솔에서 stop 명령어를 입력하거나, 실행 중인 스크린 세션을 종료합니다.

  2. 백업 생성:

    cp -r ~/minecraft-server ~/minecraft-server-backup-$(date +%Y%m%d)
  3. 최신 Paper 버전 확인:
    https://papermc.io/downloads 에서 최신 버전을 확인합니다.

  4. 새 JAR 파일 다운로드:

    cd ~/minecraft-server
    wget https://api.papermc.io/v2/projects/paper/versions/1.20.6/builds/320/downloads/paper-1.20.6-320.jar

    주의: URL은 최신 버전에 맞게 변경해야 합니다.

  5. start.sh 스크립트 업데이트:
    새 JAR 파일 이름으로 SERVER_JAR 변수를 업데이트합니다.

  6. 서버 재시작:

    ./start.sh
  7. 업데이트 확인:
    서버 콘솔에서 버전 정보를 확인합니다.

자동 업데이트 스크립트를 만들어 이 과정을 자동화할 수도 있습니다. 다음은 간단한 예시입니다:

#!/bin/bash

# 현재 디렉토리를 서버 디렉토리로 변경
cd ~/minecraft-server

# 현재 버전 정보 저장
CURRENT_VERSION=$(ls paper-*.jar | sed 's/paper-//' | sed 's/.jar//')

# 최신 버전 정보 가져오기
LATEST_VERSION=$(curl -s https://papermc.io/api/v2/projects/paper | jq -r '.versions[-1]')
LATEST_BUILD=$(curl -s https://papermc.io/api/v2/projects/paper/versions/${LATEST_VERSION} | jq -r '.builds[-1]')

# 버전 비교
if [ "$CURRENT_VERSION" != "${LATEST_VERSION}-${LATEST_BUILD}" ]; then
    echo "새 버전이 있습니다. 업데이트를 시작합니다."

    # 서버 중지
    screen -S minecraft -X stuff "say 서버가 5초 후 업데이트를 위해 재시작됩니다.\n"
    sleep 5
    screen -S minecraft -X stuff "stop\n"
    sleep 10

    # 백업 생성
    cp -r ~/minecraft-server ~/minecraft-server-backup-$(date +%Y%m%d)

    # 새 버전 다운로드
    wget https://papermc.io/api/v2/projects/paper/versions/${LATEST_VERSION}/builds/${LATEST_BUILD}/downloads/paper-${LATEST_VERSION}-${LATEST_BUILD}.jar

    # start.sh 업데이트
    sed -i "s/SERVER_JAR=\"paper-.*\.jar\"/SERVER_JAR=\"paper-${LATEST_VERSION}-${LATEST_BUILD}.jar\"/" start.sh

    # 서버 재시작
    ./start.sh

    echo "업데이트가 완료되었습니다."
else
    echo "서버가 이미 최신 버전입니다."
fi

이 스크립트를 update.sh로 저장하고 실행 권한을 부여한 후, cron job으로 정기적으로 실행되도록 설정할 수 있습니다.

8. 서버 유지보수 및 백업

정기적인 유지보수와 백업은 서버의 안정성과 데이터 보호를 위해 중요합니다.

  1. 정기 백업:
    다음은 간단한 백업 스크립트입니다.

    #!/bin/bash
    
    # 백업 디렉토리 설정
    BACKUP_DIR="/home/ubuntu/minecraft-backups"
    SERVER_DIR="/home/ubuntu/minecraft-server"
    BACKUP_NAME="minecraft-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
    
    # 백업 디렉토리가 없으면 생성
    mkdir -p $BACKUP_DIR
    
    # 서버에 백업 시작 메시지 전송
    screen -S minecraft -X stuff "say 백업을 시작합니다. 잠시 동안 지연이 발생할 수 있습니다.\n"
    
    # 월드 저장 및 오토세이브 비활성화
    screen -S minecraft -X stuff "save-all\n"
    screen -S minecraft -X stuff "save-off\n"
    
    # 백업 생성
    tar -czf $BACKUP_DIR/$BACKUP_NAME -C $SERVER_DIR world world_nether world_the_end
    
    # 오토세이브 다시 활성화
    screen -S minecraft -X stuff "save-on\n"
    
    # 오래된 백업 삭제 (30일 이상된 백업)
    find $BACKUP_DIR -name "minecraft-backup-*.tar.gz" -mtime +30 -delete
    
    # 서버에 백업 완료 메시지 전송
    screen -S minecraft -X stuff "say 백업이 완료되었습니다.\n"
    
    echo "백업이 완료되었습니다: $BACKUP_NAME"

    이 스크립트를 backup.sh로 저장하고 실행 권한을 부여합니다:

    chmod +x backup.sh

    그리고 crontab에 등록하여 정기적으로 실행되도록 설정할 수 있습니다:

    crontab -e

    다음 줄을 추가하여 매일 새벽 4시에 백업을 실행하도록 설정합니다:

    0 4 * * * /home/ubuntu/minecraft-server/backup.sh
  2. 로그 관리:
    마인크래프트 서버는 많은 로그를 생성합니다. 이를 관리하기 위해 logrotate를 사용할 수 있습니다.

    /etc/logrotate.d/minecraft 파일을 생성하고 다음 내용을 추가합니다:

    /home/ubuntu/minecraft-server/logs/*.log {
       daily
       rotate 7
       compress
       missingok
       notifempty
       create 644 ubuntu ubuntu
    }

    이 설정은 로그 파일을 일일 단위로 압축하고 7일간 보관합니다.

  3. 플러그인 관리:
    플러그인은 주기적으로 업데이트해야 합니다. 다음은 플러그인 업데이트를 위한 간단한 스크립트입니다:

    #!/bin/bash
    
    SERVER_DIR="/home/ubuntu/minecraft-server"
    PLUGINS_DIR="$SERVER_DIR/plugins"
    
    # 서버 중지
    screen -S minecraft -X stuff "say 서버가 플러그인 업데이트를 위해 5초 후 재시작됩니다.\n"
    sleep 5
    screen -S minecraft -X stuff "stop\n"
    sleep 10
    
    # 플러그인 디렉토리로 이동
    cd $PLUGINS_DIR
    
    # 각 플러그인에 대해
    for plugin in *.jar; do
       # 플러그인 이름 추출
       name=$(echo $plugin | sed 's/-.*//')
    
       # Spigot 사이트에서 최신 버전 다운로드 (예시 URL)
       wget -O "$name-new.jar" "https://api.spigotmc.org/v2/plugins/$name/download"
    
       # 새 버전이 성공적으로 다운로드되었다면 교체
       if [ -f "$name-new.jar" ]; then
           mv "$name-new.jar" "$plugin"
           echo "$name 플러그인이 업데이트되었습니다."
       else
           echo "$name 플러그인 업데이트에 실패했습니다."
       fi
    done
    
    # 서버 재시작
    cd $SERVER_DIR
    ./start.sh
    
    echo "플러그인 업데이트가 완료되었습니다."

    이 스크립트는 예시일 뿐이며, 실제로는 각 플러그인의 공식 다운로드 URL을 사용해야 합니다.

  4. 성능 모니터링:
    서버의 성능을 모니터링하기 위해 다음과 같은 도구들을 사용할 수 있습니다:

    • htop: 시스템 리소스 사용량 모니터링
    • nethogs: 네트워크 사용량 모니터링
    • iotop: 디스크 I/O 모니터링

    이들을 설치하려면:

    sudo apt install htop nethogs iotop
  5. 정기적인 서버 재시작:
    서버를 정기적으로 재시작하면 메모리 누수 등의 문제를 예방할 수 있습니다. 다음과 같은 스크립트를 사용할 수 있습니다:

    #!/bin/bash
    
    # 서버에 재시작 예고 메시지 전송
    screen -S minecraft -X stuff "say 서버가 5분 후 정기 재시작됩니다.\n"
    sleep 240
    screen -S minecraft -X stuff "say 서버가 1분 후 재시작됩니다.\n"
    sleep 50
    screen -S minecraft -X stuff "say 서버가 10초 후 재시작됩니다.\n"
    sleep 10
    
    # 서버 중지
    screen -S minecraft -X stuff "stop\n"
    sleep 30
    
    # 서버 재시작
    /home/ubuntu/minecraft-server/start.sh

    이 스크립트를 restart.sh로 저장하고 crontab에 등록하여 매일 새벽 3시에 실행되도록 설정할 수 있습니다:

    0 3 * * * /home/ubuntu/minecraft-server/restart.sh
  6. 디스크 공간 관리:
    서버의 디스크 공간을 정기적으로 확인하고 관리해야 합니다. 다음 명령어로 디스크 사용량을 확인할 수 있습니다:

    df -h

    불필요한 파일을 정리하기 위한 스크립트:

    #!/bin/bash
    
    SERVER_DIR="/home/ubuntu/minecraft-server"
    
    # 오래된 로그 파일 삭제 (30일 이상)
    find $SERVER_DIR/logs -name "*.log.*" -mtime +30 -delete
    
    # 오래된 크래시 리포트 삭제 (30일 이상)
    find $SERVER_DIR/crash-reports -name "*.txt" -mtime +30 -delete
    
    # 플레이어 데이터 정리 (6개월 동안 접속하지 않은 플레이어)
    find $SERVER_DIR/world/playerdata -name "*.dat" -mtime +180 -delete
    
    echo "서버 정리가 완료되었습니다."

이러한 유지보수 작업들을 정기적으로 수행하면 서버의 안정성과 성능을 유지할 수 있습니다. 각 스크립트와 설정은 서버의 특성과 필요에 따라 조정해야 합니다.

9. 문제 해결 및 로깅

마인크래프트 서버를 운영하다 보면 다양한 문제에 직면할 수 있습니다. 효과적인 문제 해결을 위해서는 로그를 잘 활용해야 합니다.

  1. 로그 위치:

    • 서버 로그: /home/ubuntu/minecraft-server/logs/latest.log
    • 크래시 리포트: /home/ubuntu/minecraft-server/crash-reports/
  2. 일반적인 문제와 해결 방법:

    a) 서버가 시작되지 않는 경우:

    • 로그 파일을 확인하여 오류 메시지를 찾습니다.
    • Java 버전이 올바른지 확인합니다.
    • 서버 JAR 파일이 손상되지 않았는지 확인합니다.

    b) 서버 랙(지연):

    • 서버의 리소스 사용량을 확인합니다 (CPU, RAM, 디스크 I/O).
    • 플레이어 수와 서버 설정이 하드웨어 사양에 적합한지 확인합니다.
    • 불필요한 플러그인을 제거하거나 비활성화합니다.

    c) 플러그인 충돌:

    • 최근에 추가하거나 업데이트한 플러그인을 비활성화하고 문제가 해결되는지 확인합니다.
    • 플러그인 로그를 확인하여 오류 메시지를 찾습니다.

    d) 월드 손상:

    • 백업에서 월드를 복원합니다.
    • MCEdit와 같은 도구를 사용하여 손상된 청크를 제거합니다.
  3. 로그 분석 도구:
    로그를 더 쉽게 분석하기 위해 다음과 같은 도구를 사용할 수 있습니다:

    • Graylog: 중앙 집중식 로그 관리 시스템
    • ELK Stack (Elasticsearch, Logstash, Kibana): 로그 수집, 분석, 시각화 도구
  4. 디버그 모드:
    문제 해결을 위해 서버를 디버그 모드로 실행할 수 있습니다. start.sh 스크립트에 다음 JVM 인자를 추가합니다:

    -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

    그리고 원격 디버깅을 위해 포트 5005를 개방합니다.

  5. 프로파일링:
    서버 성능 문제를 분석하기 위해 프로파일링 도구를 사용할 수 있습니다. Paper에는 내장 프로파일러가 있습니다:

    /timings on

    일정 시간 후:

    /timings paste

    이 명령어는 타이밍 리포트 URL을 제공합니다.

  6. 로그 레벨 조정:
    로깅 수준을 조정하여 더 자세한 정보를 얻을 수 있습니다. server.properties 파일에서:

    debug=true

    하지만 이 설정은 로그 파일 크기를 급격히 증가시킬 수 있으므로 주의해야 합니다.

  7. 주기적인 건강 체크:
    서버의 건강 상태를 주기적으로 확인하는 스크립트를 만들 수 있습니다:

    #!/bin/bash
    
    SERVER_DIR="/home/ubuntu/minecraft-server"
    LOG_FILE="$SERVER_DIR/logs/latest.log"
    ALERT_EMAIL="your@email.com"
    
    # 서버 프로세스 확인
    if ! pgrep -f "java.*paper-1.20.6-320.jar" > /dev/null; then
       echo "서버가 실행되고 있지 않습니다. 재시작합니다."
       $SERVER_DIR/start.sh
       echo "서버가 중단되어 재시작되었습니다." | mail -s "Minecraft 서버 알림" $ALERT_EMAIL
    fi
    
    # 최근 로그에서 오류 확인
    if grep -i "error\|exception\|crash" $LOG_FILE | tail -n 50 > /tmp/mc_errors.log; then
       echo "서버 로그에서 오류가 발견되었습니다:"
       cat /tmp/mc_errors.log
       cat /tmp/mc_errors.log | mail -s "Minecraft 서버 오류 알림" $ALERT_EMAIL
    fi
    
    # 디스크 공간 확인
    DISK_USAGE=$(df -h | awk '$NF=="/"{printf "%s", $5}' | sed 's/%//')
    if [ $DISK_USAGE -ge 90 ]; then
       echo "디스크 사용량이 90%를 초과했습니다. 현재 사용량: $DISK_USAGE%" | mail -s "Minecraft 서버 디스크 경고" $ALERT_EMAIL
    fi
    
    echo "서버 건강 체크가 완료되었습니다."

    이 스크립트를 cron job으로 설정하여 정기적으로 실행할 수 있습니다.

효과적인 문제 해결을 위해서는 로그를 주의 깊게 모니터링하고, 서버의 동작을 잘 이해하며, 문제가 발생했을 때 체계적으로 접근하는 것이 중요합니다.

10. 보안 설정

마인크래프트 서버를 안전하게 운영하기 위해서는 적절한 보안 설정이 필수적입니다. 다음은 서버 보안을 강화하기 위한 몇 가지 방법입니다:

  1. SSH 보안 강화:
    a) 루트 로그인 비활성화:
    /etc/ssh/sshd_config 파일에서:

      PermitRootLogin no

    b) 키 기반 인증만 허용:

      PasswordAuthentication no

    c) SSH 포트 변경:

      Port 2222  # 22 대신 다른 포트 번호 사용

    변경 후 SSH 서비스 재시작:

    sudo systemctl restart sshd
  2. 방화벽 설정:
    UFW(Uncomplicated Firewall)를 사용하여 필요한 포트만 개방:

    sudo ufw default deny incoming
    sudo ufw default allow outgoing
    sudo ufw allow 2222/tcp  # SSH 포트
    sudo ufw allow 25565/tcp  # 마인크래프트 서버 포트
    sudo ufw enable
  3. 정기적인 시스템 업데이트:

    sudo apt update
    sudo apt upgrade -y
  4. fail2ban 설치 및 구성:
    fail2ban은 반복적인 로그인 실패를 감지하고 해당 IP를 차단합니다.

    sudo apt install fail2ban
    sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
    sudo nano /etc/fail2ban/jail.local

    jail.local 파일에서 다음 설정을 추가 또는 수정:

    [sshd]
    enabled = true
    port = 2222
    filter = sshd
    logpath = /var/log/auth.log
    maxretry = 3
    bantime = 3600

    fail2ban 서비스 시작:

    sudo systemctl start fail2ban
    sudo systemctl enable fail2ban
  5. 마인크래프트 서버 보안:
    a) 화이트리스트 활성화:
    server.properties 파일에서:

      white-list=true

    그리고 허용된 플레이어만 추가:

      /whitelist add 

    b) 옵 권한 제한:
    ops.json 파일을 편집하여 옵 레벨을 제한합니다.

    c) 플러그인 보안:

    • 신뢰할 수 있는 소스에서만 플러그인을 다운로드합니다.
    • 정기적으로 플러그인을 업데이트합니다.
    • 사용하지 않는 플러그인은 제거합니다.

    d) RCON 비밀번호 설정:
    server.properties 파일에서:

      rcon.password=
  6. DDoS 보호:
    AWS Lightsail에서는 기본적인 DDoS 보호를 제공하지만, 추가적인 보호가 필요한 경우 다음과 같은 방법을 고려할 수 있습니다:

    • CloudFlare 등의 DDoS 보호 서비스 사용
    • 트래픽 제한 설정 (예: iptables 사용)
  7. 정기적인 보안 감사:
    다음과 같은 항목을 정기적으로 점검합니다:

    • 시스템 및 소프트웨어 업데이트 상태
    • 열린 포트 및 실행 중인 서비스
    • 사용자 계정 및 권한
    • 로그 파일 검토
  8. 백업 암호화:
    중요한 데이터와 백업 파일을 암호화하여 저장합니다:

    gpg -c backup.tar.gz

    이 명령은 백업 파일을 암호화합니다. 복호화할 때는:

    gpg backup.tar.gz.gpg
  9. SELinux 또는 AppArmor 설정:
    Ubuntu에서는 AppArmor를 사용하여 추가적인 보안 계층을 구성할 수 있습니다:

    sudo apt install apparmor-utils
    sudo aa-genprof java

    이후 마인크래프트 서버를 실행하고 필요한 권한을 설정합니다.

  10. 로그 모니터링 강화:
    로그 파일을 지속적으로 모니터링하고 의심스러운 활동을 감지하는 도구를 설정합니다. 예를 들어, logwatch를 사용할 수 있습니다:

    sudo apt install logwatch
    sudo logwatch --output mail --mailto your@email.com --detail high
  11. 네트워크 보안 강화:
    a) TCP Wrappers 설정:
    /etc/hosts.allow/etc/hosts.deny 파일을 사용하여 접근을 제어합니다.

    b) Iptables 규칙 설정:

       sudo iptables -A INPUT -p tcp --dport 25565 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
       sudo iptables -A OUTPUT -p tcp --sport 25565 -m conntrack --ctstate ESTABLISHED -j ACCEPT

    c) 패킷 필터링 최적화:

       sudo sysctl -w net.ipv4.tcp_syncookies=1
       sudo sysctl -w net.ipv4.tcp_max_syn_backlog=2048
       sudo sysctl -w net.ipv4.tcp_synack_retries=2
       sudo sysctl -w net.ipv4.tcp_syn_retries=5
  12. 정기적인 취약점 스캔:
    OpenVAS나 Nessus 같은 도구를 사용하여 주기적으로 시스템의 취약점을 스캔합니다.

이러한 보안 설정들을 적용하면 마인크래프트 서버의 보안을 크게 향상시킬 수 있습니다. 하지만 보안은 지속적인 과정이므로, 항상 최신 보안 권고사항을 주시하고 시스템을 최신 상태로 유지하는 것이 중요합니다.

11. 성능 모니터링 및 튜닝

마인크래프트 서버의 성능을 최적화하고 유지하기 위해서는 지속적인 모니터링과 튜닝이 필요합니다. 다음은 이를 위한 방법들입니다:

  1. 시스템 리소스 모니터링:
    a) htop 사용:

      htop

    CPU, 메모리 사용량, 실행 중인 프로세스 등을 실시간으로 확인할 수 있습니다.

    b) vmstat 사용:

      vmstat 1

    1초 간격으로 시스템 활동을 모니터링합니다.

    c) iostat 사용:

      iostat -x 1

    디스크 I/O 통계를 모니터링합니다.

  2. 네트워크 모니터링:
    a) iftop 사용:

      sudo apt install iftop
      sudo iftop

    실시간 네트워크 트래픽을 모니터링합니다.

    b) netstat 사용:

      netstat -tuln

    열린 포트와 연결 상태를 확인합니다.

  3. Java 힙 메모리 모니터링:
    jstat 도구를 사용하여 Java 힙 메모리 사용량을 모니터링할 수 있습니다:

    jstat -gcutil  1000

    여기서 는 Java 프로세스 ID입니다.

  4. 마인크래프트 서버 내부 성능 모니터링:
    a) /tps 명령어:
    서버의 TPS(Ticks Per Second)를 확인합니다. 20이 이상적입니다.

    b) /timings 명령어:
    서버 내부 작업의 타이밍을 분석합니다.

  5. 성능 튜닝:
    a) JVM 튜닝:
    start.sh 스크립트의 JVM 인자를 최적화합니다. 예를 들어:

      java -Xms4G -Xmx4G -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 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true -jar paper.jar nogui

    b) 서버 설정 최적화:
    server.properties, spigot.yml, paper.yml 파일의 설정을 조정합니다.

    c) 월드 최적화:

    • 렌더 거리 제한
    • 몹 스폰 제한
    • 청크 로딩 최적화

    d) 플러그인 최적화:

    • 불필요한 플러그인 제거
    • 리소스를 많이 사용하는 플러그인 식별 및 대체
  6. 성능 모니터링 대시보드 구축:
    Grafana, Prometheus, InfluxDB 등을 사용하여 실시간 성능 모니터링 대시보드를 구축할 수 있습니다.

    a) InfluxDB 설치:

      wget https://dl.influxdata.com/influxdb/releases/influxdb_1.8.10_amd64.deb
      sudo dpkg -i influxdb_1.8.10_amd64.deb
      sudo systemctl start influxdb

    b) Grafana 설치:

      sudo apt-get install -y apt-transport-https
      sudo apt-get install -y software-properties-common wget
      wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
      echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
      sudo apt-get update
      sudo apt-get install grafana
      sudo systemctl start grafana-server

    c) Prometheus 설치:

      wget https://github.com/prometheus/prometheus/releases/download/v2.30.3/prometheus-2.30.3.linux-amd64.tar.gz
      tar xvfz prometheus-2.30.3.linux-amd64.tar.gz
      cd prometheus-2.30.3.linux-amd64/
      ./prometheus

    이후 Grafana에서 InfluxDB와 Prometheus를 데이터 소스로 추가하고, 대시보드를 구성합니다.

  7. 자동화된 성능 리포트:
    다음과 같은 스크립트를 사용하여 정기적으로 성능 리포트를 생성할 수 있습니다:

    #!/bin/bash
    
    # 시스템 정보 수집
    echo "시스템 정보:" > performance_report.txt
    echo "-------------" >> performance_report.txt
    echo "CPU 사용량:" >> performance_report.txt
    top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1"%"}' >> performance_report.txt
    echo "메모리 사용량:" >> performance_report.txt
    free -m | awk 'NR==2{printf "%.2f%%\n", $3*100/$2 }' >> performance_report.txt
    echo "디스크 사용량:" >> performance_report.txt
    df -h | awk '$NF=="/"{printf "%s\n", $5}' >> performance_report.txt
    
    # 마인크래프트 서버 정보 수집
    echo "마인크래프트 서버 정보:" >> performance_report.txt
    echo "-------------------------" >> performance_report.txt
    echo "현재 접속자 수:" >> performance_report.txt
    screen -S minecraft -X stuff "list^M"
    sleep 1
    tail -n 1 /home/ubuntu/minecraft-server/logs/latest.log | cut -d ' ' -f7- >> performance_report.txt
    echo "TPS:" >> performance_report.txt
    screen -S minecraft -X stuff "tps^M"
    sleep 1
    tail -n 1 /home/ubuntu/minecraft-server/logs/latest.log | cut -d ' ' -f7- >> performance_report.txt
    
    # 리포트 전송
    mail -s "마인크래프트 서버 성능 리포트" your@email.com < performance_report.txt

    이 스크립트를 cron job으로 설정하여 정기적으로 실행할 수 있습니다.

  8. 성능 벤치마킹:
    서버의 성능을 객관적으로 평가하기 위해 벤치마킹 도구를 사용할 수 있습니다. 예를 들어, MinecraftBenchmark 플러그인을 사용하여 서버의 성능을 측정할 수 있습니다.

  9. 로그 분석:
    서버 로그를 정기적으로 분석하여 성능 문제의 원인을 파악합니다. 예를 들어:

    grep "Can't keep up!" /home/ubuntu/minecraft-server/logs/latest.log | wc -l

    이 명령은 서버가 "따라잡지 못하는" 횟수를 계산합니다.

  10. 네트워크 레이턴시 모니터링:
    ping 명령을 사용하여 서버와 클라이언트 간의 네트워크 레이턴시를 모니터링할 수 있습니다:

    ping -c 100 your_server_ip

    이 명령은 100개의 패킷을 보내고 평균 응답 시간을 측정합니다.

  11. 프로파일링 도구 사용:
    Java Flight Recorder(JFR)와 같은 프로파일링 도구를 사용하여 서버의 성능을 심층 분석할 수 있습니다:

    java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=duration=60s,filename=myrecording.jfr -jar paper.jar nogui

    이 명령은 60초 동안 서버를 프로파일링하고 결과를 myrecording.jfr 파일에 저장합니다.

  12. 서버 워밍업:
    서버 시작 후 일정 시간 동안 성능이 안정화되도록 "워밍업" 기간을 가집니다. 이를 위한 스크립트 예시:

    #!/bin/bash
    echo "서버 워밍업 시작..."
    ./start.sh &
    sleep 300  # 5분 대기
    echo "워밍업 완료. 서버가 준비되었습니다."
  13. 청크 프리로딩:
    서버 시작 시 자주 사용되는 청크를 미리 로드하여 성능을 개선할 수 있습니다. Paper에서는 이를 위한 명령어를 제공합니다:

    /paper chunk-task queue     load
  14. 가비지 컬렉션 모니터링:
    GC 로그를 활성화하고 분석하여 메모리 사용 패턴을 이해할 수 있습니다:

    java -Xms4G -Xmx4G -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 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintGCCause -Xloggc:gc.log -jar paper.jar nogui
  15. 플러그인 성능 분석:
    플러그인의 성능 영향을 분석하기 위해 Plugin Metrics나 Spark와 같은 도구를 사용할 수 있습니다.

  16. 시스템 튜닝:

    • 디스크 I/O 최적화: noatime 옵션 사용
      sudo mount -o remount,noatime /
    • 스왑 사용 최소화:
      echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf
      sudo sysctl -p
  17. 주기적인 성능 테스트:
    서버에 부하를 주는 테스트 스크립트를 작성하여 주기적으로 실행합니다. 예를 들어:

    import socket
    import time
    
    def test_server(host, port, duration):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((host, port))
        start_time = time.time()
        while time.time() - start_time < duration:
            sock.send(b'\xFE\x01')
            response = sock.recv(1024)
            time.sleep(1)
        sock.close()
    
    test_server('your_server_ip', 25565, 300)  # 5분 동안 테스트
  18. 커스텀 모니터링 스크립트:
    서버의 특정 지표를 모니터링하는 커스텀 스크립트를 작성할 수 있습니다:

    #!/bin/bash
    while true; do
        players=$(screen -S minecraft -X stuff "list^M" && sleep 1 && tail -n 1 /home/ubuntu/minecraft-server/logs/latest.log | cut -d ' ' -f7-)
        tps=$(screen -S minecraft -X stuff "tps^M" && sleep 1 && tail -n 1 /home/ubuntu/minecraft-server/logs/latest.log | cut -d ' ' -f7-)
        cpu=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1"%"}')
        mem=$(free -m | awk 'NR==2{printf "%.2f%%", $3*100/$2 }')
        echo "$(date), Players: $players, TPS: $tps, CPU: $cpu, MEM: $mem" >> server_stats.log
        sleep 60
    done
  19. 자동화된 성능 최적화:
    서버 성능에 따라 자동으로 설정을 조정하는 스크립트를 만들 수 있습니다:

    #!/bin/bash
    while true; do
        tps=$(screen -S minecraft -X stuff "tps^M" && sleep 1 && tail -n 1 /home/ubuntu/minecraft-server/logs/latest.log | cut -d ' ' -f7- | cut -d ',' -f1)
        if (( $(echo "$tps < 18" | bc -l) )); then
            screen -S minecraft -X stuff "gamerule randomTickSpeed 1^M"
            echo "TPS가 낮아 randomTickSpeed를 줄였습니다."
        else
            screen -S minecraft -X stuff "gamerule randomTickSpeed 3^M"
            echo "TPS가 정상이어서 randomTickSpeed를 기본값으로 설정했습니다."
        fi
        sleep 300
    done
  20. 성능 데이터 시각화:
    수집한 성능 데이터를 시각화하여 장기적인 트렌드를 분석할 수 있습니다. 예를 들어, Python의 matplotlib 라이브러리를 사용할 수 있습니다:

    import matplotlib.pyplot as plt
    import pandas as pd
    
    # 로그 파일에서 데이터 읽기
    df = pd.read_csv('server_stats.log', parse_dates=[0], header=None, names=['timestamp', 'players', 'tps', 'cpu', 'mem'])
    
    # 그래프 그리기
    plt.figure(figsize=(12, 6))
    plt.plot(df['timestamp'], df['tps'], label='TPS')
    plt.plot(df['timestamp'], df['players'], label='Players')
    plt.xlabel('Time')
    plt.ylabel('Value')
    plt.title('Server Performance Over Time')
    plt.legend()
    plt.savefig('performance_graph.png')

이러한 도구와 기법들을 조합하여 사용하면 마인크래프트 서버의 성능을 지속적으로 모니터링하고 최적화할 수 있습니다. 서버의 특성과 사용 패턴에 따라 적절한 방법을 선택하고 커스터마이즈하는 것이 중요합니다.

12. 플러그인 관리

마인크래프트 Paper 서버의 큰 장점 중 하나는 다양한 플러그인을 사용하여 서버의 기능을 확장할 수 있다는 것입니다. 하지만 플러그인을 효과적으로 관리하는 것도 중요합니다. 다음은 플러그인 관리에 대한 상세한 가이드입니다:

  1. 플러그인 선택:

    • 신뢰할 수 있는 소스에서 플러그인을 다운로드합니다 (예: https://www.spigotmc.org/, https://dev.bukkit.org/)
    • 플러그인의 평판, 리뷰, 다운로드 수를 확인합니다.
    • 서버 버전과 호환되는지 확인합니다.
    • 플러그인의 성능 영향을 고려합니다.
  2. 플러그인 설치:

    cd ~/minecraft-server/plugins
    wget 

    서버를 재시작하거나 /reload confirm 명령어를 사용하여 플러그인을 로드합니다.

  3. 플러그인 구성:
    대부분의 플러그인은 config.yml 파일을 통해 설정할 수 있습니다:

    cd ~/minecraft-server/plugins/
    nano config.yml
  4. 플러그인 업데이트:
    정기적으로 플러그인을 업데이트하여 버그 수정과 새로운 기능을 적용합니다:

    cd ~/minecraft-server/plugins
    rm .jar
    wget 

    서버를 재시작하여 새 버전을 로드합니다.

  5. 플러그인 비활성화:
    플러그인을 완전히 제거하지 않고 일시적으로 비활성화하려면:

    mv .jar .jar.disabled

    서버를 재시작하면 해당 플러그인이 로드되지 않습니다.

  6. 플러그인 종속성 관리:
    일부 플러그인은 다른 플러그인에 의존할 수 있습니다. 종속성을 확인하고 필요한 플러그인을 모두 설치합니다.

  7. 플러그인 충돌 해결:
    플러그인 간 충돌이 발생할 경우:

    • 서버 로그를 확인하여 오류 메시지를 분석합니다.
    • 플러그인을 하나씩 비활성화하며 문제의 원인을 찾습니다.
    • 플러그인 개발자에게 문의하거나 대체 플러그인을 찾습니다.
  8. 플러그인 성능 모니터링:

    • Spark 플러그인을 사용하여 각 플러그인의 성능 영향을 분석합니다.
    • 과도한 리소스를 사용하는 플러그인을 식별하고 최적화하거나 대체합니다.
  9. 플러그인 자동 업데이트:
    UpdaterPlus와 같은 플러그인을 사용하여 플러그인 자동 업데이트를 구성할 수 있습니다.

  10. 플러그인 백업:
    플러그인과 설정 파일을 정기적으로 백업합니다:

    tar -czf plugins_backup_$(date +%Y%m%d).tar.gz ~/minecraft-server/plugins
  11. 플러그인 문서화:
    서버에 설치된 플러그인 목록과 각 플러그인의 용도, 설정을 문서화합니다:

    # 서버 플러그인 목록
    
    1. EssentialsX
       - 용도: 기본적인 서버 명령어 및 기능 제공
       - 버전: 2.19.0
       - 설정: /plugins/Essentials/config.yml
    
    2. WorldEdit
       - 용도: 월드 편집 도구
       - 버전: 7.2.8
       - 설정: /plugins/WorldEdit/config.yml
    
    ...
  12. 플러그인 권한 관리:
    LuckPerms와 같은 권한 관리 플러그인을 사용하여 플러그인 명령어에 대한 접근을 제어합니다.

  13. 개발 환경과 프로덕션 환경 분리:
    새로운 플러그인이나 설정을 테스트할 때는 별도의 테스트 서버를 사용합니다.

  14. 플러그인 API 활용:
    자주 사용하는 플러그인의 API를 학습하여 커스텀 스크립트나 플러그인을 개발할 수 있습니다.

  15. 커뮤니티 참여:
    플러그인 개발 커뮤니티에 참여하여 최신 트렌드와 모범 사례를 학습합니다. Reddit, Discord, 공식 마인크래프트 포럼 등을 활용할 수 있습니다.

  16. 플러그인 호환성 테스트:
    새로운 플러그인을 추가하기 전에 기존 플러그인과의 호환성을 테스트합니다. 테스트 서버에서 먼저 시도해 보는 것이 좋습니다.

  17. 플러그인 로드 순서 최적화:
    일부 플러그인은 로드 순서에 민감할 수 있습니다. 'server.properties' 파일에서 'plugin-priority' 설정을 사용하여 로드 순서를 조정할 수 있습니다.

  18. 플러그인 성능 프로파일링:
    TickProfiler나 Timings 플러그인을 사용하여 각 플러그인의 성능 영향을 상세히 분석합니다.

  19. 플러그인 설정 버전 관리:
    Git과 같은 버전 관리 시스템을 사용하여 플러그인 설정 파일의 변경 사항을 추적합니다.

    cd ~/minecraft-server
    git init
    git add plugins/*/config.yml
    git commit -m "Initial plugin configurations"
  20. 플러그인 설정 템플릿 생성:
    자주 사용하는 플러그인의 설정 템플릿을 만들어 새 서버 설정 시 시간을 절약합니다.

  21. 플러그인 사용 통계 수집:
    Plan과 같은 플러그인을 사용하여 서버와 플러그인 사용 통계를 수집하고 분석합니다.

  22. 플러그인 의존성 그래프 생성:
    플러그인 간의 의존성을 시각화하여 전체 구조를 이해하고 최적화합니다.

    import os
    import yaml
    import networkx as nx
    import matplotlib.pyplot as plt
    
    def get_dependencies(plugin_folder):
        dependencies = {}
        for plugin in os.listdir(plugin_folder):
            plugin_yml = os.path.join(plugin_folder, plugin, 'plugin.yml')
            if os.path.exists(plugin_yml):
                with open(plugin_yml, 'r') as f:
                    data = yaml.safe_load(f)
                    if 'depend' in data:
                        dependencies[plugin] = data['depend']
        return dependencies
    
    def create_dependency_graph(dependencies):
        G = nx.DiGraph()
        for plugin, deps in dependencies.items():
            G.add_node(plugin)
            for dep in deps:
                G.add_edge(plugin, dep)
        return G
    
    dependencies = get_dependencies('/path/to/plugins')
    G = create_dependency_graph(dependencies)
    nx.draw(G, with_labels=True)
    plt.savefig('plugin_dependencies.png')
  23. 플러그인 설정 검증:
    플러그인 설정 파일의 유효성을 자동으로 검사하는 스크립트를 작성합니다.

    import yaml
    import os
    
    def validate_config(config_path, schema):
        with open(config_path, 'r') as f:
            config = yaml.safe_load(f)
    
        for key, value_type in schema.items():
            if key not in config:
                print(f"Missing key: {key}")
            elif not isinstance(config[key], value_type):
                print(f"Invalid type for {key}: expected {value_type}, got {type(config[key])}")
    
    # 예시 스키마
    essentials_schema = {
        'spawn-on-join': bool,
        'default-stack-size': int,
        'max-nick-length': int,
    }
    
    validate_config('/path/to/plugins/Essentials/config.yml', essentials_schema)
  24. 플러그인 설정 마이그레이션:
    플러그인 업데이트 시 설정 파일 구조가 변경될 수 있습니다. 이를 자동으로 처리하는 마이그레이션 스크립트를 작성합니다.

  25. 플러그인 사용 가이드 작성:
    서버 관리자와 플레이어를 위한 각 플러그인의 사용 가이드를 작성하여 문서화합니다.

  26. 플러그인 개발 참여:
    필요한 기능이 없는 경우, 직접 플러그인을 개발하거나 기존 플러그인에 기여할 수 있습니다. Java와 Bukkit API에 대한 학습이 필요합니다.

  27. 플러그인 설정 동기화:
    여러 서버를 운영하는 경우, 플러그인 설정을 동기화하는 스크립트를 작성합니다.

    #!/bin/bash
    
    SOURCE_SERVER="/path/to/source/server"
    TARGET_SERVERS=("/path/to/target/server1" "/path/to/target/server2")
    
    for target in "${TARGET_SERVERS[@]}"; do
        rsync -avz --delete $SOURCE_SERVER/plugins/ $target/plugins/
        echo "Synchronized plugins to $target"
    done
  28. 플러그인 사용량 모니터링:
    각 플러그인의 사용 빈도와 중요도를 모니터링하여 불필요한 플러그인을 식별하고 제거합니다.

  29. 플러그인 설정 백업 및 복원:
    플러그인 설정을 쉽게 백업하고 복원할 수 있는 스크립트를 작성합니다.

    #!/bin/bash
    
    BACKUP_DIR="/path/to/backups"
    SERVER_DIR="/path/to/server"
    
    # 백업
    backup() {
        tar -czf $BACKUP_DIR/plugin_configs_$(date +%Y%m%d).tar.gz -C $SERVER_DIR plugins/*/config.yml
        echo "Backup created: $BACKUP_DIR/plugin_configs_$(date +%Y%m%d).tar.gz"
    }
    
    # 복원
    restore() {
        latest_backup=$(ls -t $BACKUP_DIR/plugin_configs_*.tar.gz | head -1)
        tar -xzf $latest_backup -C $SERVER_DIR
        echo "Restored configurations from $latest_backup"
    }
    
    case "$1" in
        backup)
            backup
            ;;
        restore)
            restore
            ;;
        *)
            echo "Usage: $0 {backup|restore}"
            exit 1
    esac
  30. 플러그인 충돌 해결 가이드:
    일반적인 플러그인 충돌 문제와 해결 방법에 대한 가이드를 작성하여 문서화합니다.

이러한 고급 기법들을 활용하면 마인크래프트 Paper 서버의 플러그인을 더욱 효과적으로 관리할 수 있습니다. 플러그인 관리는 지속적인 과정이므로, 서버의 요구사항 변화에 따라 계속해서 최적화하고 개선해 나가는 것이 중요합니다.

13. 커스텀 맵 및 게임모드

마인크래프트의 매력 중 하나는 다양한 맵과 게임모드를 만들어 플레이할 수 있다는 것입니다. Paper 서버에서 커스텀 맵과 게임모드를 구현하는 방법에 대해 자세히 알아보겠습니다.

  1. 커스텀 맵 제작:
    a) WorldEdit 사용:
    WorldEdit은 강력한 맵 편집 도구입니다.

      # WorldEdit 설치
      wget https://dev.bukkit.org/projects/worldedit/files/latest -O plugins/WorldEdit.jar

    주요 명령어:

    • //wand: 편집 도구 얻기
    • //set : 선택 영역을 특정 블록으로 채우기
    • //copy: 선택 영역 복사
    • //paste: 복사한 영역 붙여넣기

    b) VoxelSniper 사용:
    더 세밀한 지형 조작에 유용합니다.

      wget https://dev.bukkit.org/projects/voxelsniper/files/latest -O plugins/VoxelSniper.jar

    c) 외부 도구 활용:

    • MCEdit: 오프라인에서 맵 편집
    • World Painter: 큰 규모의 지형 생성
  2. 커스텀 구조물 생성:
    a) Structure Block 사용:

      /give @p minecraft:structure_block

    구조물을 저장하고 로드할 수 있습니다.

    b) 스키매틱 파일 사용:
    WorldEdit으로 구조물을 .schematic 파일로 저장하고 공유할 수 있습니다.

      //copy
      //schem save mystructure
  3. 커스텀 게임모드 구현:
    a) 스코어보드 활용:

      /scoreboard objectives add Kills playerKillCount
      /scoreboard objectives setdisplay sidebar Kills

    b) 커맨드 블록 사용:
    복잡한 게임 로직을 구현할 수 있습니다.

      /give @p minecraft:command_block

    c) 플러그인 개발:
    Java를 사용하여 커스텀 플러그인을 개발합니다.

      public class MyGameMode extends JavaPlugin {
          @Override
          public void onEnable() {
              getLogger().info("커스텀 게임모드가 활성화되었습니다!");
              this.getCommand("startgame").setExecutor(new StartGameCommand());
          }
      }
  4. 월드 관리:
    a) 다중 월드 설정:
    Multiverse-Core 플러그인을 사용합니다.

      wget https://dev.bukkit.org/projects/multiverse-core/files/latest -O plugins/Multiverse-Core.jar

    주요 명령어:

      /mv create  normal -t flat
      /mv tp 

    b) 월드 보더 설정:

      /worldborder set 1000
  5. 게임 규칙 설정:
    a) 기본 게임 규칙:

      /gamerule keepInventory true
      /gamerule doDaylightCycle false

    b) 커스텀 규칙 구현:
    플러그인을 통해 더 복잡한 규칙을 구현합니다.

  6. 이벤트 및 미니게임:
    a) 이벤트 스케줄러 사용:

      Bukkit.getScheduler().runTaskTimer(this, () -> {
          // 이벤트 로직
      }, 0L, 20L * 60); // 1분마다 실행

    b) 미니게임 플러그인 활용:
    MiniGames 또는 Arcade 플러그인을 사용하여 다양한 미니게임을 추가합니다.

  7. 커스텀 아이템 및 몹:
    a) 아이템 속성 수정:

      /give @p diamond_sword{display:{Name:'{"text":"초강력 검"}'},Enchantments:[{id:sharpness,lvl:10}]} 1

    b) 커스텀 몹 생성:
    MythicMobs 플러그인을 사용하여 커스텀 몹을 만듭니다.

  8. 파쿠르 맵 제작:
    a) 점프 패드:

      /setblock ~ ~ ~ slime_block

    b) 체크포인트 시스템:
    커맨드 블록을 사용하여 구현합니다.

  9. PvP 아레나 설정:
    a) 팀 설정:

      /team add Red
      /team add Blue
      /team join Red @p

    b) 킬 카운트 시스템:
    스코어보드를 활용합니다.

  10. 경제 시스템 구현:
    Vault 플러그인과 함께 사용할 수 있는 경제 플러그인을 설치합니다.

    wget https://dev.bukkit.org/projects/vault/files/latest -O plugins/Vault.jar
  11. 퀘스트 시스템:
    BetonQuest 플러그인을 사용하여 복잡한 퀘스트 라인을 만듭니다.

    wget https://dev.bukkit.org/projects/betonquest/files/latest -O plugins/BetonQuest.jar
  12. 커스텀 NPC 생성:
    Citizens 플러그인을 사용하여 상호작용 가능한 NPC를 만듭니다.

    wget https://dev.bukkit.org/projects/citizens/files/latest -O plugins/Citizens.jar
  13. 파티클 효과:

    player.getWorld().spawnParticle(Particle.FLAME, player.getLocation(), 50, 0.5, 0.5, 0.5, 0.1);

    이 코드는 플레이어 주변에 불꽃 파티클을 생성합니다.

  14. 사운드 효과:

    player.playSound(player.getLocation(), Sound.ENTITY_ENDER_DRAGON_GROWL, 1.0f, 1.0f);

    이 코드는 플레이어 위치에서 엔더 드래곤 소리를 재생합니다.

  15. 커스텀 인벤토리 GUI:

    Inventory gui = Bukkit.createInventory(null, 27, "커스텀 GUI");
    gui.setItem(13, new ItemStack(Material.DIAMOND));
    player.openInventory(gui);

    이 코드는 다이아몬드가 중앙에 있는 커스텀 GUI를 생성합니다.

  16. 시나리오 스크립팅:
    Skript 플러그인을 사용하여 복잡한 게임 시나리오를 쉽게 구현할 수 있습니다.

    wget https://github.com/SkriptLang/Skript/releases/download/2.6.3/Skript.jar -O plugins/Skript.jar

    Skript 예시:

    on right click on stone:
        set block to diamond ore
        send "다이아몬드를 발견했습니다!" to player
  17. 커스텀 생성기:

    public void spawnCustomMob(Location loc) {
        Zombie zombie = (Zombie) loc.getWorld().spawnEntity(loc, EntityType.ZOMBIE);
        zombie.setCustomName("슈퍼 좀비");
        zombie.setCustomNameVisible(true);
        zombie.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(40.0);
        zombie.setHealth(40.0);
    }

    이 코드는 체력이 강화된 커스텀 좀비를 생성합니다.

  18. 타이머 시스템:

    BukkitRunnable timer = new BukkitRunnable() {
        int time = 300;  // 5분
        @Override
        public void run() {
            if (time <= 0) {
                cancel();
                Bukkit.broadcastMessage("시간 종료!");
            } else {
                Bukkit.broadcastMessage("남은 시간: " + time + "초");
                time--;
            }
        }
    };
    timer.runTaskTimer(this, 0L, 20L);  // 1초마다 실행
  19. 커스텀 인챈트:

    @EventHandler
    public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
        if (event.getDamager() instanceof Player) {
            Player player = (Player) event.getDamager();
            ItemStack weapon = player.getInventory().getItemInMainHand();
            if (weapon.getItemMeta().getLore().contains("화염의 검")) {
                event.getEntity().setFireTicks(100);  // 5초간 불타게 함
            }
        }
    }

    이 코드는 "화염의 검" 로어를 가진 무기로 공격 시 대상을 불태웁니다.

  20. 커스텀 포탈:

    @EventHandler
    public void onPlayerMove(PlayerMoveEvent event) {
        if (event.getTo().getBlock().getType() == Material.END_PORTAL) {
            Player player = event.getPlayer();
            Location destination = new Location(player.getWorld(), 100, 64, 100);
            player.teleport(destination);
            player.sendMessage("신비한 힘에 의해 이동되었습니다!");
        }
    }

    이 코드는 엔드 포탈 블록을 밟으면 지정된 위치로 텔레포트됩니다.

  21. 동적 월드 생성:

    WorldCreator creator = new WorldCreator("NewWorld");
    creator.environment(World.Environment.NORMAL);
    creator.type(WorldType.NORMAL);
    creator.generateStructures(true);
    World newWorld = creator.createWorld();

    이 코드는 새로운 월드를 동적으로 생성합니다.

  22. 커스텀 레시피:

    NamespacedKey key = new NamespacedKey(this, "custom_item");
    ItemStack result = new ItemStack(Material.DIAMOND);
    ShapedRecipe recipe = new ShapedRecipe(key, result);
    recipe.shape("AAA", "BBB", "CCC");
    recipe.setIngredient('A', Material.IRON_INGOT);
    recipe.setIngredient('B', Material.GOLD_INGOT);
    recipe.setIngredient('C', Material.EMERALD);
    Bukkit.addRecipe(recipe);

    이 코드는 철괴, 금괴, 에메랄드를 사용하여 다이아몬드를 만드는 커스텀 레시피를 추가합니다.

  23. 날씨 제어:

    public void setCustomWeather(World world, boolean storm, int duration) {
        world.setStorm(storm);
        world.setWeatherDuration(duration);
        if (storm) {
            world.setThundering(true);
            world.setThunderDuration(duration);
        }
    }

    이 메서드를 사용하여 특정 월드의 날씨를 제어할 수 있습니다.

  24. 플레이어 스킬 시스템:

    Map cooldowns = new HashMap<>();
    
    @EventHandler
    public void onPlayerInteract(PlayerInteractEvent event) {
        Player player = event.getPlayer();
        if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
            if (player.getInventory().getItemInMainHand().getType() == Material.BLAZE_ROD) {
                if (cooldowns.containsKey(player.getUniqueId())) {
                    long secondsLeft = ((cooldowns.get(player.getUniqueId()) / 1000) + 10) - (System.currentTimeMillis() / 1000);
                    if (secondsLeft > 0) {
                        player.sendMessage("스킬 쿨다운: " + secondsLeft + "초");
                        return;
                    }
                }
                player.getWorld().strikeLightning(player.getTargetBlock(null, 50).getLocation());
                cooldowns.put(player.getUniqueId(), System.currentTimeMillis());
            }
        }
    }

    이 코드는 화염 막대를 들고 우클릭하면 10초 쿨다운으로 번개를 소환하는 스킬을 구현합니다.

  25. 동적 텍스처 변경:
    리소스팩과 함께 사용하여 게임 내 아이템의 텍스처를 동적으로 변경할 수 있습니다.

    ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
    ItemMeta meta = item.getItemMeta();
    meta.setCustomModelData(1001);  // 리소스팩에서 정의한 커스텀 모델 데이터
    item.setItemMeta(meta);
    player.getInventory().addItem(item);
  26. 이벤트 기반 스토리텔링:

    int storyProgress = 0;
    
    @EventHandler
    public void onPlayerMove(PlayerMoveEvent event) {
        Player player = event.getPlayer();
        Location loc = player.getLocation();
        if (storyProgress == 0 && loc.getBlockX() == 100 && loc.getBlockZ() == 100) {
            player.sendMessage("신비한 기운이 느껴집니다...");
            storyProgress = 1;
        } else if (storyProgress == 1 && loc.getBlockX() == 200 && loc.getBlockZ() == 200) {
            player.sendMessage("고대의 유적을 발견했습니다!");
            storyProgress = 2;
        }
    }

    이 코드는 플레이어의 위치에 따라 스토리를 진행합니다.

  27. 동적 난이도 조절:

    @EventHandler
    public void onEntitySpawn(EntitySpawnEvent event) {
        if (event.getEntity() instanceof Monster) {
            Monster monster = (Monster) event.getEntity();
            int playerCount = Bukkit.getOnlinePlayers().size();
            double healthMultiplier = 1 + (playerCount * 0.1);  // 플레이어 수에 따라 체력 증가
            monster.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(monster.getHealth() * healthMultiplier);
            monster.setHealth(monster.getHealth() * healthMultiplier);
        }
    }

    이 코드는 온라인 플레이어 수에 따라 몬스터의 체력을 동적으로 조절합니다.

이러한 기능들을 조합하고 확장하여 독특하고 흥미로운 커스텀 맵과 게임모드를 만들 수 있습니다. 플레이어들의 피드백을 받아 지속적으로 개선하고, 새로운 아이디어를 실험해보는 것이 중요합니다. 또한, 서버의 성능을 고려하여 너무 복잡한 시스템은 점진적으로 도입하는 것이 좋습니다.

14. 멀티월드 설정

마인크래프트 서버에서 여러 개의 월드를 관리하는 것은 다양한 게임 경험을 제공하는 데 매우 유용합니다. 여기서는 Paper 서버에서 멀티월드를 설정하고 관리하는 방법에 대해 자세히 알아보겠습니다.

  1. Multiverse-Core 플러그인 설치:
    멀티월드 관리를 위해 가장 널리 사용되는 플러그인은 Multiverse-Core입니다.

    cd ~/minecraft-server/plugins
    wget https://dev.bukkit.org/projects/multiverse-core/files/latest -O Multiverse-Core.jar

    서버를 재시작하여 플러그인을 로드합니다.

  2. 기본 Multiverse 명령어:

    • 월드 생성: /mv create <world_name> <world_type>
    • 월드 로드: /mv load <world_name>
    • 월드 언로드: /mv unload <world_name>
    • 월드 삭제: /mv delete <world_name>
    • 월드 목록: /mv list
    • 월드 정보: /mv info <world_name>
    • 월드 이동: /mv tp <world_name>
  3. 다양한 월드 유형 생성:

    /mv create normal_world normal
    /mv create nether_world nether
    /mv create end_world end
    /mv create flat_world normal -t flat
  4. 월드별 게임 규칙 설정:

    /mv gamerule   

    예: /mv gamerule pvp_world pvp true

  5. 월드 포탈 생성:
    Multiverse-Portals 플러그인을 추가로 설치합니다.

    wget https://dev.bukkit.org/projects/multiverse-portals/files/latest -O Multiverse-Portals.jar

    포탈 생성:

    /mvp create 
    /mvp set dest  
  6. 월드 접근 권한 설정:
    Multiverse-Core의 내장 권한 시스템을 사용합니다.

    /mv modify set -p  
  7. 커스텀 월드 생성기 사용:
    월드 생성 시 커스텀 생성기를 지정할 수 있습니다.

    /mv create custom_world normal -g YourCustomGenerator
  8. 월드 백업 및 복원:

    # 백업
    tar -czf world_backup.tar.gz /path/to/world
    
    # 복원
    tar -xzf world_backup.tar.gz -C /path/to/server
    /mv load 
  9. 월드 가져오기:
    외부에서 만든 월드를 서버에 추가할 수 있습니다.

    # 월드 파일을 서버 디렉토리로 복사
    cp -r /path/to/external_world /path/to/server/
    
    # Multiverse에 월드 추가
    /mv import external_world normal
  10. 월드별 인벤토리:
    Multiverse-Inventories 플러그인을 사용하여 월드별로 별도의 인벤토리를 관리할 수 있습니다.

    wget https://dev.bukkit.org/projects/multiverse-inventories/files/latest -O Multiverse-Inventories.jar
  11. 월드 리젠:
    특정 구역만 리젠하려면 WorldEdit과 함께 사용할 수 있습니다.

    //sel
    //regen

    전체 월드를 리젠하려면:

    /mv regen 
  12. 월드 시간 및 날씨 관리:
    각 월드의 시간과 날씨를 독립적으로 관리할 수 있습니다.

    /mv modify set time  
  13. 월드 스폰 위치 설정:

    /mv set spawn

    현재 플레이어의 위치를 해당 월드의 스폰 포인트로 설정합니다.

  14. 월드 경계 설정:

    /mv modify set border  
  15. 월드 별 채팅 설정:
    Multiverse-ChatManager 플러그인을 사용하여 월드별로 채팅을 분리할 수 있습니다.

    wget https://dev.bukkit.org/projects/multiverse-chatmanager/files/latest -O Multiverse-ChatManager.jar
  16. 월드 별 경제 시스템:
    Vault와 함께 사용하여 월드별로 다른 경제 시스템을 구현할 수 있습니다.

  17. 월드 간 아이템 이동 제한:

    /mvim no   
  18. 월드 그룹 관리:
    여러 월드를 그룹으로 관리할 수 있습니다.

    /mvg create 
    /mvg addworld  
  19. 월드 별 몹 스폰 설정:

    /mv modify set spawning  
    /mv modify set animals  
    /mv modify set monsters  
  20. 월드 복사:
    기존 월드를 복사하여 새로운 월드를 만들 수 있습니다.

    /mv clone  
  21. 월드 별 게임모드 설정:

    /mv modify set gamemode  
  22. 월드 로드 자동화:
    서버 시작 시 자동으로 월드를 로드하도록 설정할 수 있습니다.
    config.yml 파일에서:

    autoload: true
  23. 월드 별 난이도 설정:

    /mv modify set difficulty  
  24. 월드 간 텔레포트 쿨다운:

    /mv modify set portalcooldown  
  25. 월드 별 PvP 설정:

    /mv modify set pvp  
  26. 월드 별 허기 설정:

    /mv modify set hunger  
  27. 월드 프리픽스 설정:
    채팅에서 월드 이름을 표시할 때 사용할 프리픽스를 설정합니다.

    /mv modify set prefix  
  28. 월드 별 커스텀 스폰 아이템:
    새로운 플레이어가 특정 월드에 처음 입장할 때 받을 아이템을 설정합니다.

    /mv modify set firstspawnitem  
  29. 월드 별 환경 설정:
    각 월드의 환경(일반, 네더, 엔드)을 변경할 수 있습니다.

    /mv modify set environment  
  30. 월드 별 커스텀 생성기 옵션:
    월드 생성 시 추가적인 옵션을 설정할 수 있습니다.

    /mv create  normal -g TerrainControl:TC_MAIN
  31. 월드 별 명령어 차단:
    특정 월드에서 특정 명령어를 사용하지 못하도록 설정할 수 있습니다.

    /mv block  
  32. 월드 간 이동 시 이펙트:
    플레이어가 월드 간 이동할 때 특별한 효과를 줄 수 있습니다.

    @EventHandler
    public void onPlayerChangedWorld(PlayerChangedWorldEvent event) {
        Player player = event.getPlayer();
        World from = event.getFrom();
        World to = player.getWorld();
    
        player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 40, 1));
        player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f);
        player.spawnParticle(Particle.PORTAL, player.getLocation(), 100, 0.5, 1, 0.5);
    }
  33. 월드 별 스코어보드:
    각 월드마다 다른 스코어보드를 표시할 수 있습니다.

    @EventHandler
    public void onPlayerChangedWorld(PlayerChangedWorldEvent event) {
        Player player = event.getPlayer();
        World world = player.getWorld();
    
        Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
        Objective objective = scoreboard.registerNewObjective("worldInfo", "dummy", ChatColor.GOLD + world.getName());
        objective.setDisplaySlot(DisplaySlot.SIDEBAR);
    
        Score score = objective.getScore(ChatColor.GREEN + "Players: ");
        score.setScore(world.getPlayers().size());
    
        player.setScoreboard(scoreboard);
    }
  34. 월드 별 탑승물 제한:
    특정 월드에서 특정 탑승물의 사용을 제한할 수 있습니다.

    @EventHandler
    public void onVehicleEnter(VehicleEnterEvent event) {
        if (event.getEntered() instanceof Player) {
            Player player = (Player) event.getEntered();
            if (player.getWorld().getName().equals("no_vehicles_world")) {
                event.setCancelled(true);
                player.sendMessage("이 월드에서는 탑승물을 사용할 수 없습니다.");
            }
        }
    }
  35. 월드 별 채팅 형식:
    각 월드마다 다른 채팅 형식을 사용할 수 있습니다.

    @EventHandler
    public void onPlayerChat(AsyncPlayerChatEvent event) {
        Player player = event.getPlayer();
        String worldName = player.getWorld().getName();
        String format = ChatColor.GRAY + "[" + worldName + "] " + ChatColor.WHITE + "%s: %s";
        event.setFormat(format);
    }

이러한 기능들을 조합하여 각 월드마다 고유한 특성과 규칙을 가진 다양한 게임 환경을 만들 수 있습니다. 멀티월드 설정을 통해 플레이어들에게 다양한 게임 경험을 제공하고, 서버의 콘텐츠를 풍부하게 만들 수 있습니다. 단, 너무 많은 월드를 동시에 로드하면 서버 성능에 부담이 될 수 있으므로, 적절히 관리하는 것이 중요합니다.

15. 백업 및 복구 전략

마인크래프트 서버를 안정적으로 운영하기 위해서는 효과적인 백업 및 복구 전략이 필수적입니다. 여기서는 Paper 서버의 데이터를 안전하게 백업하고 필요 시 복구하는 방법에 대해 자세히 알아보겠습니다.

  1. 자동 백업 스크립트 생성:
    다음은 기본적인 백업 스크립트의 예시입니다.

    #!/bin/bash
    
    # 설정
    SERVER_DIR="/home/ubuntu/minecraft-server"
    BACKUP_DIR="/home/ubuntu/minecraft-backups"
    WORLDS_TO_BACKUP=("world" "world_nether" "world_the_end")
    MAX_BACKUPS=7
    
    # 타임스탬프
    TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
    
    # 백업 디렉토리 생성
    mkdir -p "$BACKUP_DIR"
    
    # 서버에 백업 시작 메시지 전송
    screen -S minecraft -X stuff "say 서버 백업을 시작합니다. 잠시 지연이 있을 수 있습니다.$(printf '\r')"
    
    # 월드 저장 및 오토세이브 비활성화
    screen -S minecraft -X stuff "save-all$(printf '\r')"
    screen -S minecraft -X stuff "save-off$(printf '\r')"
    
    # 백업 생성
    for world in "${WORLDS_TO_BACKUP[@]}"; do
       tar -czf "$BACKUP_DIR/$world-$TIMESTAMP.tar.gz" -C "$SERVER_DIR" "$world"
    done
    
    # 플러그인 설정 백업
    tar -czf "$BACKUP_DIR/plugins-$TIMESTAMP.tar.gz" -C "$SERVER_DIR" "plugins"
    
    # 서버 속성 파일 백업
    cp "$SERVER_DIR/server.properties" "$BACKUP_DIR/server.properties-$TIMESTAMP"
    
    # 오토세이브 다시 활성화
    screen -S minecraft -X stuff "save-on$(printf '\r')"
    
    # 오래된 백업 삭제
    for world in "${WORLDS_TO_BACKUP[@]}"; do
       find "$BACKUP_DIR" -name "$world-*.tar.gz" -type f -printf '%T@ %p\n' | sort -n | head -n -$MAX_BACKUPS | cut -d' ' -f2- | xargs -r rm
    done
    find "$BACKUP_DIR" -name "plugins-*.tar.gz" -type f -printf '%T@ %p\n' | sort -n | head -n -$MAX_BACKUPS | cut -d' ' -f2- | xargs -r rm
    find "$BACKUP_DIR" -name "server.properties-*" -type f -printf '%T@ %p\n' | sort -n | head -n -$MAX_BACKUPS | cut -d' ' -f2- | xargs -r rm
    
    # 서버에 백업 완료 메시지 전송
    screen -S minecraft -X stuff "say 서버 백업이 완료되었습니다.$(printf '\r')"
    
    echo "백업이 완료되었습니다: $TIMESTAMP"

    이 스크립트를 backup.sh로 저장하고 실행 권한을 부여합니다:

    chmod +x backup.sh
  2. 정기적인 백업 스케줄링:
    cron을 사용하여 백업을 자동화합니다.

    crontab -e

    다음 줄을 추가하여 매일 새벽 4시에 백업을 실행합니다:

    0 4 * * * /home/ubuntu/minecraft-server/backup.sh
  3. 원격 백업:
    백업 파일을 다른 서버나 클라우드 스토리지에 저장하는 것이 좋습니다.

    예를 들어, AWS S3를 사용하는 경우:

    aws s3 sync /home/ubuntu/minecraft-backups s3://your-bucket-name/minecraft-backups
  4. 백업 무결성 검증:
    정기적으로 백업 파일의 무결성을 검사합니다.

    for backup in /home/ubuntu/minecraft-backups/*.tar.gz; do
       if ! tar -tzf "$backup" > /dev/null 2>&1; then
           echo "손상된 백업 파일: $backup"
       fi
    done
  5. 증분 백업:
    전체 백업 대신 변경된 파일만 백업하여 저장 공간을 절약할 수 있습니다.

    rsync -avz --link-dest="/path/to/last_backup" "/path/to/minecraft-server" "/path/to/new_backup"
  6. 데이터베이스 백업:
    플러그인이 사용하는 데이터베이스가 있다면 함께 백업해야 합니다.
    MySQL 예시:

    mysqldump -u username -p database_name > /path/to/backup/database_backup.sql
  7. 복구 절차:
    백업에서 서버를 복구하는 방법입니다.

    a) 서버 중지

    screen -S minecraft -X stuff "say 서버가 복구를 위해 5초 후 종료됩니다.$(printf '\r')"
    sleep 5
    screen -S minecraft -X stuff "stop$(printf '\r')"

    b) 백업에서 복원

    # 월드 파일 복원
    tar -xzf /path/to/backup/world-TIMESTAMP.tar.gz -C /home/ubuntu/minecraft-server
    tar -xzf /path/to/backup/world_nether-TIMESTAMP.tar.gz -C /home/ubuntu/minecraft-server
    tar -xzf /path/to/backup/world_the_end-TIMESTAMP.tar.gz -C /home/ubuntu/minecraft-server
    
    # 플러그인 설정 복원
    tar -xzf /path/to/backup/plugins-TIMESTAMP.tar.gz -C /home/ubuntu/minecraft-server
    
    # 서버 속성 파일 복원
    cp /path/to/backup/server.properties-TIMESTAMP /home/ubuntu/minecraft-server/server.properties

    c) 서버 재시작

    screen -S minecraft -dm bash -c 'java -Xms4G -Xmx4G -jar paper.jar nogui'
  8. 자동 복구 스크립트:
    복구 과정을 자동화하는 스크립트를 만들 수 있습니다.

    #!/bin/bash
    
    # 설정
    SERVER_DIR="/home/ubuntu/minecraft-server"
    BACKUP_DIR="/home/ubuntu/minecraft-backups"
    TIMESTAMP=$1  # 복구할 백업의 타임스탬프를 인자로 받음
    
    # 서버 중지
    screen -S minecraft -X stuff "say 서버가 복구를 위해 5초 후 종료됩니다.$(printf '\r')"
    sleep 5
    screen -S minecraft -X stuff "stop$(printf '\r')"
    sleep 10
    
    # 현재 서버 상태 백업
    mv "$SERVER_DIR" "${SERVER_DIR}_old_$(date +%Y%m%d_%H%M%S)"
    
    # 새 서버 디렉토리 생성
    mkdir -p "$SERVER_DIR"
    
    # 백업에서 복원
    tar -xzf "$BACKUP_DIR/world-$TIMESTAMP.tar.gz" -C "$SERVER_DIR"
    tar -xzf "$BACKUP_DIR/world_nether-$TIMESTAMP.tar.gz" -C "$SERVER_DIR"
    tar -xzf "$BACKUP_DIR/world_the_end-$TIMESTAMP.tar.gz" -C "$SERVER_DIR"
    tar -xzf "$BACKUP_DIR/plugins-$TIMESTAMP.tar.gz" -C "$SERVER_DIR"
    cp "$BACKUP_DIR/server.properties-$TIMESTAMP" "$SERVER_DIR/server.properties"
    
    # 서버 재시작
    screen -S minecraft -dm bash -c 'cd /home/ubuntu/minecraft-server && java -Xms4G -Xmx4G -jar paper.jar nogui'
    
    echo "서버가 $TIMESTAMP 백업으로 복구되었습니다."

    이 스크립트를 restore.sh로 저장하고 실행 권한을 부여합니다:

    chmod +x restore.sh

    사용 예:

    ./restore.sh 2023-07-13_04-00-00
  9. 백업 로테이션:
    디스크 공간을 효율적으로 사용하기 위해 오래된 백업을 자동으로 삭제합니다.

    # 30일 이상 된 백업 삭제
    find "$BACKUP_DIR" -name "*.tar.gz" -type f -mtime +30 -delete
    find "$BACKUP_DIR" -name "server.properties-*" -type f -mtime +30 -delete
  10. 백업 암호화:
    중요한 데이터를 보호하기 위해 백업을 암호화할 수 있습니다.

    # 백업 암호화
    gpg --symmetric --cipher-algo AES256 "$BACKUP_DIR/$world-$TIMESTAMP.tar.gz"
    
    # 암호화된 백업 복호화
    gpg --decrypt "$BACKUP_DIR/$world-$TIMESTAMP.tar.gz.gpg" > "$BACKUP_DIR/$world-$TIMESTAMP.tar.gz"
  11. 백업 알림:
    백업 완료 후 관리자에게 이메일로 알림을 보냅니다.

    echo "마인크래프트 서버 백업이 완료되었습니다. 타임스탬프: $TIMESTAMP" | mail -s "백업 완료 알림" admin@example.com
  12. 백업 테스트:
    정기적으로 백업에서 복구 테스트를 수행하여 백업의 신뢰성을 확인합니다.

    # 테스트용 임시 디렉토리 생성
    TEST_DIR="/tmp/minecraft_backup_test"
    mkdir -p "$TEST_DIR"
    
    # 백업에서 복원
    tar -xzf "$BACKUP_DIR/world-$TIMESTAMP.tar.gz" -C "$TEST_DIR"
    
    # 복원된 파일 확인
    if [ -f "$TEST_DIR/world/level.dat" ]; then
        echo "백업 테스트 성공: world/level.dat 파일이 존재합니다."
    else
        echo "백업 테스트 실패: world/level.dat 파일이 없습니다."
    fi
    
    # 테스트 디렉토리 정리
    rm -rf "$TEST_DIR"
  13. 차등 백업:
    전체 백업과 함께 차등 백업을 사용하여 백업 시간과 저장 공간을 절약할 수 있습니다.

    # 마지막 전체 백업 이후 변경된 파일만 백업
    rsync -avz --link-dest="$BACKUP_DIR/latest" "$SERVER_DIR" "$BACKUP_DIR/$TIMESTAMP"
    ln -sfn "$BACKUP_DIR/$TIMESTAMP" "$BACKUP_DIR/latest"
  14. 백업 압축 최적화:
    백업 파일의 크기를 줄이기 위해 고급 압축 옵션을 사용할 수 있습니다.

    XZ_OPT='-9' tar -cJf "$BACKUP_DIR/$world-$TIMESTAMP.tar.xz" -C "$SERVER_DIR" "$world"
  15. 백업 메타데이터 저장:
    각 백업에 대한 메타데이터를 저장하여 관리를 용이하게 합니다.

    echo "Timestamp: $TIMESTAMP
    Server Version: $(java -jar paper.jar --version)
    Worlds: ${WORLDS_TO_BACKUP[*]}
    Plugins: $(ls -1 "$SERVER_DIR/plugins" | grep .jar)
    " > "$BACKUP_DIR/backup_info_$TIMESTAMP.txt"
  16. 롤백 기능:
    특정 시점으로 서버를 롤백할 수 있는 기능을 구현합니다.

    #!/bin/bash
    
    ROLLBACK_TIME=$1  # 형식: YYYY-MM-DD_HH:MM:SS
    
    # 가장 가까운 백업 찾기
    CLOSEST_BACKUP=$(find "$BACKUP_DIR" -name "world-*.tar.gz" -type f -printf '%T@ %p\n' | sort -n | awk -v time="$ROLLBACK_TIME" '$1 <= time' | tail -n 1 | cut -d' ' -f2-)
    
    if [ -z "$CLOSEST_BACKUP" ]; then
        echo "지정된 시간 이전의 백업을 찾을 수 없습니다."
        exit 1
    fi
    
    # 롤백 실행
    ./restore.sh $(basename "$CLOSEST_BACKUP" | sed 's/world-\(.*\)\.tar\.gz/\1/')
  17. 백업 성능 최적화:
    백업 중 서버 성능에 미치는 영향을 최소화하기 위한 방법들:

    • nice 명령어 사용: nice -n 19 tar -czf ...
    • ionice 사용: ionice -c2 -n7 tar -czf ...
    • 백그라운드에서 백업 실행: (backup_command) & disown
  18. 백업 결과 로깅:
    백업 프로세스의 상세 로그를 유지합니다.

    exec > >(tee -a "/var/log/minecraft_backup.log") 2>&1
    echo "백업 시작: $(date)"
    # 백업 명령어들...
    echo "백업 완료: $(date)"

이러한 고급 백업 및 복구 전략을 구현하면 마인크래프트 서버의 데이터를 안전하게 보호하고, 문제 발생 시 신속하게 복구할 수 있습니다. 정기적으로 백업 프로세스를 검토하고 테스트하여 항상 최신 상태로 유지하는 것이 중요합니다.

이상으로 마인크래프트 1.20.6 Paper 서버 구축 및 관리 가이드를 마칩니다. 이 가이드를 통해 안정적이고 최적화된 마인크래프트 서버를 운영할 수 있기를 바랍니다. 추가적인 질문이나 더 자세한 설명이 필요한 부분이 있다면 언제든 물어보세요.

Leave a Reply