[AWS EC2] 배포를 해야 하는데, 막막할 때 (feat. pm2, NGINX, Certbot, Route53)

SUNG JE KIM·2023년 3월 22일
30
post-thumbnail

이번에 개인 프로젝트 배포를 어떻게 하였는지, 배포할 때 마주쳤던 것들을 위주로 적을 예정이다.

필자는 NextJS를 이용한 개인 프로젝트를 배포해야 했고, 가비아에서 도메인을 구입한 상황이다.

https://ap-northeast-2.console.aws.amazon.com/ec2/v2/home
위 링크에 들어가서 인스턴스 시작을 할 것이다.


1. 인스턴스 생성

인스턴스 시작을 누르면 생성창으로 이동하게 되는데, 이 부분은 사실 다른 글들과 유사하다.
그저 따라오기만 하면 되는 부분이라고 볼 수 있다.

1-1. 이름과 OS 설정


여러 글에서 보았는데, OS는 다들 Ubuntu의 22.04가 무난한 선택이라고 하셔서, 필자도 그렇게 하였다.

1-2. 인스턴스 유형 선택


또한 인스턴스 유형에 있어서도 t2.micro가 프리티어(회원가입 후 12개월 무료) 사용도 가능하고 무난하다고 하여서 선택한 이유다.

1-3. 키페어 생성


새 키페어 생성을 누른다.

마음에 드는 키페어 이름을 적은 후에 키 페어 설정 버튼을 누르면 키페어가 생성이 된다.

⚠️주의 : 키페어는 ssh 접속의 인증 수단으로, 각별히 관리해야 한다.⚠️

필자는 아래와 같이 해당 프로젝트 폴더와 나란히 놔둠.

1-4. 네트워크 설정, 스토리지 구성, 고급 세부 정보 등

이제 키페어 이후의 생성 시 설정은 일단 넘어가고, 네트워크 설정 부분은 인스턴스를 생성 완료한 후에 설정을 손 볼 것이다.

이제 우측 하단의 인스턴스 시작을 누르면, 인스턴스가 생성이 된다.


2. 탄력적 IP

탄력적 IP란, 고정된 퍼블릭 IP라고 생각을 하면 된다.

우리가 생성한 인스턴스 즉, 우리가 AWS에서 빌린 EC2라는 컴퓨터를 킬 때마다, 해당 인스턴스는 새로운 IP를 할당 받는데 그것이 경험상 ssh 접속을 할 때마다 굉장히 우리를 귀찮게 한다.

그래서 EC2의 변덕스러운 IP를 고정시키는 것이 탄력적 IP다.

2-1. 탄력적 IP 생성


탄력적 IP (EC2 기능)으로 이동하여

탄력적 IP 주소 할당을 클릭한다.

태그 같은 경우에는 필수적이진 않고, 이제 우측 하단에 '할당'을 클릭하게 되면 탄력적 IP 하나가 생성이 된다.

이렇게 생성된 IP를 나는 일단 velog-sung-je-kim으로 이름을 바꿨다.
(이전에 생성한 것과 헷갈리지 않기 위해 이름을 부여 해줬다.)

2-2. 탄력적 IP를 EC2에 할당


해당 탄력적 IP 주소 리스트에서 방금 막 만든 탄력적 IP를 선택한 후에 '작업'을 선택하고, '탄력적 IP 주소 연결'을 누른다.

연결을 원하는 인스턴스를 선택을 하고, 프라이빗 IP 주소를 선택하는데 필자는 AWS에서 추천하는(?) 거 하나가 뜨길래 그걸로 연결하였다.
크게 중요한 부분은 아닌 거 같다.
그리고 우측 하단에 연결을 누르게 되면 성공적으로 연결이 되는 모습을 볼 수 있다.

2-3. 탄력적 IP 확인

해당 인스턴스로 이동하여 해당 인스턴스의 세부 정보를 확인을 해보게 되면 정상적으로 할당이 된 모습을 볼 수 있다.


3. 인바운드 규칙

이제는 인바운드 규칙을 편집할 것이다. 여기서 "인바운드 규칙"이라는 것을 설명하자면,
"'내 방화벽으로 들어올 때'의 규칙"이 인바운드 규칙이다.
밖에서 안으로들어오는 IP별의 요청을 제한할 수 있고, PORT 별로도 요청을 제한할 수도 있는 것을 설정하는 것이 인바운드 규칙 설정하기다.

