AWS EC2에 Next 프로젝트 배포해보기 A to Z

2023. 4. 2. 16:12React/Next.js

말로만 듣던 EC2에 프로젝트를 Next 프로젝트를 배포하는 여정을 기록해보려고 합니다. 제 프로젝트는 의도치 않게 모노레포로 구성이 되어있었기 때문에 추후 포스팅할 Jenkins를 사용한 배포 자동화에 대한 고민이나, EC2 인스턴스에서 프로젝트를 세팅하는 과정에서 경로와 관련된 처리가 필요하답니다!

 

Next 프로젝트를 배포해보는 건 이번이 처음이었는데요. 배포에 앞서서 로컬에서 빌드했을 때 무슨 차이가 있는지 비교해보는 과정부터 시작해보겠습니다.

 

1. Next의 build 파일에는 index.html이 없다.



Next 빌드 결과

webpack 빌드 결과물

 

Next가 SSR을 지원하기에 요청이 들어오면 그때서 html을 만들어 보낸다는 건 개념적으로 알았지만, 결국 엔트리포인트를 어디로 잡아야할까에 대한 고민이 빌드를 준비하는 내내 들었었는데, 의외로 결과는 단순히 .next 폴더로 잡아주기만 하면 됐다.

 

 

// react-loadable-manifest.json

{
  "..\\..\\node_modules\\next\\dist\\client\\index.js -> ../pages/_app": {
    "id": "..\\..\\node_modules\\next\\dist\\client\\index.js -> ../pages/_app",
    "files": [
      "static/chunks/node_modules_next_dist_pages__app_js.js"
    ]
  },
  "..\\..\\node_modules\\next\\dist\\client\\index.js -> ../pages/_error": {
    "id": "..\\..\\node_modules\\next\\dist\\client\\index.js -> ../pages/_error",
    "files": [
      "static/chunks/node_modules_next_dist_pages__error_js.js"
    ]
  }
}

 

빌드된 프로젝트를 까보다가 react-loadable-menifest.json을 발견했는데, dynamic 라우팅의 과정을 단편적으로 확인해볼 수 있었다. jsx를 컴파일할 때 html, css, js 파일을 서버단에서 만들어 준 뒤에, 브라우저로 보내줍니다. EC2에 웹서버를 구축해두어서 해결할 수 있습니다.

 

사용해볼 스택을 한 번 정리해보겠습니다.

 

 

EC2 인스턴스 안에서 포트를 설정한 뒤에, Nginx를 사용하여 라우팅을 처리해주었습니다. 추후 Jenkins와 github의 webhook을 사용해서 master 브랜치에 배포되었을 때 프론트 서버, 백엔드 서버로 자동 배포되는 프로세스를 구축해보겠습니다.

 

2. EC2 보안 그룹 설정


(AWS 콘솔은 자주 바뀌기 때문에 2023.03 기준으로 작성되었습니다.)

EC2를 생성할 때 여러 서버를 선택할 수 있는데 저는 Amazon Linux로 선택했습니다.

다른 포스트에서 확인해보면 HTTP에 쓰이는 80포트나 HTTPS에 쓰이는 443포트를 직접 열어주는 과정이 필요하다고 되어있는데 일단 기본적으로 열려있는 걸 확인했습니다. launch-wizard로 되어있는 그룹에서 [인바운드 규칙]을 설정하여 포트를 열어줍니다.

 

 

저는 8000번 포트를 열어주었습니다. 이 포트에서 Next를 돌리고, 80포트나 443포트로 들어오는 요청을 8000번으로 포워딩해주면 브라우저에서 Next 프로젝트를 받아보는 게 가능합니다.

 

ssh로 인스턴스에 연결을 해준 뒤에 Next를 실행시키기 위한 Node.js와 Nginx를 설치해줘야합니다.

 

// nvm을 설치
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

// nvm 활성화
$ . ~/.nvm/nvm.sh

// 타깃하는 node 버전을 설치(저는 로컬과 똑같이 맞춰줬습니다.)
nvm install 18.6.0
// nginx 설치
$ sudo yum nginx

 

 

Nginx의 설정파일은 /etc/nginx/nginx.conf에서 확인해볼 수 있습니다. 일반적으로 이 파일을 루트로써 사용하고, sites-enabled 디렉토리에서 각 서비스의 설정을 따로 관리하는 방식으로 서버를 활용합니다. 이렇게 되면 하나의 IP 안에서 여러 서비스를 배포할 수 있는 장점이 있습니다.

 

3. Nginx.conf 설정


nginx.conf를 지우고 그 안에 간단한 설정 파일을 작성해줍니다. http는 80번 포트, https는 443포트입니다.

다만, 지금 ssh 인증서가 따로 없기 때문에 80번 포트에 대해서만 설정해주면 됩니다.

 

// nginx 설정파일 열기
$ sudo vi /etc/nginx/nginx.conf
include /etc/nginx/conf.d/*.conf;

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  _;
    root         /usr/share/nginx/html;
    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;
    location / {
    }
    error_page 404 /404.html;
        location = /40x.html {
    }
    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
 }

 

해당 파일을 지우고, 어떤 경로를 루트로 설정할 건지를 다시 넣어줍니다. 그에 앞서서 github에서 저장한 프로젝트를 클론하여 가져올 필요가 있네요. 얼른 가져와봅시다.

 

cd ~
git clone <your address of repository (SSH Address)>
server {
  listen 80;
  location / {
    root /home/ec2-user/YOUR_PROJECT_PATHS/.next;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
}

 

이어서 site-available과 sites-enabled를 설정하여 디렉토리에 필요한 파일들을 연결해 줄 필요가 있습니다. 여러 프로젝트를 호스팅할 수 있기 때문에 설정 파일을 지우지 않고 특정 설정 파일을 가져오면서 동기화시킬 수 있습니다.

경로를 만든 다음에 설정을 enabled 폴더에 그대로 복사해준 뒤에 nginx를 실행시킵니다.

 

$ sudo mkdir /etc/nginx/sites-available
$ sudo mkdir /etc/nginx/sites-enabled
$ sudo ln -s /etc/nginx/sites-available/YOUR_CONFIG_FILE.conf /etc/nginx/sites-enabled/YOUR_CONFIG_FILE.conf
$ sudo nginx -t
// 성공 시 콘솔에 다음과 같이 나옵니다.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

 

 

이렇게 설정한 이후에는 internal server error가 발생할 수 있습니다. ec2-user의 권한을 711로 변경해줍니다.

$ sudo systemctl start nginx
$ chmod 711 /home/ec2-user

 

 

4. 포트 설정


로컬에서 프로젝트를 실행시키면 일반적으로 3000번 포트에서 실행시킵니다. next를 빌드한 뒤에 실행시켜 줄 필요가 있습니다.

 

// package.json

{
  /*..*/
  "scripts": {
    "dev": "next dev",
    "start": "next start",
    "build": "next build",
  }
}

 

작성된 프로젝트에 대해 build 후, start로 프로젝트를 실행해줍니다. 이후에 인스턴스의 DNS 주소로 접속하면 성공!

 

개선해야할 점들


  • 백그라운드에서 프로젝트를 실행하는 방법.
    • "nohup npm start &" 등 명령어로 실행 시 백그라운드에서 프로젝트를 실행할 수 있다고 합니다.
    • 다만 npm을 사용하면 프로젝트 관리가 불리해 pm2를 사용한다고 합니다.
  • 443 포트 대응 방법.
    • ssh 인증서를 넣어 https를 대응할 수 있습니다.
  • 각 포트를 분리하여, 백엔드 서버 등 포트를 나눈다,