본문 바로가기
개발(Development)/Etc(기타)

[AWS|GCP EC2] React+Next.js HTTPS 도메인 적용 방법 (Nginx 리버스프록시 연결 + snapd SSL 인증서 자동 갱신)

by 카레유 2022. 9. 23.

# AWS | GCP : EC2에서 React+Next.js 서버 https 적용방법

AWS나 EC2 인스턴스에서 Next.js 기반의 React 프로젝트를 구동하고,

SSL인증서를 설치(+자동갱신)하여 HTTPS로 연결하는 방법을 정리한다.

이 글은 Nginx 리버스 프록시와 Certbot을 통한 Let's Ecrypt 인증서를 사용한다.

 

# 작업 순서 및 내용

순서 작업 내용
1 도메인 AWS|GCP IP 연결 설정
2 Next.js 배포용 설정 추가(+GitHub 업로드)
3 EC2 접속 및  Node.js 설치
4 GitHub에서 소스코드 Clone 해오기
5 npm 패키지 설치
6 .env 설정파일 생성
7 Next.js프론트 서버 빌드  구동
8 Nginx 설치/설정/구동
9 certbot-auto 설치
10 HTTPS SSL 인증서 자동갱신

 

만약 AWS, GCP 에서 EC2 인스턴스 생성, 접속방법이 궁금하다면 아래글 참고

[AWS] EC2 Node.js, Mysql 설치 및 세팅 방법

[GCP] Compute Engine에 VM인스턴스 생성하는 방법(구글클라우드플랫폼)

 

주의: 메모리 1GB이하의 EC2인스턴스에서 Next.js 프로젝트 빌드시, 메모리 부족으로 빌드가 불가할 수 있다.(해결책은 본문에 적었다)


1. 도메인 연결 설정

- 도메인 주소로 접속시, EC 인스턴스의 ip로 접속할 수 있도록 설정한다.

- DNS 사이트(가비아, DNSZi 등)에 가서 A레코드를 "AWS 퍼블릭IPv4주소" (GCP는 외부IP)로 설정해둔다.

 

 

2. 로컬: Next.js 프로젝트 설정

- 개발중인 로컬환경에서 배포를 위해 아래의 작업을 먼저 해준다.

1) pm2, cross-env 모듈 설치

npm install pm2 cross-env

# resolve 관련 에러 뜨면 강제 설치
npm install pm2 cross-env --legacy-peer-deps

 

2) start 스크립트 변경: cross-env를 통해 3000번 포트에서 구동하도록 설정

"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "cross-env NODE_ENV=production next start -p 3000",
    "lint": "next lint"
  }

 

3) Git Hub 등에 push

- 잘 모른다면 아래 글 참고

- .env 등 보안이 필요한 설정파일은 .gitignore 등 제외 처리해주자.

[Github] 터미널에서 GitHub Repository 연동 사용 방법: git remote, push

 

 

3. EC2 접속: Node.js 설치

1) EC2 인스턴스 접속

 

2) Node.js 설치

- 바로  Node.js 특정 버전을 설치해도 되고,

# *** node.js 바로 설치

# 루트권한 사용
sudo su

# apt-get 업데이트
sudo apt-get update

# 특정 모듈 설치 에러 방지(bcrypt, sharp 등)
sudo apt-get install -y build-essential

# curl 설치
sudo apt-get install curl

# node.js 16 버전 설치: 원하는 버전으로 변경해서 설치하면 된다
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash --
apt-get install -y nodejs

 

