2023. 4. 2. 16:12ㆍReact/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를 대응할 수 있습니다.
- 각 포트를 분리하여, 백엔드 서버 등 포트를 나눈다,
'React > Next.js' 카테고리의 다른 글
Next13(app beta) 써본 후기 (0) | 2023.04.30 |
---|---|
Next에서 정적 미디어파일 사용하기 (0) | 2023.03.19 |
한땀한땀 Next로 프로젝트 마이그레이션 하기 (1) | 2023.03.17 |
Next.js로 배포해보는 gh-pages (1) | 2022.11.01 |
[TIL] NextJS는 window를 바로 접근할 수 없다. (window is not defined) (0) | 2022.10.28 |