추가적으로 아웃바운드 규칙을 설정해야 되는 경우를 간단히 예시만 짚고 넘어가자면,
어떠한 해커가 '내 사이트'에서 해커가 외부로 출금 요청을 보내고 있다면, 지금 당장 아웃바운드 규칙 설정 글로 가보시는게 좋을 듯 하다.

3-1. 인바운드 규칙 확인

인스턴스 목록으로 이동하고, 해당 인스턴스를 클릭한 후에 '보안'을 눌러보면, 인바운드 규칙이 하나 밖에 없을 것이다.

보안 그룹을 클릭하여 이동을 한 뒤에

인바운드 규칙 편집을 눌러주어서 편집을 진행한다.

3-2. 인바운드 규칙 설정


필자는 위와 같이 설정했다.

사용자가 8080 PORT를 통해 들어올 수 있도록 인바운드 규칙을 설정하였고,

package.json의 build된 파일들을 start로 실행시키는데, start script 또한 8080 PORT로 수정해줬다.

⚠️겪은 문제⚠️

ssh를 왜 0.0.0.0/0으로 설정했는지는 아래와 같다.
ssh 같은 경우에 '내 IP'로 설정하는 경우도 있는데 필자 또한 '내 IP'로 설정하였다가 설정 당일날은 정말 정상적으로 잘 되었는데,
다음날 ssh 접속을 하려니 안됐어서 확인해보니, 내 IP가 카페 wifi 때문인지 지속적으로 바뀌는 현상이 있어서 ssh 접속 안된다고 3시간을 버린 기억이 있다.


4. 인스턴스에 접속

이제 .pem을 저장해둔 곳으로 가서 ssh 접속을 해볼 것이다.
ssh 통해 해당 인스턴스로 접속을 해서, 우리가 빌린 AWS EC2 컴퓨터 기초 세팅할 것이다.
우리가 사용하게 될 것은 아래와 같다.

  • nvm을 통해서 Node 버전 관리
  • npm 또는 yarn과 같은 사용했던 package manager
  • GitHub에 저장되어 있는 내 프로젝트 코드 인스턴스에 삽입하기
  • 무중단 배포를 위한 'pm2'
  • 리버스 프록시 및 HTTPS 설정을 위한 'NGINX'
  • Let's Encrypt에서 발급해주는 SSL 인증서 발급 그리고 자동 갱신 도구 'Certbot'

4-1. ssh 명령어 확인 후 인스턴스에 연결


위 사진 처럼 인스턴스 리스트로 이동하게 되면 '연결'을 클릭한 후 확인하게 되면 AWS에서 친절하게 어떻게 명령어를 치면 연결이 되는지 순차적으로 설명 되어 있다.
iTerm(터미널)을 킨 뒤에 해당 .pem 이 있는 곳으로 이동하여 아래 명령어를 사용하였다.

- chmod 400 ".pem 파일 이름"
- ssh -i ".pem 파일 이름" ubuntu@"퍼블릭 IPv4 DNS"

위와 같이 명령어를 기입하고, 아래와 같이 yes라고 하면?


성공적으로 접속한 모습을 볼 수 있다~~!!

4-2. 인스턴스 ubuntu 업데이트


위 사진과 같이 git을 제외하고는 package manager도 없는 상태임을 알 수 있다.

- sudo apt-get update

명령어를 입력하여 ubuntu 관리 버전을 업데이트 시켜준다. 뭐가 길게 줄줄 뜨는데 기다리면 완료가 된다.

4-3. nvm 설치

아래 두 명령어를 통해서 설치, 설치 확인을 할 것이다.

- curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
- command -v nvm /** 버전 확인 */

설치를 진행하고 command -v nvm을 치면 nvm이 나오면 성공적으로 설치가 완료된 것이다.
⚠️설치를 했는데 버전 확인 명령어에 무반응이예요⚠️

이런 식으로 nvm이 뜨지 않는다면 iTerm(터미널)을 껐다가 다시 켜보면 된다.

위 처럼 nvm이 나오면 성공적으로 설치된 것이다.

4-4. Node 설치

- nvm install "버전"
- nvm use "버전"


필자는 "버전"을 18.15.0으로 설치를 하였고, 설치를 진행한 뒤에 정상적으로 설치되었는지 확인해보았다.

GOOD.

4-5. Yarn 설치

yarn을 사용하지 않는다면 이 부분은 건너 뛰어도 무방하다.
이미 위에서 확인을 했겠지만 npm은 node를 설치할 때 같이 설치 되었기 때문이다.

