졸업프로젝트로 웹 어플리케이션을 제작하고 Cloud Server에 배포를 진행하였다. 보통 가장 유명한 Cloud Service인 AWS를 사용해서 배포를 진행하는데, 학교에서 Tencent Cloud 가상머신을 사용할 수 있도록 지원해줘서 Tencent Cloud를 사용하였다. 많이 사용하지 않는 클라우드 서비스인만큼, 배포하는 과정에 어려움을 느꼈기에 글을 작성해서 남겨두려고 한다.
발급받은 가상머신 정보는 위와 같다. Tencent Cloud에서 CAM user login을 하고 Console
→ Cloud Virtual Machine
탭으로 이동을 하면 가상머신 인스턴스를 확인할 수 있다.
빨간색 박스 부분에는 인스턴스에 할당된 Public IP와 Private IP이 적혀져 있다. 다른 네트워크에 접속된 기기가 Public IP를 사용해서 접근할 수 있으므로 도메인을 할당할 때 Public IP가 필요하다. 인스턴스를 종료할 때 Public IP를 유지하거나 바꾸는 옵션 중 하나를 선택할 수 있으며 유지할 경우 요금이 조금 더 부과된다.
오른쪽에 있는 Log in 버튼을 클릭하여 우분투 계정으로 로그인을 진행한다.
Ubuntu 서버에 접속한 모습이다. 왼쪽 아래에는 이 서버의 Public IP가 있다.
클라우드 서버에 배포하기 위해 그동안 로컬에서 작업했던 프로젝트 폴더를 업로드해야 한다. 터미널의 파일 시스템을 사용해서 폴더 자체를 업로드할 수도 있지만 용량이 크기 때문에 GitHub에 업로드 후 레포지토리 자체를 복제해오기로 했다.
기존에는 MySQL 로컬 서버를 사용했기 때문에 SSH 등을 사용하여 터널링을 진행하였지만, 클라우드에 배포하면 서버 자체에서 프론트엔드, 백엔드, DB 작업을 다 할 수 있다. SSH 관련 코드가 불필요하기 때문에 코드를 cloud 버전으로 수정한 프로젝트 폴더를 GitHub에 업로드하였다.
git clone "Git 레포지토리 주소"
git add .
git commit -m "커밋 메시지"
git push origin main
git pull origin main
git clone
명령어를 사용하여 레포지토리를 클라우드 서버에 복제했다.
클라우드 서버의 터미널에서 git 명령어를 사용하려면 사용자 인증을 해야하는데 인증에 필요한 토큰은 GitHub 로그인 후 Settings
→ Developer Settings
→ Personal access tokens
탭에서 Tokens(classic)을 발급받으면 된다.
우리팀의 프로젝트에는 크게 4개의 서버를 운영하고 있기 때문에 4개의 Port를 열어줘야 했다.
- 프론트엔드 - React 서버 (3000번 포트)
- 백엔드 - Flask 서버 (5000번 포트)
- DB - redis 서버 (6379번 포트)
- DB - MySQL 서버 (3306번 포트)
1. 프론트엔드 - React 서버 (3000번 포트)
cd "React 작업 폴더" #작업 폴더로 이동
npm start
2. 백엔드 - Flask 서버 (5000번 포트)
python3 server.py #상대경로 작성
3. DB - redis 서버 (6379번 포트)
redis-server
4. DB - MySQL 서버 (3306번 포트)
MySQL은 ubuntu 서버에 MySQL 설치 후 계정을 만들고 권한을 주면 된다.
# root에 권한 주기
sudo mysql -u root -p
# MySQL 접속
GRANT ALL ON *.* TO 'root'@'%';
FLUSH PRIVILEGES;
# root 계정 비밀번호 설정
alter user 'root'@'localhost' identified with mysql_native_password by'설정할 비밀번호'
참고로, 프론트엔드 - 백엔드 서버 간 연결, 백엔드 - DB 서버 간 연결은 React 작업 폴더의 package.json
, Flask 작업 폴더의 config.py
에서 할 수 있다. 만약 개인 컴퓨터에서 서버를 구축한다면 Public IP와 User, Password가 들어가는 부분은 절대 공개적인 곳에 올리면 안된다. 아무 생각 없이 GitHub의 공개 레포지토리에 SSH 정보를 업로드했다가 컴퓨터 자체가 해킹되는 사건이 있었다. 검색해보니 GitHub에 업로드된 코드 때문에 털리는 일이 잦다고 하니 꼭 주의하도록 하자.
이제 외부 네트워크에서 각 포트에 접근할 수 있도록 클라우드 서버 인스턴스의 Inbound Rule을 설정해야 한다.
Cloud Virtual Machine 창에서 인스턴스 이름을 설정하고 Security groups 탭의 Edit Rule 버튼을 클릭해 수정하였다.
3306번, 3000번, 5000번 포트의 Source를 0.0.0.0/0
로 설정하여 이 포트로 들어오는 모든 트래픽을 허용하였다. 지금 다시 생각해보니, 사용자는 프론트엔드 서버인 3000번 포트에만 직접적으로 접속하므로 3000번 포트만 전체로 설정하고 나머지는 localhost에서만 접속할 수 있도록 해도 될 것 같다.
HTTP 서버 (80번 포트), HTTPS 서버 (443번 포트)는 따로 설정하지 않아도 기본으로 열린 포트로 도메인 배포 시에 필요하다.
도메인을 발급받기 전에 웹 서버가 정상적으로 작동되는지 확인해야 한다.
우리 프로젝트의 경우에 프론트엔드 서버가 3000번 포트이므로 http://{Public IP주소}:3000
로 접근이 가능하다. HTTPS 서버는 SSL 인증서를 발급받은 이후에만 사용이 가능하므로 HTTP 서버만 제대로 작동되는지 확인하면 된다.
이 과정에서 오류가 뜬다면 Inbound Rule 설정이 제대로 안된 것이거나, 프로젝트 폴더를 클라우드 서버에 업로드하는 과정에 문제가 생긴 것이므로 터미널에 뜨는 에러를 확인하며 수정하면 된다.
로그인을 하지 않은 상태에서는 /login
페이지로 이동되도록 만들어주었기 때문에 login 페이지가 뜨는 것이고 Public IP 뒤에 :3000
이 붙어있을 때 접속이 잘 되는지 확인하면 된다.
Public IP 뒤에 :3000
을 붙여야만 웹페이지가 정상적으로 작동되는 이유는 아무것도 붙이지 않았을 때 자동으로 HTTP 서버인 80번 포트로 로딩되기 때문이다. 즉, http://{Public IP 주소}
는 http://{Public IP 주소}:80
과 같은 상태이다.
3000번 포트로 접근하도록 유도해도 되지만, 포트 번호를 쓰지 않아도 바로 React 서버에 접근하도록 하고 싶었다. 그러면 80번 포트로 들어온 트래픽을 3000번 포트로 연결해주는 포트 포워딩이 필요하다.
먼저 Nginx를 설치하고 시작해야 한다.
#Nginx 설치
sudo apt install nginx
#Nginx 시작
sudo service nginx start
#Nginx가 제대로 동작하는지 확인
sudo service nginx status
설치가 완료되면 /etc/nginx
폴더가 생성되었을 것이다. 그 안에 있는 nginx.conf
파일을 수정해야 한다.
#nginx.conf 열기
vi /etc/nginx/nginx.conf
맨 아래에 http 블럭
에 아래 코드를 추가해주면 된다.
http {
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
다음으로 /etc/nginx/sites-available/default.conf
파일을 수정한다.
#nginx.conf 열기
vi /etc/nginx/sites-available/default.conf`
server 블럭
에 아래 코드를 추가한다.
server {
listen 80;
location / {
# 모든 요청을 3000번 포트로 리디렉션
proxy_pass http://localhost:3000;
# 기타 프록시 설정
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_ad_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
listen
, location
을 사용해서 80번 포트로 들어오는 요청을 3000번 포트로 리디렉션한다.
또한, sites-available/default.conf
에서 수정한 내용이 sites-enabled/default.conf
에도 반영되어 있어야 한다. 이를 심볼릭 링크라고 하며 nginx.conf
에 적어두었으므로 자동으로 반영된다. 아래 코드를 확인해서 제대로 반영되었는지 확인해볼 수 있다.
#nginx.conf 확인
cat /etc/nginx/sites-enabled/default.conf
마지막으로 Nginx를 재시작해준다.
#Nginx 재시작
sudo service nginx restart
아까와 달리 웹사이트 주소 마지막에 :3000
을 쓰지 않아도 3000번 포트로 바로 리디렉션되는 것을 볼 수 있다.
주소창에 Public IP 주소를 매번 입력해서 웹사이트에 접속할 수 없으니 비교적 기억하기 쉬운 Domain을 발급받아 연결해 줄 것이다.
도메인을 발급해주는 사이트는 많지만 배포를 Tencent Cloud에서 했기 때문에 도메인 발급도 Tencent Cloud 내의 도메인 발급 서비스를 사용해서 진행했다.
Register Domain 버튼을 눌러 원하는 주소의 도메인을 발급받으면 된다. Tencent Cloud에서는 DNSPod의 DNS 서비스를 제공하며, 오른쪽의 DNS 버튼을 클릭하면 DNS 설정 페이지로 이동된다.
여기서 도메인 이름을 클릭하여 발급받은 도메인과 Public IP 주소를 연결해주는 작업을 할 것이다.
빨간색 박스 부분에 Public IP 주소를 적으면 된다. 가상머신 인스턴스를 종료할 때 Public IP가 변경되는 옵션을 선택한 경우에는 이 부분을 매번 수정해 줘야 한다. 마지막에 CNAME 설정에 www
과 도메인 주소를 입력해서 'www'로도 접근 가능하도록 설정해줬다.
도메인 연결에는 시간이 조금 소요될 수 있으며 개인적으로 30분 이내에 연결이 완료되는 것 같았다.
도메인 연결이 완료되면 IP 주소가 아닌, 발급받은 도메인 주소로 웹사이트에 접근할 수 있다.
log 웹 어플리케이션은 영상 일기를 기록하기 위한 서비스이기 때문에, 영상을 녹화하는 과정에서 카메라와 마이크 권한을 허용해야 한다.
그런데 HTTP의 경우에는 보안 문제로 권한을 허용해줄 수 없었다. 그래서 SSL 인증서를 발급받아 HTTPS 주소로 접속할 수 있도록 해주었다.
먼저, 실행중인 Ngnix를 중지하고 SSL 인증서 발급을 위해 Cerbot
을 설치한다.
#Ngnix 중지
sudo systemctl stop nginx
#Cerbot 설치
apt-get update
sudo apt-get install certbot
apt-get install python3-certbot-nginx
#인증서 생성 및 발급
sudo certbot --nginx -d logyourmemory.xyz -d www.logyourmemory.xyz
SSL 인증서 발급 및 갱신 등 관리자가 필요하기 때문에 관리자의 이메일을 입력해야 한다. 이메일을 입력하고 발급이 완료되면, /etc/letsencrypt/live/{도메인 이름}/
폴더에 2개의 pem
키 파일이 생성된다.
이번에는 HTTPS 서버인 443 포트로 들어오는 요청을 3000번 포트로 리디렉션해주는 포트 포워딩이 필요하다. 방법은 80번 포트를 3000번 포트로 연결해주는 것과 같다.
먼저, /etc/nginx/sites-available/default.conf
파일을 수정한다.
#nginx.conf 열기
vi /etc/nginx/sites-available/default.conf
server 블럭
에 아래 코드를 추가한다.
server {
# SSL configuration
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate "{fullchain.pem 경로}" #/etc/letsencrypt/live/logyourmemory.xyz/fullchain.pem;
ssl_certificate_key "{privkey.pem 경로}" #/etc/letsencrypt/live/logyourmemory.xyz/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
# 모든 요청을 3000번 포트로 리디렉션
proxy_pass http://localhost:3000;
# 기타 프록시 설정
proxy_set_header Host $http_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;
}
}
2개의 pem은 SSL 인증서를 발급받은 도메인 폴더 아래에 있으니 경로를 수정해서 입력하면 된다.
이번에도 마찬가지로 심볼릭 링크가 잘 연결되어 있는지 확인해본다.
#nginx.conf 확인
cat /etc/nginx/sites-enabled/default.conf
마지막으로 Nginx를 재시작해준다.
#Nginx 재시작
sudo service nginx restart
이 과정이 완료되면 https://{도메인 주소}
로 프론트엔드 프로젝트에 접근할 수 있으며 아까와 달리 주의 요함 문구가 뜨지 않는 것을 확인할 수 있다.