[AWS] 유니티 게임 서버(NestJS) 무중단 배포

이번 글은 개인 프로젝트로 진행했던 방치형 게임의 백엔드 시스템을 AWS EC2에 올린 과정을 정리합니다.

 

AWS 계정 보안: 권한 분리 및 MFA 설정

처음 가입했을때 root 계정으로 사용하게 되는데 root 계정은 모든 권한을 가진 '마스터 계정' 이라서 사용자계정을 분리 시켜야합니다.

 

  • IAM 콘솔 접속: AWS 상단 검색창에 IAM을 입력하고 이동합니다.
  • 사용자 생성 시작: 왼쪽 메뉴에서 사용자 -> 사용자 생성 버튼을 클릭합니다.
  • 사용자 세부 정보 설정:
    • 사용자 이름: Admin-Dev (본인이 알아보기 쉬운 이름)
    • AWS 관리 콘솔에 대한 사용자 액세스 권한 제공: 체크
    • 사용자 유형: IAM 사용자를 생성하고 싶음 선택
    • 비밀번호 설정: 사용자 지정 비밀번호로 안전하게 설정합니다.

 

  • 권한 설정:
    • 직접 정책 연결 선택
    • 권한 정책 검색창에 AdministratorAccess 입력 후 체크 (관리자 권한 부여)
  • 검토 및 생성: 설정을 확인하고 사용자 생성을 완료합니다.
    • 중요: 생성 직후 나오는 로그인 URL, 사용자 이름, 암호가 담긴 .csv 파일을 다운로드하거나 안전한 곳에 기록해 두세요.

 

MFA(2단계 인증) 설정 (보안의 핵심)

비밀번호가 유출되더라도 스마트폰 OTP 없이는 로그인이 불가능하게 만듭니다. Root 계정과 새로 만든 IAM 계정 둘 다 설정하는 것이 필수입니다.

  1. 사용자 선택: IAM 리스트에서 방금 만든 Admin-Dev 사용자를 클릭합니다.
  2. 보안 자격 증명 탭: 중간에 있는 보안 자격 증명 탭으로 이동합니다.
  3. MFA 할당: MFA 장치 할당 버튼을 클릭합니다.
  4. 장치 선택:
    • 장치 이름: MyPhone
    • MFA 장치 유형: 인증 앱 (Google Authenticator 등) 선택
  5. 앱 연동:
    • 스마트폰에서 Google Authenticator 앱을 실행합니다.
    • QR 코드 표시를 누르고 앱으로 스캔합니다.
    • 앱에 뜨는 6자리 번호 2개를 차례대로 입력(코드 1, 코드 2)하고 MFA 추가를 누릅니다.

Root 계정 보안 조치 (마무리)

이제 Root 계정은 더 이상 쓰지 않도록 잠궈야 합니다.

  1. Root 계정 로그아웃 후, 아까 저장한 IAM 사용자 전용 로그인 URL로 접속하여 Admin-Dev로 로그인합니다.
  2. 앞으로는 이 계정으로만 서버를 관리합니다.
  3. Root 계정 관리: Root 계정은 결제 수단 변경 등 아주 중요한 작업 외에는 절대 로그인하지 마세요.

이렇게 MFA가 인증됩니다.

앞으로 로그인할때마다 휴대폰에 6자리 입력하면서 로그인하게 됩니다.


EC2 인스턴스 생성 (골격 만들기)

  1. AWS 콘솔 접속 > EC2 서비스 선택 > 인스턴스 시작 클릭
  2. 이름 및 태그: auto-game-server (관리하기 편한 이름)
  3. OS(AMI): Ubuntu Server 24.04 LTS (64비트) 선택 (가장 안정적임)
  4. 인스턴스 유형: t2.micro (프리티어 확인)
  5. 키 페어: 새 키 페어 생성 > RSA 방식, .pem 형식으로 다운로드 (보관 필수!)

스토리지(EBS) 30GB 증설 (근육 붙이기)

  • 설정 위치: 인스턴스 생성 화면 하단의 스토리지 구성
  • 변경 내용: 기본값 8 GiB를 **30 GiB**로 수정합니다.
  • 주의: 30GB를 초과하면 비용이 발생하므로 정확히 30으로 맞추는 것이 포인트입니다.