- npm i -g yarn /** yarn 설치 */
- yarn --version /** yarn이 성공적으로 설치 되었는지 확인 */


위 처럼 yarn이 성공적으로 설치된 것을 확인할 수 있다.

4-6. 프로젝트 코드 인스턴스에 삽입

EC2 인스턴스에서 배포할 프로젝트를 clone을 진행한다.

- git clone "프로젝트 레포지터리 주소"

- npm i
- yarn install

clone을 성공적으로 진행했다면 사용하는 package manager를 통해 install을 진행한 후, 이제 필요한 환경 변수들을 넣어주고, package manager를 통해서 build를 진행한다.

4-7. 브라우저에서 확인해보기

성공적으로 build 되었다면, yarn start를 통해서 확인을 해본다.

앞서 start script에 -p 8080을 추가해주고, 인바운드 규칙에서 사용자가 8080으로 들어올 수 있도록 설정을 해주어서, '퍼블릭 IPv4 주소:8080'으로 브라우저에서 들어가보면

성공적으로 나오는 모습을 확인할 수 있다.


5. 무중단 배포를 위한 pm2

내 컴퓨터가 꺼지게 된다면 또는 내가 인스턴스와 연결을 종료한다면, 내가 켜둔 인스턴스가 연결 종료와 함께 수면 상태에 들어간다.
365일 24시간 무중단으로 인스턴스를 활용해먹어야 하니 pm2 설정을 해야 한다.

5-1. pm2 설치

아래의 명령어를 이용해서 pm2를 설치해주도록 하자

- npm i -g pm2

해당 명령어를 실행한 후

pm2 list

를 쳐봤을 때 아래와 같이 나오면 성공적으로 설치가 된 것이다

그리고 list에는 아무것도 뜨지 않을 것이다.

5-2. 무중단 배포 활성화

사용하는 package manager 활용해서 pm2를 활성화 시켜주면 된다.

- pm2 start yarn -w -i 0 --name "velog-sung-je-kim" -- start
/** yarn 활용해서 시작 */
- pm2 start npm --name "velog-sung-je-kim" -w -i 0 -- run start
/** npm 활용해서 시작 */
  • -w(--watch) : 파일의 변경 시 자동으로 재시작되는 옵션을 활성화 시키는 것
  • -i 0(코어 갯수) : Node.js의 싱글 스레드를 보완하기 위한 CPU 코어 수만큼 프로세스를 생성하는 클러스터 모드

    pm2 list에 성공적으로 하나 생긴 것이 보인다. 그리고 '~.'을 통해서 인스턴스를 빠져나가도 무중단 배포가 활성화 되어 있기 때문에 지속적으로 서버가 활성화 되어 있다.

6. 도메인 연결

Route53을 통해서 DNS를 구축하고, 도메인을 인스턴스의 퍼블릭IP로 라우팅 시켜줄 작업니다.

6-1. Route53 호스팅 영역 생성

AWS에서 Route53 페이지로 이동을 한다.

좌측 사이드바에서 호스팅 영역을 클릭한 후에 호스팅 영역 생성을 클릭한다.

도메인 주소를 기재하고 새 호스팅 영역을 생성한다.

그러면 해당 도메인의 레코드들이 생기는데, 우리는 하나의 레코드를 더 만들어줄 것이다.
레코드 생성을 누른 뒤에 아래와 같이 값에 퍼블릭 IP를 기재해주고 레코드를 생성한다. 퍼블릭 IP로 라우팅해줄 레코드다.

6-2. 가비아에서 네임서버 편집

가비아로 이동해서 Route53에서 기재한 도메인의 관리 탭으로 이동한다.

관리 탭으로 이동하여 네임서버 '설정'을 눌러 편집할 것이다.
1차, 2차, 3차, 4차를 이전에 AWS에서 생성한 호스팅 영역의 NS 유형에 해당하는 값/트래픽 라우팅 대상 4가지로 대체할 것이다.
편집을 완료하고 적용되는데 시간이 좀 걸리기 때문에 기다렸다 도메인을 통해 접속이 가능하다.


7. NginX

NginX에 대해서는 아직 미흡해서 추후에 또 NginX 관련 글을 쓸 예정이다.
NginX를 이용하여 리버스 프록시를 적용할 것이다.
간단히 설명하자면 NginX를 클라이언트와 우리 어플리케이션 사이에 배치를 하는 것이다.

7-1. NginX 설치

아래 명령어를 통해서 NginX를 설치해준다.

- sudo apt-get install nginx -y	/** NginX 설치 */
- nginx -v 	/** 잘 설치 되어 있는지 확인 */