- nvm이라는 node 버전 관리도구를 통해 설치해도 된다.(참고: https://github.com/nvm-sh/nvm )

# *** nvm 사용

# 루트권한 사용
sudo su

# apt-get 업데이트
sudo apt-get update

# 특정 모듈 설치 에러 방지(bcrypt, sharp 등)
sudo apt-get install -y build-essential

# curl 설치
sudo apt-get install curl

# nvm 설치(node 버전 관리용)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash

# nvm 활성화
source ~/.bashrc

# nvm 정상 설치 확인
nvm -v

# 설치 가능한 node.js 버전 확인
nvm ls-remote

# node.js 특정 버전 설치. 여러 버전을 설치할 수 있다. (특정 버전이 필요한게 아니라면, 최신 LTS 추천)
nvm install 16.17.0

# node, npm 설치 확인
node -v
npm -v

# 버전 변경 (원하는 버전을 아래와 같이 선택할 수 있다.)
nvm use 16.17.0
nvm use default

 

 

4. Git Clone 해오기

- EC2 인스턴스에서 적절히 디렉토리를 생성하고,

- GitHub 등에서 소스코드를 Clone 한다.

# 디렉터리 생성
mkdir service

# 디렉터리 진입
cd service

# Git Clone
git clone https://github.com/아이디/레퍼지터리.git

 

 

5. npm 패키지 설치

- 서비스 폴더에 들어가서, Next.js 프로젝트에서 사용중인 모듈들을 설치한다.

# package.json에 기술된 모듈들 모두 설치
npm install

# resolve 관련 에러 뜨면 아래 명령어로 강제 설치
npm install --legacy-peer-deps

 

 

6 .env 파일 만들기

- .env 파일 생성 및 vim 에디터로 열기

vim .env

 

- .env 파일내용 입력: a 나 i 누르면, 글자 입력 가능

- 저장: esc 한번 누르고, :wq 엔터치면 저장하고 나간다.

- 확인: cat .env 하면 파일 내용 확인 가능

 

 

7. Next.js프론트 서버 빌드 구동

- next.js 프로젝트를 배포용으로 빌드해준다.

npm run build


- pm2로 Next.js 프론트 서버를 구동해준다. (package.json 파일의 start 명령어를 위에서 설정했어야 한다.)

npx pm2 start npm -- start

#재구동시엔 npx pm2 reload all 명령어 사용

 

여기서 이제 첫 번째 난관에 부딪칠 수 있다.

GCP 기준 EC2인스턴스 사양이 Micro(메모리1GB) 인 경우, 빌드 에러가 나거나 먹통되어 멈춰버릴 수 있다.

 

인스턴스 사양이 너무 낮아 메모리 부족 등의 이슈로 빌드가 되지 않는 것이다.
해결책은 3가지가 있다.(필자는 결국 3번째 해결책을 사용했다)


1) 로컬에서 빌드 >  GitHub Push > EC2인스턴스 Pull

- 사양 낮은 EC2인스턴스에서 빌드하지 않고,  빵빵한 내 컴퓨터에서 빌드한 다음

- GitHub로 빌드된 코드(.next 폴더)까지 Push하고 EC2에서 Pull 받는 것이다.

- 그러나 이 또한 github 업로드 용량이 100mb 이하라 안될 수도 있다. (아래 에러가 뜬다.)

remote: error: GH001: Large files detected.

You may want to try Git Large File Storage - https://git-lfs.github.com

! [remote rejected] main -> main (pre-receive hook declined)

error: 레퍼런스를  푸시하는데 실패했습니다

 

2) Lazy/Dynamic import 등으 최적화한다.

- 이건 코딩의 영역이므로 각자 알아서 해보자. 근데 큰 효과는 보기 힘들었다.

 

3) 높은 사양의 EC2 인스턴스 사용

- GCP 기준 Small(메모리 2GB) 인스턴스에선 빌드에 성공했다.

- 앞으론 비용 부담이 있더라도 메모리 2GB 이상의 인스턴스를 사용할 계획이다.

- 이 경우, 기존 인스턴스를 삭제하고 새 인스턴스를 생성 후 위에서 한 작업을 다시 다 해줘야 한다.

 

---- 결과적으로 빌드, 구동이 완료되어 아래 화면이 나오면 성공이다!

 

이제 http://도메인주소:포트번호 로 접속이 될 것이다!

짝짝짝! 축하합니다.

(혹시 접속되지 않더라도 그냥 넘어가자.

현재 포트번호가 80이 아닌 3000 등으로 설정되어 있어서, 접속 허용이 되지 않기 때문인데,

GCP의 경우, VPC네트워크>방화벽>방화벽정책만들기 에서 해당 port 접속을 허용해주면 되지만,

어차피 아래에서 Nginx 로 80, 443 포트로 받을 것이므로 그냥 넘어가도 된다.)


자! 이제 Nginx 리버스프록시를 이용해 HTTPS를 적용해보자.

 

Nginx 에 https 인증서를 설치해두고,

브라우저에서 "도메인주소:80" 이나 "도메인주소:443" 으로 접속시,

Nginx 가 받아서 Next.js 서버의 3000번 포트로 연결하여 HTTPS가 적용되는 방식이다.

 

 

8. Nginx 설치/설정/구동

1) 먼저 Nginx 서버를 설치해준다.

# nginx 설치 (-y 옵션으로 모든옵션을 자동 yes 처리)
sudo apt-get install nginx -y

# nginsx 설치 확인
nginx -v

 

2) 설정파일을 수정해준다.

- Nginx 버전에 따라 설정 파일의 위치가 다를 수 있는니, 필요시 구글링 해보자.

# 설정파일 열기
vim /etc/nginx/nginx.conf

 

- server 항목을 아래 처럼 수정해준다.

# http 항목 내부에 아래 내용 추가 
# 미리 아래 정보는 적어 놔야, certbot가 이걸 인식해서 알아서 해줌.
# 도메인 주소는 http 빼고 적는다.
# 포트 번호 3000도 잊지 말자.
server{
	server_name 내도메인.com;
	listen 80;
	location / {
		proxy_set_header HOST $host;
		proxy_pass http://127.0.0.1:3000;
		proxy_redirect off;
	}
}

 