3. 네트워크 및 보안 그룹 (방어선 구축)

  • 인스턴스 생성 시 네트워크 설정에서 보안 그룹 생성을 선택하고 아래 규칙을 추가합니다.
유형 포트 범위 소스 유형 설명
SSH 22 내 IP 내 PC에서만 터미널 접속 허용 (보안)
사용자 지정 TCP 3000 위치 무관(0.0.0.0/0) NestJS 서버 포트 (유니티 클라이언트용)
사용자 지정 TCP 6379 사용자 지정 (선택) 외부에서 Redis 접속이 필요할 때만 개방

 


탄력적 IP(Elastic IP) 할당 및 연결 (필수)

EC2는 기본적으로 '동적 IP'를 사용합니다. 즉, 서버를 재부팅하거나 인스턴스를 중지 후 다시 시작하면 IP 주소가 바뀝니다. 유니티 클라이언트에 서버 주소를 고정해두려면 '고정 IP'가 반드시 필요합니다.

  1. 메뉴 이동: EC2 대시보드 왼쪽 사이드바 -> 네트워크 및 보안 -> 탄력적 IP 클릭.
  2. IP 할당: 오른쪽 상단 탄력적 IP 주소 할당 클릭 -> 할당 버튼 클릭.
  3. 인스턴스 연결: 생성된 IP 주소를 체크 -> 작업 메뉴 -> 탄력적 IP 주소 연결 선택.
    • 인스턴스: 내가 만든 auto-game-server 선택.
    • 프라이빗 IP 주소: 해당 인스턴스의 내부 IP 선택.
  4. 확인: 이제 서버를 껐다 켜도 이 IP 주소는 절대 바뀌지 않습니다.

📍 인스턴스 생성 시 '보안 그룹 생성' 상세 설정 (Step-by-Step)

인스턴스 시작(Launch Instance) 화면 중간의 [네트워크 설정] 부분에서 아래 순서대로 세팅하세요.

1. 보안 그룹 생성 선택

  • 보안 그룹 생성 항목을 체크합니다.
  • 보안 그룹 이름: auto-game-sg (나중에 찾기 쉽게 이름을 꼭 지어주세요)
  • 설명: Game server security group for NestJS and Redis

2. 인바운드 보안 그룹 규칙 구성 (여기가 핵심!)

기본으로 하나가 떠 있을 텐데, 오른쪽의 [보안 그룹 규칙 추가] 버튼을 눌러 총 3개를 만듭니다.

Rule 1: SSH (내 접속용)

  • 유형: SSH
  • 프로토콜/포트: TCP / 22
  • 소스 유형: 내 IP (가장 중요!)
  • 설명: Admin SSH Access

Rule 2: NestJS (게임 통신용)

  • 유형: 사용자 지정 TCP
  • 프로토콜/포트: TCP / 3000
  • 소스 유형: 위치 무관(Anywhere) (0.0.0.0/0)
  • 설명: Unity Client Communication

Rule 3: Redis (내부 DB용)

  • 유형: 사용자 지정 TCP
  • 프로토콜/포트: TCP / 6379
  • 소스 유형: 사용자 지정 * 소스: 칸을 클릭하면 나오는 리스트에서 **현재 생성 중인 보안 그룹 이름(또는 ID)**을 선택합니다. 만약 아직 안 뜨면 일단 내 IP로 해두고 생성 후에 수정하면 됩니다.
  • 설명: Internal Redis Access

💡 왜 '그냥' 만들 때 이 설정을 해야 하나요? (납득 포인트)

  • 자동 생성의 함정: 아무 설정 없이 SSH를 허용하면 소스가 0.0.0.0/0(모두)으로 잡힙니다. 이러면 전 세계 해커들이 내 서버 대문에 매일 노크를 하게 됩니다.
  • 한 번에 끝내기: 생성 단계에서 **내 IP**와 **3000번 포트**만 정확히 잡아줘도 보안의 80%는 성공입니다.

 


서버 원격 접속 및 초기 환경 구축 (Access & Runtime)

1. 내 PC에서 서버 접속하기 (SSH)

