[AWS] EC2에 Next.js(Standalone) 배포하기

neom·2026년 2월 3일

Web

목록 보기
4/4

AWS EC2 프리티어 환경에서 Next.js 프로젝트를 배포하면서 겪었던 문제들과 해결 과정을 정리해 봅니다. 특히 메모리 부족 문제와 Standalone 모드, 그리고 Nginx/DNS 연결 이슈를 중점적으로 다룹니다.

1. 배경

환경: AWS EC2 (Ubuntu 24.04, t3.micro 프리티어)
스택: Next.js 16 (App Router), PM2, Nginx, Let's Encrypt, Route53, 가비아 도메인
목표: Github Actions로 자동 배포 파이프라인 구축 및 도메인(https) 연결

pnpm run build → PM2 → Nginx 리버스프록시 → 도메인 연결


2. 트러블 슈팅

이슈 1: 빌드하다가 서버가 자꾸 죽음 (메모리 부족)

프리티어(t3.micro)의 RAM은 고작 1GB인데
pnpm build만 돌리면 서버가 멈춰버리는 현상이 발생했습니다. (SSH 타임아웃)

✅ 해결: Swap 메모리 2GB 설정

RAM이 부족할 때 HDD를 RAM처럼 쓰는 스왑 메모리를 설정해서 해결했습니다.

# 2GB 스왑 파일 생성
sudo dd if=/dev/zero of=/swapfile bs=128M count=16
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 재부팅해도 유지되도록 /etc/fstab에 추가
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab

이슈 2: 배포 용량 최적화 (Standalone 모드)

기본 빌드는 node_modules 전체가 필요해서 무거워서 실행에 필요한 파일만 추려내는 Standalone 모드를 적용하기로 했습니다.

  • next.config.ts 수정
const nextConfig: NextConfig = {
  output: "standalone", // 이 한 줄이 핵심!
  reactCompiler: true,
};

  • ecosystem.config.js 수정
    PM2가 실행할 스크립트를 next start가 아닌 Standalone 빌드 결과물(server.js)로 변경.
module.exports = {
  apps: [{
    name: "aws-practice",
    script: "node", // next start 아님!
    args: ".next/standalone/server.js",
    env: {
      NODE_ENV: "production",
      PORT: 3000,
      HOSTNAME: "0.0.0.0"
    }
  }]
}

⚠️ 주의할 점
Standalone 모드는 정적 파일(public, static)을 자동으로 복사하지 않기 때문에 배포 스크립트에서 수동으로 복사해줘야 이미지와 스타일이 안 깨진다.


이슈 3. Nginx 502 Bad Gateway & Connection Refused

Nginx 설정을 잘 했는데도 무한로딩이 되며 접속이 안 되고 에러 로그에 connect() failed (111: Connection refused)가 떴습니다.

sudo tail /var/log/nginx/error.log
# 2026/02/03 14:24:36 [error] connect() failed (111: Connection refused) 
# while connecting to upstream, upstream: "http://127.0.0.1:3000/"

디버깅을 해보고자 아래 명령어로 로컬에 접근했지만 Next.js의 문제가 아니었습니다.

curl http://127.0.0.1:3000

알고 보니 EC2를 재부팅하면서 IP 주소가 바뀌었는데, 도메인(DNS)은 옛날 IP를 가리키고 있어 발생하는 문제였습니다.

✅ 해결: 탄력적 IP (Elastic IP) 할당

AWS EC2 콘솔에서 '탄력적 IP'를 할당받아 인스턴스에 연결하고
Route 53에서 A 레코드 값을 새 IP로 수정했습니다.
Github Actions 배포 스크립트(deploy.yml)의 host 주소도 새 IP로 변경했습니다.


3. 최종 배포 스크립트 (Github Actions)

# .github/workflows/deploy.yml
- name: Deploy to EC2
  run: |
    ssh -i key.pem ubuntu@43.xxx.xxx.xxx << 'EOF'
      cd ~/aws-practice
      git pull origin main
      pnpm install
      pnpm build
      
      # Standalone 필수: 정적 파일 복사
      cp -r public .next/standalone/
      cp -r .next/static .next/standalone/.next/
      
      # PM2 재시작
      pm2 restart aws-practice
    EOF

4. 결론 및 배운점

프리티어는 용량이 적기에 스왑 메모리가 필수다! (안 그러면 빌드 못함)
Standalone 모드는 가볍고 좋지만, 정적 파일 복사(cp)를 잊으면 안 된다.
EC2 IP는 재부팅 시 변하므로 도메인을 연결할 거면 처음부터 탄력적 IP를 할당하고 시작하자!

profile
행복하게 살래여

0개의 댓글