3) Nginx 서버를 구동해준다.

# Nginx 실행
sudo systemctl start nginx

# nginx 상태 확인 
sudo systemctl status nginx

# 참고: 빠져나올 땐, Contorl + C

# 참고: Nginx는 설정파일 변경시 재구동 해줘야 한다.
# 재실행: sudo systemctl restart nginx

 

4) 브라우저에서 도메인주소로 접속

- 아래 화면이 나오면 성공이다.

*** 참고

- 이미 사용중인 포트에서 서버 구동시 에러가 발생할 수 있다.

- 이 경우, 해당 포트를 사용 중인 프로세스를 종료해주면 된다.

# 80 번 포트 사용중인 프로그램 확인(lsof는 list open file의 약자)
sudo lsof -i tcp:80

# Process ID에 해당하는 프로세스 끄기
sudo kill -0 PID

# pm2 로 구동중인 프로세스 끄기
npx pm2 kill

 

9. certbot-auto 설치

- cerbot-auto 는 Let's Encrypt SSL 인증서를 설치/갱신해주는 프로그램이다.

- 과거에는 wget https://dl.eff.org/certbot-auto 명령어로 설치했으나 더이상 지원되지 않는다.(404에러 뜬다)

Resolving dl.eff.org (dl.eff.org)... 151.101.192.201, 151.101.128.201, 151.101.64.201, ...

Connecting to dl.eff.org (dl.eff.org)|151.101.192.201|:443... connected.

HTTP request sent, awaiting response... 404 Not Found

2022-08-30 03:39:30 ERROR 404: Not Found.

 

- 다행히 snapd를 통해 더 쉽고 간편하게 설치할 수 있다.

- 왠만한 Ubuntu OS에는 snapd가 기본 설치되어 있으며, 혹시 설치가 안 되어 있다면 아래 링크에서 해당 OS를 클릭하여 확인해보자.

https://snapcraft.io/docs/installing-snapd

 

* 혹시 기존에 wget으로 certbot을 설치해준 경우라면, 아래코드로 제거하고 시작한다.

sudo apt-get remove certbot
sudo dnf remove certbot
sudo yum remove certbot

 

1) Certbot 설치

- 드디어 마지막 작업인 cetbot을 설치하자.

# 최신버전으로 snapd를 업그레이드 해준다.
sudo snap install core; sudo snap refresh core

# certbot을 설치한다.
sudo snap install --classic certbot

# certbot 명령어 실행이 가능하도록 설정한다.
sudo ln -s /snap/bin/certbot /usr/bin/certbot

 

2) certbot 인증서 설치 및 설정 적용

sudo certbot --nginx

 

- 아래 화면이 나오면,

- 이메일(인증서 기한 지나기 전에 알려줌)을 정확히 써주고, 계속 y를 눌러주다가

- Which names would you like to activate HTTPS for? 라고 나오면 적용할 도메인(아마도 1번)을 골라준다.

 

- 아까 설정했던 Nginx 설정파일을 다시 열어보면, certbot 이 알아서 ssl 관련 설정을 추가해두었을 것이다.

 cat /etc/nginx/nginx.conf

 

3) Nginx 재시작

이제 Nginx 를 재시작하여 certbot이 바꿔준 설정을 적용하자!

sudo systemctl restart nginx

 

4) 브라우저 접속

-이제 http:// 도메인, https:// 도메인으로 접속하면, 모두 https://도메인 으로 접속되면서 좌물쇠가 채워져있을 것이다.

 

끝!


10. CertBot HTTPS SSL 인증서 자동갱신 방법

Let's Encrypt SSL 인증서는 유효기간이 3개월이므로, 매번 연장해줘야 한다.

 

하지만 이미 3개월 자동 연장이 처리되어 있으므로 신경쓸 필요 없다!

snapd 로 설치한 certbot은 crontab이 내장되어 있어서 인증서 만료 전에 자동으로 갱신하도록 타이머가 설정된다.

 

진짜로 되는지 확인하고 싶다면, 아래 명령어로 인증서 갱신 시뮬레이션을 테스트해볼 있다.

sudo certbot renew --dry-run

 

위와 같이 뜬다면 certbot 3개월 SSL 인증서 자동갱신이 잘 적용되어 있는 것이다.


힘들게 구축하신 서비스가 잘 되기를 바라겠습니다!

 

화이팅!

 

마지막 참고:

만약 SSR용 Next.js 가 아닌 단순 React(CSR)프로젝트라면,

CloudFlare를 사용해 DNS, IP 설정만 해주면 쉽게 HTTPS 를 적용할 수 있다.

 

 

댓글