이번에 개인 프로젝트를 진행하면서 배포도 진행을 하게 되었다 필자는 Next와 Express를 이용한 개인 프로젝트를 배포해야 했고 가비아에서 도메인을 구입한 상황이다
https://ap-northeast-2.console.aws.amazon.com/ec2/v2/home
https://ap-northeast-2.console.aws.amazon.com/ec2/v2/home
ap-northeast-2.console.aws.amazon.com
위 링크에 들어가서 인스턴스 시작을 할 것이다.
인스턴스 시작을 누르면 생성창으로 이동하게 된다
os는 Ubuntu 22.04를 선택했다 여기서 주의 할 점은 프리티어 (회원가입 후 12개월 무료) 를 선택해야 과금이 되지 않는다 .
또한 인스턴스 유형도 t2.micro를 선택했다 이유는 역시 프리티어이기 때문 다만 메모리가 많이 작다는 문제가 있다.
다음으로 키페어의 이름을 적은 다음 키페어 설정 버튼을 클릭하면 키페어가 생성된다.
여기서 주의할 점은 키페어는 ssh 접속의 인증 수단이기 때문에 절대로 잃어버리면 안된다 또한 github에도 올리면 안된다.
다음과 같이 추가 설정도 완료한 이후에 인스턴스 시작을 눌러 인스턴스를 생성한다.
다음으로는 탄력적 IP에 대한 부분이다 우리가 AWS에서 빌린 EC2는 컴퓨터를 끄고 킬때마다 새로운 ip를 할당받는다 그리고 ssh 접속을 할 때마다 바뀐 IP를 매번 입력해줘야 하는 번거로움이 생기게 된다 따라서 고정적인 ip 주소를 발급 받을 건데 이것이 탄력적 IP이다.
EC2 -> 탄력적 ip주소 -> 탄력적 ip주소 할당으로 접속한다. 할당해주고자 하는 인스턴스를 선택한 뒤 Ip를 할당한다.
할당을 완료한 이후 해당 인스턴스 세부정보에서 할당된 탄력적Ip주소를 확인 할 수 있다.
참고로 탄력적 IP는 원래 유료다 하지만 실행중인 인스턴스 하나까지는 할당을 한다는 전제하에 무료로 이용할 수 있다
대신 어디까지나 실행중인 인스턴스에만 해당이 되기 때문에 나중에 인스턴스를 종료하게 된다면 반드시 할당 받은 ip도 삭제 해야 한다 그렇지 않으면 과금이 된다 ㅜㅜ
다음으로는 이제 인바운드 규칙을 편집해 줄것이다 인바운드 규칙이란 "내 방화벽으로 들어올 때의 규칙" 이다.
밖에서 안으로 들어오는 IP의 요철을 제한 할 수 있고 포트 별로 요청을 제한할 수 있도록 설정하는 것이 인바운드 규칙 설정이다.
인스턴스에서 보안 그룹을 이동한 다음 인바운드 규칙에서 인바운드 규칙 편집을 클릭한다.
필자는 이렇게 설정했다 인스턴스 하나에 프론트 서버와 백 서버를 돌릴 것이기 때문에 프론트 서버에서 3000포트를 쓰고
백엔드 서버에서 4000포트를 쓸 수 있도록 설정했다.
프론트 서버와 백 서버도 각각 알맞은 포트에서 실행하도록 바꿔주었다.
이제 해당 인스턴스로 ssh 접속을 해볼 것이다 ssh 를 통해 해당 인스턴스로 접속을 해서 ec2 컴퓨터의 기초 세팅을 진행해야 한다 다음은 우리가 해야 할 것들이다.
- NVM을 통해서 Node 버전 관리
- NPM 또는 yarn과 같은 사용했던 package manager
- 깃허브에 저장되어 있는 프로젝트 코드 Pull 받기
- 무중단 배포를 위한 pm2
- 리버스 프록시 및 HTTPS 설정을 위한 NGINX
- SSL 인증서 발급 및 자동 갱신 설정
먼저 터미널을 킨다음 위에서 내려받은 키페어 파일이 있는 경로로 가서 다음과 같이 명령어를 입력한다.
ssh -i ".pem 파일 이름" ubuntu@"퍼블릭 IPv4 DNS"
성공적으로 접속한 모습을 확인 할 수 있다.
sudo apt-get update
위에 같이 명령어를 입력해서 ubuntu 관리 버전을 업데이트 시켜준다
다음으로 Node 버전 관리를 위해 Nvm을 설치할 것이다 아래 두 명령어를 통해서 설치와 설치 확인을 한다.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
command -v nvm /** 버전 확인 */
설치를 진행하고 command -v nvm을 입력하면 nvm이 나오면 설치가 완료 된것이다
nvm install "버전"
- nvm use "버전"
위의 명령어를 입력해서 Node를 설치한다.
필자는 버전을 18.15.0으로 설치 했다.
다음으로 git clone 명령어를 이용해서 만든 프로젝트 코드를 인스턴스에 내려받는다
git clone '내려받을 깃 레포 주소"
clone을 성공적으로 진행했다면 사용하는 패키지 매니저를 통해 Install을 진행하고 필요한 환경변수들을 넣어주고
build를 진행한다. build 를 마친후 프론트 서버에서 npm start를 해주고
앞서 start script에 3000포트로 접속할 수 있도록 했기에 퍼블릭 Ip 주소 3000포트로 들어가보면
우리가 쓰고 있는 인스턴스에서 프론트 서버가 잘 실행되어 3000포트로 접근이 가능한 것을 확인 할 수 있다.
만약 내가 쓰고 있는 컴퓨터가 종료된다면 아니면 내가 인스턴스와 연결이 종료된다면 인스턴스가 연결 종료와 함께 수면 상태에 들어간다 365일 24시간 무중단으로 인스턴스를 활용해야 하니 무중단 배포를 진행해보도록 하겠다,
npm i -g pm2
해당 명령어를 통해 pm2를 설치하도록 하자.
pm2 list
다음 명령어를 입력하면.
이런 화면이 나올것이다 설치가 성공적으로 완료되었다.
다음으로 사용하는 package manager를 활용해서 pm2를 활성화 시켜주면 된다
필자는 다음과 같이 설정했다.
"start": "cross-env NODE_ENV=production pm2 start app.js",
npm start를 눌렀을 때 pm2가 성공적으로 실행되는 것을 확인할 수 있다.
현재 pm2로 돌리고 있는 서버는 백엔드 서버 하나다 필자는 프론트서버도 무중단으로 배포해야 하기 때문에
프론트 폴더로 이동한 후 같은 방식으로 pm2로 무중단 배포를 할 것이다.
프론트 서버와 백엔드 서버 2개가 pm2에서 실행되고 있는 것을 확인 할 수 있다.
다음 순서로 도메인을 연결하겠다. 필자는 AWS Route53을 통해서 DNS를 구축하고 도메인을 인스턴스의
퍼블릭 IP로 라우팅 시켜줄것이다.
Route53에서 호스팅영역 생성을 클릭한다.
그리고 도메인 주소를 기재하고 새 호스팅 영역을 생성한다.
그러면 해당 도메인의 레코들이 생기는데 우리는 하나의 레코드를 더 만들어줄것이다.
레코드 생성을 누른 뒤에 아래와 같이 값에 퍼블릭 IP를 기재해주고 레코드를 생성한다 퍼블릭IP로
라우팅해줄 레코드다.
다음으로 필자는 가비아에서 도메인을 구입했다 가비아로 이동해서 Route53에서 기재한 도메인의 관리탭으로 이동한다.
관리 탭으로 이동하여 네임 서버 설정을 눌러서 편집한다 1차 2차 3차 4차를 이전에 AWS에서 생성한 호스팅 영역의
NS 유형에 해당하는 값/트래픽 라우팅 대상 4가지로 대체할 것이다.
이렇게 도메인 설정까지 완료되었다.
이제 NGINX를 이용해서 리버스 프록시 를 적용해보도록 하겠다 리버스 프록시에 대해 간단하게 설명하자면
리버스 프록시란 클라이언트 요청을 대신 받아 내부 서버로 전달해주는 것을 리버스 프록시라고 한다 더 딥하게 이야기 하면 프록시란 대리라는 의미로 정보를 전달해주는 주체라고 생각하면 된다.
만약 이 프록시 없이 웹 서버를 운영한다고 가정해보자.
localhost:3000 이라고 하는 웹 서버를 열어서 운영했을 때 사용자가 갑자기 많아지거나 웹서버가 그대로 노출되어 잇기 때문에 보안적으로 위험성이 있다 여기서 Nginx를 이용해 리버르 프록시를 적용해서
사용자 -> 웹서버 가 아닌 사용자 -> NGINX -> 웹서버로 구성해서
요청을 NGINX가 대신 웹서버로 전달해주도록 구성하는 것이다.
그림으로 표현하자면 다음과 같다.
그럼 이제 NGINX를 사용해보자 아래 명령어를 이용해서 NGINX를 설치한다.
sudo apt-get install nginx -y /** NginX 설치 */
nginx -v /** 잘 설치 되어 있는지 확인 */
그리고 다음 명령어를 입력해서 아래의 파일을 편집한다.
sudo vim /etc/nginx/sites-available/default /** 편집할 파일 */
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name 도메인;
location / {
proxy_pass http://퍼블릭IP:3000;
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;
}
location /api {
proxy_pass http://퍼블릭IP:4000;
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;
}
}
위에 대해서 설명을 하자면 우리는 여태 특정 포트 (ex 3000)으로 사용자의 접속을 허용했다.
근데 사용자가 접속을 하려면 도메인:3000 이런 식으로 PORT 번호까지 기입을 해야지 해당 서비스로 이동할 수 있느데 이것은 사용자 입장에서 너무 불편하다
그래서 사용자와 내 어플리케이션 (Port === 3000) 사이에 NGINX (PORT === 80)을 배치해서 사용자가 포트 번호를 기입하지 않고도 사용자가 우리 서비스에 접속할 수 있도록 한 것이다.
또한 우리서비스는 백엔드 서버도 같은 인스턴스에 있기에 4000또한 같은 방식을 적용했다.
아래의 명령어로 NGINX를 리로드 해준다.
sudo nginx -t
sudo systemctl reload nginx
이렇게 리로드해주고 브라우저에서 확인을 해보면
포트번호 없이도 성공적으로 접속이 가능해졌다 ㅎㅎㅎ
이제 드디어 마지막 작업이다 마지막으로 HTTPS를 적용할 것이다 .
Let's Encrypt에서 90일 유효기간이 있는 ssl 인증서 발급을 받은 뒤 cerbot으로 ssl 인증서를 자동
갱신하는 작업을 해줄 것이다.
sudo snap install certbot --classic
/** certbot 설치 */
sudo certbot --nginx
/** SSL 인증서 발급 */
이메일을 입력하고 나머지 질문에 y를 누른다.
어떤 도메인에 대해서 인증서를 받을 것인지 물어보는데 발급 받을 도메인의 번호를 기입하면 된다.
아래 명령어를 통해서 설정 파일을 연다
sudo crontab -e
/** 설정 파일 열기 */
그리고 맨 밑에 아래 명령어를 기입하고 저장한다.
0 18 1 * * certbot renew --renew-hook="sudo systemctl restart nginx"
이렇게 설정하면 매월 1일 오후 6시마다 인증서를 갱신하고 Nginx를 재시작하는 명령어가 실행된다.
HTTPS가 성공적으로 적용된 모습을 확인할 수 있다.
이렇게 해서 최종적으로 배포를 완료했다 프론트 개발자이지만 웹의 전체적인 동작과정 흐름들을 몸소 느끼고 싶어서 이번 프로젝트를 통해 배포를 공부하고 적용해보았다 참 유익한 시간이였고 스스로도 시야가 넓어진거 같아 뿌듯한 느낌이 많이 들었다.
프론트 개발자가 이런것 까지 해야하나 하는 생각도 할 수 있겠지만 난 그렇게 생각하지 않는다 내 분야가 아니라도 전체적인 흐름들을 알고 있으면 나중에 회사에 들어가서도 다른 파트의 개발자와 소통하는데 훨씬 장점이 있을 것이고 내가 맡을 프론트 파트에서도 시너지가 있을 것이다 분명 뼈가 되고 살이 될것이라 확신한다.
여기서 끝이 아니라 CI/CD도 적용을 해보려구 한다 배포를 하면서 필요성을 정말 많이 느끼게 되었기 때문이다 CI/CD는 추후에 공부해서 적용해보고 다음 포스팅으로 기약해보도록 하겠다
긴 글 읽어주셔서 감사합니다.