설치 중에 아래와 같이 터미널이 변하면 편하게 엔터 누르면 된다.

7-2. 리버스 프록시 적용

우리는 아래의 파일을 vim으로 편집을 해서 리버스 프록시를 적용할 것이다.

- sudo vim /etc/nginx/sites-available/default /** 편집할 파일 */
/** 첨부할 코드 */
server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name 도메인;
        location / {
                proxy_pass http://퍼블릭IP:8080;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
        }
}


위에 대해서 설명을 첨부하자면 우리는 여태 8080 PORT로 사용자의 접속을 허용했다. 근데 사용자가 접속을 하려면 '도메인:8080' 이런 식으로 PORT 번호까지 기입을 해야지 해당 서비스로 이동할 수 있는데, 이것은 사용자 입장에서 너무 불편하다.
그래서 사용자와 내 어플리케이션(PORT === 8080) 사이에 NginX(PORT === 80)를 배치하여 PORT 번호를 기입하지 않고도 사용자가 우리의 서비스에 접속을 하면 8080 PORT로 이동 시키는 것이다.

7-3. NginX 서비스 재시작

아래의 명령어로 NginX 서비스를 리로드해주고 브라우저에서 확인해보면,

- sudo nginx -t
- sudo systemctl reload nginx

첫 번째 사진은 이전에 8080 PORT를 기입해줘야 접속이 가능했는데, 두 번째 사진을 보면 8080 PORT를 기입하지 않아도 내 어플리케이션으로 접속할 수 있는 모습을 볼 수 있다.


도메인을 통해서도 확인 가능.


8. HTTPS 적용

Let's Encrypt에서 90일 유효기간이 있는 SSL 인증서 발급을 받은 뒤, Certbot으로 SSL 인증서를 자동 갱신하는 작업을 해줄 것이다.

8-1. Certbot 설치 후 인증서 발급

- sudo snap install certbot --classic
/** certbot 설치 */
- sudo certbot --nginx
/** SSL 인증서 발급 */


이메일을 입렵하라고 위 처럼 나오는데 만료 기간이 얼마 남지 않았을 때, 메일을 받을 주소를 기입하고 Enter를 누르면 된다.

무슨 서비스에 동의 하는지에 대해서 물어보는데 must agree라고 하니 동의한다고 해준다.

뉴스레터 이메일 받는 것의 동의여부에 대해서 물어보는데, 필자는 굳이 싶어서 동의하지 않았다.

어떠한 도메인에 대해서 SSL 인증서를 받을 것인지에 대해서 물어보는데, 발급 받을 도메인의 번호를 기입하면 된다.

성공적으로 90일 짜리 SSL 인증서를 발급 받았다.

8-2. Certbot으로 자동 갱신 설정

아래 명령어를 통해서 설정 파일을 열게 되면 사진과 같이 편집기를 선택하라고 뜨는데, 거기서 편한 편집기를 사용하면 된다.

- sudo crontab -e
/** 설정 파일 열기 */


그리고 맨 밑에 아래 명령어를 기입해주고 저장한다.

0 18 1 * * certbot renew --renew-hook="sudo systemctl restart nginx"

기입하고 Ctrl + X -> y -> Enter로 빠져나오면 된다.

이렇게 설정하면 매월 1일 오후 6시마다 인증서를 갱신하고 NGINX를 재시작하는 명령어가 실행된다. 추후에 certbot에 대해서도 깊게 다뤄볼 예정이다.


9. 최종 확인

HTTPS가 설정 되었는지 확인을 해보면 HTTPS가 잘 적용된 것을 확인할 수 있다.

이렇게 해서 어떻게 배포를 하는지에 대해서 알아보았다.
현업에서는 지금 필자가 했던 방법보다 더 복잡하고 심도 있을 거라고 생각하고, 더 심도 있게 알기 위해서 추후에 더 공부한 뒤에 또 다른 글로 하나하나 다뤄볼 예정이다.

큰 도움이 되었던 문서

5개의 댓글

comment-user-thumbnail
2023년 3월 27일

재밌네요ㅋㅋㅋ 잘 봤습니다.

1개의 답글
comment-user-thumbnail
2023년 3월 29일

잘 봤습니다.

1개의 답글
comment-user-thumbnail
2023년 12월 25일

감사합니다!! 덕분에 서비스 배포 도메인 연결해서 처음으로 해보았습니다!! 많은 도움이 됐어요 ㅎㅎ

답글 달기