다운로드받은 .pem 키 파일이 있는 폴더에서 터미널(CMD 또는 PowerShell)을 열고 아래 명령어를 입력합니다.

터미널 명령어
# 1. (Windows 전용) 키 파일 권한 제한 (앞서 설명한 icacls 명령어)
icacls "your-key.pem" /inheritance:r
icacls "your-key.pem" /grant:r "%username%:R"

# 2. SSH 접속 실행
# ubuntu는 AWS 우분투 이미지의 기본 사용자 이름입니다.
ssh -i "your-key.pem" ubuntu@[탄력적 IP 주소]

성공 시: Welcome to Ubuntu... 라는 문구와 함께 커서가 ubuntu@ip-xxx-xx-xx-xx:~$ 로 바뀝니다.

2. 필수 런타임 설치 (Node.js & npm)

NestJS 서버는 Node.js 위에서 돌아갑니다. 최신 LTS 버전을 설치해 줍니다.

Bash
 
# 패키지 매니저 업데이트
sudo apt update && sudo apt upgrade -y

# Node.js 20.x (LTS) 설치 스크립트 실행
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

# 설치 확인
node -v
npm -v

3. Redis 인메모리 데이터베이스 구축

게임의 랭킹이나 실시간 세션 데이터를 빠르게 처리하기 위해 Redis를 설치합니다.

Bash
 
# Redis 설치
sudo apt install redis-server -y

# Redis 실행 및 자동 실행 설정
sudo systemctl start redis-server
sudo systemctl enable redis-server

# 작동 테스트 (PONG이 나오면 성공)
redis-cli ping

4. PM2 (Process Manager) 설치

우리가 터미널 창을 닫아도 서버가 죽지 않고 24시간 돌아가게 해주는 필수 도구입니다.

Bash
 
# 전역(global)으로 PM2 설치
sudo npm install -g pm2

 

PM2 프로세스 관리 및 모니터링 마스터하기

PM2는 서버가 예상치 못한 에러로 종료되어도 자동으로 재시작해주며, 터미널을 닫아도 백그라운드에서 서비스를 유지해주는 든든한 관리자입니다.

1. 서버 실행 및 등록

처음 프로젝트를 빌드한 후 서버를 올릴 때 사용합니다.

Bash
 
# dist/main.js 파일을 "auto-game-server"라는 이름으로 실행
pm2 start dist/main.js --name "auto-game-server"

# 서버 재부팅 시에도 PM2가 이 프로세스를 기억하고 자동 실행하게 설정
pm2 save

2. 실시간 상태 모니터링 (가장 많이 사용)

서버가 잘 돌아가고 있는지, 에러는 없는지 확인할 때 필수입니다.

  • 상태 요약: pm2 status
    • online 상태인지, 메모리와 CPU 점유율은 어떤지 한눈에 보여줍니다.
  • 실시간 로그 감시: pm2 logs auto-game-server
    • 가장 중요합니다. 유니티 클라이언트에서 접속 에러가 나거나 서버 내부 로직 오류(500 Error 등)가 발생하면 여기서 실시간으로 확인할 수 있습니다.
  • 대시보드 모드: pm2 monit
    • 터미널 화면을 화려한 대시보드로 바꿔줍니다. 리소스 사용량을 시각적으로 모니터링할 때 유용합니다.

3. 프로세스 제어 (업데이트 및 수정 시)

코드를 수정하거나 서버 설정을 바꿨을 때 사용합니다.

  • 재시작: pm2 restart auto-game-server
    • git pull로 코드를 업데이트하거나 .env 파일을 수정한 후 즉시 반영할 때 사용합니다.
  • 중지 및 삭제:
    • pm2 stop auto-game-server: 잠시 서버를 끕니다.
    • pm2 delete auto-game-server: 관리 목록에서 완전히 삭제합니다.

4. PM2 관리 명령어 요약표

상황 실행 명령어 비고
최초 실행 pm2 start [경로] --name [이름] 프로세스 이름 지정 권장
에러 추적 pm2 logs [이름] 트러블슈팅의 1순위
상태 확인 pm2 status 서비스 생존 여부 확인
코드 반영 pm2 restart [이름] 수정사항 즉시 적용
부팅 자동화 pm2 save AWS 인스턴스 재부팅 대비