Elastic Beanstalk로 Next.js 앱 배포하기
AWS Elastic Beanstalk는 웹 애플리케이션을 배포할 수 있는 클라우드 플랫폼으로 인스턴스 성능 조절, 로드 밸런싱, 상태 모니터링, 버전 관리 등이 가능하다. 사용자에게 웹 애플리케이션 배포를 위한 AWS의 여러 서비스를 통합 제공하는 서비스라고 볼 수 있다. 특히 변화하는 네트워크 트래픽에 대응할 수 있도록 자동 스케일링을 지원한다. 그리고 복수의 환경을 구성해서 스테이징 버전을 충분히 테스트한 후 프로덕션 버전을 서비스 중단 없이 교체하는 등 서비스 안정성 보장을 위한 다양한 기능이 있다.
공식 문서에는 Node.js 플랫폼에서 express 애플리케이션을 배포하는 방법을 제공한다. 이 글에서는 별도의 빌드 과정이 필요한 Next 앱을 배포하는 과정을 정리했다.
Elastic Beanstalk 용어
-
애플리케이션
- 복수의 환경으로 구성된 작업 공간.
-
환경
- 앱이 실행되는 배포 환경. 각각의 환경은 서로 다른 ID와 접속 URL을 가진다. 개발, 릴리즈, 프로덕션 등 목적에 맞게 추가해서 사용할 수 있다.
-
인스턴스
- 1개의 환경은 복수의 AWS EC2 인스턴스를 가질 수 있다. 인스턴스 유형은 필요한 성능에 맞춰 선택할 수 있다.
-
플랫폼
- 운영체제, 웹 서버, 애플리케이션 서버 등 웹 애플리케이션 실행을 위한 구성 요소를 포함한다.
-
용량
- 환경의 인스턴스가 1개 이상이면 자동으로 로드 밸런싱이 작동한다. 환경은 최소 1개에서 최대 10000개의 인스턴스를 가질 수 있다. 실제로 사용되는 인스턴스의 수는 사용자가 설정한 최소, 최대 인스턴스 수와 트리거에 기반을 둬서 자동으로 조절된다.
-
롤링 업데이트
- 배포를 하면 기본적으로 모든 인스턴스를 한 번에 업데이트한다. 그런데 Elastic Beanstalk는 드롭인(drop-in) 업그레이드 프로세스를 사용하기 때문에 애플리케이션이 몇 초 정도 가동이 중지될 수 있다. 그래서 프로덕션 환경에서는 인스턴스를 나눠서 업데이트하는 방법이 권장된다. 한 번에 업데이트할 인스턴스의 수와 비율을 사용자가 직접 지정할 수 있다.
배포 과정
아래의 배포 과정은 macOS에서 진행할 수 있다.
1. EB CLI 설치
설치 스크립트가 있는 Git repository를 클론한 후 실행한다.
git clone https://github.com/aws/aws-elastic-beanstalk-cli-setup.git
./aws-elastic-beanstalk-cli-setup/scripts/bundled_installer
시스템에 파이썬이 설치되어 있지 않다면 bundled_installer
실행 중에 오류가 발생한다. 그럴 때는 scripts 폴더에 있는 python_installer
로 파이썬을 설치한 후 진행하면 된다. 설치 성공 후에는 CLI 실행 파일을 PATH에 추가하는 명령어가 제공되므로 그것도 실행해준다.
2. Git 저장소 초기화
Elastic Beanstalk는 Git 저장소에서 마지막으로 커밋된 버전을 압축해서 S3에 올린다. 소스를 수정했더라도 커밋을 하지 않았다면 해당 내용은 배포되지 않으니 주의해야 한다.
그리고 현재 브랜치의 커밋이 원격에 푸시되지 않아도 배포할 수 있다. 그래서 공동 작업을 한다면 CI 도구를 사용해서 원격에 올라간 작업 내용만 Elastic Beastalk에 배포되게 보장해야 할 것이다.
3. Next.js 앱 설치
Next.js 문서에 있는 설치 과정을 참조해서 빌드와 실행이 가능하도록 프로젝트를 소스를 구성한다.
4. eb init
Elastic Beanstalk 애플리케이션을 생성하거나 선택할 수 있도록 초기 설정을 진행한다. 자기에게 맞는 리전, 플랫폼 등을 선택한다.
5. eb create
배포할 환경을 만든다. 이름을 입력하고 로드 밸런서 타입을 선택한다. 로드 밸런서는 보통 기본 타입인 application을 선택한다.
init, create 과정을 거치면 프로젝트 폴더에 .elasticbeanstalk/config.yml 파일이 만들어진다.
branch-defaults:
develop:
environment: eb-next-app-dev # develop 브랜치에서 배포할 환경. eb use 명령어로 수정 가능하다. environment-defaults:
eb-next-app-dev:
branch: null
repository: null
global:
application_name: eb-next-app # 애플리케이션 이름 default_ec2_keyname: key-name # 배포에 ssh를 사용하려면 AWS IAM에서 엑세스 키를 만들어야 한다. default_platform: arn:aws:elasticbeanstalk:ap-northeast-2::platform/Node.js running on 64bit Amazon Linux/4.10.1 # 선택한 플랫폼
default_region: ap-northeast-2 # Seoul 리전
include_git_submodules: true
instance_profile: null
platform_name: null
platform_version: null
profile: eb-cli
sc: git
workspace_type: Application
이 글에서 진행하는 배포 과정에서는 config.yml 파일을 직접 수정해야 할 필요가 없다.
6. .ebignore 파일 추가
배포는 Git 저장소 전체를 S3에 업로드하는 방식이다. .gitignore 설정 파일이 있다면 등록된 파일을 제외하고 배포를 한다. 그런데 .gitignore에는 보통 .next, node_modules처럼 앱 실행에 필요한 파일과 폴더가 지정되어 있다. 그런 상태에서 배포를 해서 앱을 실행하면 자연히 필요한 파일을 찾지 못하는 오류가 생긴다. 그래서 .ebignore 파일에 배포를 할 때 제외시킬 파일을 지정해야 한다. .ebignore에는 아래와 같은 내용이 들어갈 수 있다.
.git
.gitignore
Git 저장소 관련 파일만 제외하고 모두 배포하도록 했다. EB CLI는 .ebignore가 있으면 .gitignore를 무시한다.
7. Next.js 앱의 실행 포트를 8081로 변경
Elastic Beanstalk의 node.js 플랫폼은 기본적으로 웹 서버로 Nginx를 사용하며 리버스 프록시 설정을 통해 외부 접근을 8081 포트로 보낸다. 그런데 Next 앱은 기본적으로 서버 포트로 3000을 사용한다. 리버스 프록시 설정을 직접 수정할 수도 있지만 Next 앱이 프로덕션 모드로 실행할 때 8081 포트를 사용하도록 package.json 파일을 수정하는 편이 더 간단하다.
{
"scripts": {
"start": "next start -p 8081",
}
}
8. .npmrc 설정 (생략 가능)
Elastic Beanstalk에서 node.js 앱을 실행하기 위한 기본 명령어는 npm start
로 지정되어 있다(콘솔에서 수정 가능). 만약 저 스크립트에 npm install
이 포함되어 있다면 배포 과정에서 오류가 발생할 수 있다.
npm install은 root 계정으로 실행되지만 node-gyp 프로세스가 일부 패키지를 기본 계정인 ec2-user로 실행한다. 그 결과 node-gyp 프로세스가 root 계정이 만든 파일에 접근할 수 없는 오류를 만든다. 이를 방지하기 위해서는 npm이 node-gyp 프로세스를 강제로 root 계정을 통해 실행하도록 .npmrc 파일을 추가해야 한다.
unsafe-perm=true
9. eb deploy
터미널에서 eb deploy <환경 이름>
을 실행하면 해당 환경으로 브랜치의 최근 커밋이 배포된다.
빌드 후 배포가 진행되도록 npm script를 수정한다.
{
"scripts": {
"dev": "next dev",
"start": "next start -p 8081",
"build": "npm run clean && next build",
"clean": "rm -rf .next",
"deploy-dev": "npm install && npm run build && eb deploy eb-next-app-dev" }
}
npm run deploy-dev
10. eb open
배포에 성공했다면 eb open
명령어를 사용해서 기본 브라우저에 배포된 웹페이지를 열어본다. 접속 주소는 콘솔에서도 확인할 수 있다.
참고 문서
- AWS Elastic Beanstalk 플랫폼 용어집 - AWS Elastic Beanstalk
- 배포 - AWS Elastic Beanstalk
- 프록시 서버 구성 - AWS Elastic Beanstalk
- Beanstalk: Node.js deployment - node-gyp fails due to permission denied - Stack Overflow