Tooravel 프론트앤드를 배포 했으나 백엔드를 배포하지 않았기 때문에 프론트앤드 내부에서 배포버전과 개발버전을 나눈 부분들 때문에 연동이 되지 않았다.
makeUrl: (url) => {
let obj = {};
if (url[0] === '/') {
obj['external'] = false;
if (process.env.NODE_ENV === 'development') {
obj['fullUrl'] = 'http://localhost:4000' + url;
}
else if (process.env.NODE_ENV === 'production') {
obj['fullUrl'] = 'https://tooravel-front.vercel.app/' + url;
}
else {
new Error('process.env.NODE_ENV is not on development or production')
}
// TODO : add my ec2 path
} else if (url.startsWith('http')) {
obj['external'] = true;
obj['fullUrl'] = url;
}
return obj;
}
이러한 형태로 배포 버전과 개발 버전의 Url를 나눠 넣었기 때문에
yarn run dev
로 local 서버로 올린 프론트 앤드에서는 로컬 백엔드와 연동이 되지 않았다.
else if (process.env.NODE_ENV === 'production') { obj['fullUrl'] = 'https://tooravel-front.vercel.app/' + url; }
위 부분에서 배포된 백엔드 주소를 넣어야 한다.
AWS는 큰 트래픽을 발생하지 않는 선에서 12개월 무료 Tier를 제공해준다. 개이득! 👍
가입을 완료한다음 AWS EC2 콘솔로 들어가서 Free Tier 사용가능한 옵션을 선택해서 Ubuntu를 선택한다.
어차피 선택은 답정너이다. 검토및 시작을 눌러준다. 다음 !
현재 내가 선택한 인스턴스의 스펙이다. 위에보면 인스턴스 보안을 위해서 웹 서버용으로 포트 80으로 열라고 한다. 선택! ✔️
위 모습을 보듯이 새 보안그룹을 설정하면 기본으로 http, https 보안으로 연결될 수 있도록 연결 유형을 ssh로 설정된 모습을 볼수 있다. 그리고 IP주소를 사용자 지정으로 선택하면 해당 아이피만 접속 가능하므로 지금 배포하는 입장에 있는 나는 위치 무관으로 선택한다.
계속 검토 및 실행을 누르고 인스턴스를 마무리 하는 단계에서 키페어 생성 칸이 나온다. 여기서 생성하는 키는 mac이나 window에서 지금 생성하는 인스턴스 컴퓨터에 원격보안으로 연결하기 위한 키이다. 기존 키 말고 새키 페어 생성을 눌러 키페어를 다운로드 한다.
다운로드한 키는 잘 보관 하도록 하고 인스턴스 시작이 되었다. 인스턴스 보기를 누르자
인스턴스가 성공적으로 실행이 되었다. 🎉
터미널을 열어 아까 키페어를 생성해서 다운로드 받았던 폴더로 들어간다.
해당 위치에서 아래와 같은 코드를 입력한다.
chmod 400 <your pem key name>.pem
ssh -i "<your pem key name>.pem" ubuntu@<your IPv4 Public IP>
your pen key name
= 다운로드 받은 pem키 파일 이름 전체
your IPv4 Public IP
은 생성한 인스턴트 상태에 적혀있는 IPv4속성
macbook@homehub Downloads % chmod 400 aws-ec2-tooravel-backend-sever.pem
macbook@homehub Downloads % ssh -i "aws-ec2-tooravel-backend-sever.pem" ubuntu@3.36.54.219
접속 코드(예시)
ssh -i "tooravel_backend.pem" ubuntu@ec2-54-180-223-98.ap-northeast-2.compute.amazonaws.com
연결하겠냐는 내용이 뜨면 yes를 누르면 연결완료 !
위 모습은 ubuntu 인스턴스에 연결되어있는 모습입니다. 여기서 node js, npm 등을 설치해서 git clone 후 동작이 되게끔 베이스 프로그램들을 깔아줍니다.
sudo apt update
sudo apt install npm
sudo apt install nodejs
이미 git은 깔려있으므로 바로 원하는 서버를 다운로드 받으려 github에서 git clone을 해준다. 그리고 package.json 에 의존성을 보존시켜주기 위해서 아래 코드를 반복적으로 넣어 의존성을 보존했다.
sudo npm install <package name>
❗️ git clone 하기전 작업하던 로컬 git에서
.gitignore
파일을 잘 살피자
❗️
git reset --hard
와git push -f
명령어를 정말 웬만하면 사용하지말고branch
를 하나 파도록 하자
위 주의사항을 지키지 않다가 폴더하나를 통째로 영영 복구 할수 없는 경우가 발생해서 식은땀이 흘렀다. (별거아닌 코드가 담긴 폴더여서 30분 만에 복구했지만..)
npm start
성공적이다.
❗️ 현재 배포된 백엔드의 node_module은 mac 환경이랑 다르므로 git pull 이나 push로 github의 레포지토리에 혼선이 올수 있으므로 dev버전과 prod버전을
branch
로 나누어 관리하자
포트포워드의 역할은 http 요청으로 들어오는 포트는 80번 포트를 통해서 들어오게 되는데 우리의 서버는 8080 포트를 열어놓았기 때문에 8080포트로 해당 요청을 우회한다.
인스턴스 터미널에 다음 명령어를 넣는다.
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
물론 앞단에 nginx
, apache
등의 웹서버를 놓고 수정하면 되지만 프로젝트가 트래픽이 커질 위험이 없고 관리를 크게 하지 않아도 되기 때문에 위와 같은 명령어를 넣는다.
지금 인스턴스를 만들면 해당하는 IP는 scale out으로 다양한 트래픽 과부하가 이루어질 경우 서버 컴퓨팅을 나눠서 여러대의 인스턴스로 감당하게 할텐데 그때에는 여러 인스턴스의 IP가 생기므로 한대의 IP 인스턴스로는 이러한 과정을 극복할수가 없다.
따라서 고정 IP를 설정해서 이후 Load Balancer를 구성할 때 고정 Ip로 감당가능하도록 설정하자.
이렇게 탄력적 IP주소를 생성해서 인스턴스에 연결한다.
EC2 Instance 설정에서 백엔드에 express에서 받기로한 포트를 열어야한다.
const port = 8080;
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
위와 같이 현재 코드에서 port는 8080으로 설정되어 있으므로 8080포트를 개방한다.
❗️ 8080 포트를 개방한 이유는 보통 80번 포트는 로컬안에서 예약된 포트인 80 번포트 ( http를 위해 예약되어있는 ) 대신 8080포트를 개방해서 80번 포트로 이어지게 할 거라는 관습적인 포트번호이다.
보안 그룹명을 확인 후 왼쪽탭에서 보안그룹으로 들어가서 해당 그룹으로 들어간다.
인바운드 규칙변경을 클릭해서 원하는 포트를 등록한다.
성공!!! 만약 여기서 요청을 보내게 되면 https 사이트에서 http서버로 요청을 보내게 되므로 위험하다는 경고를 보게된다.
프론트는 https 보안설정이 되어있고 백엔드는 http 형태로 보안등급이 낮은 상태에서 통신할 수가 없다. 지금 ec2 인스턴스에 연결되어 있는 서버에 도메인이 없어 SSL 인증서가 없기때문에 https 프로토콜 사용이 불가하다. https는 http에 SSL보안기능 (보안소켓계층)
을 추가한 인터넷 통신 프로토콜로서 서버와 브라우저 사이의 안전한 무결성 데이터 통신을 가능하게 해준다. 따라서 현재 백엔드 서비스 배포에도 https 통신을 위해 SSL 인증서를 추가해줘야한다.
ACM에서 SSH인증서를 받으려면 도메인을 구매해야한다.
도메인은 무료로 구할 수있는 경우가 있고 유료가 있는데 AWS에서 도메인을 구매하면 자동으로 Route53
에 NS레코드
가 등록이된다.
굉장히 빠르게 도메인 등록이 진행되는데 외부회사에서 도메인을 등록하는 것보다 훨씬싸다. 다만 등록할 수 있는 도메인의 네이밍은 한국과는 다르다. .kr
과 같은 도메인등록은 안된다. 나는 tooravel.de
라는 도메인을 매년 9달러를 내는 것으로 등록을 했다.
등록을 마무리하면
아래 와 같이 해당 도메인이 등록 진행중이라는 문구가 뜨면서 최대 3일이 걸릴 수있다고 한다. 넘 느려 ...
약 1시간!! 1시간 지나고 도메인 등록이 완료되었다. 바로 안된다고 걱정하지마라 1시간 지나면 된다.
❗️❗️❗️ 굉장히 중요한 점이 있는데 여기서 도메인을 생성하면 자동으로 Route53에서 구입한 도메인에 대한 호스팅영역이 생성된다. 이생성된 호스팅영역을 삭제할시 다시 호스팅영역을 생성해야하지만 딱 알맞는 호스팅영역을 재생성하기가 매우 까다로워 진다. 필자는 삭제했다가 큰 곤욕을 치루었다. 절대 호스팅영역을 삭제하지 말도록하자
❗️참고
AWS에서 도메인 구매하기
❗️http와 https의 차이
https://url.kr/xjy2wb
aws ec2
에서 https 을 사용하려면 SSL인증서가 필요한데 이는 ACM(AWS Certification Manager)을 받으면 가능하다. 해당 페이지에 들어가서 먼저 도메인등록을 시작한다.
도메인을 등록 할때는 aws route53에서 산 도메인을 등록해야한다.
나는 tooravel.de
도메인을 구매했으므로 해당 도메인을 인증하고 하위 접근 도메인 인증으로는 *.tooravel.de
를 선택해서 접근을 용이하게 했다.
계속 넘어가다보면
여기에서 Route 53을 사용하는경우 (즉, Route 53에 먼저 도메인 등록이 되어있는 상태에서) Route 53에서 레코드 만들기
를 누르면 Route 53의 레코드에 CNAME 레코드가 자동으로 등록이되어 ACM인증이 자동으로 등록 된다.
Route 53에 들어가면 자동으로 aws에서 등록한 도메인에 호스트영역이 생성되어 있고 여기에 certication manager에서 등록한 CNAME레코드가 자동으로 등록되어있다.
이제 시간을 들여 기다리면 ssl 인증서가 발급될 것이다.
추가로 레코드이름을 추가해서 *.example.com
이렇게 설정한다면 www.example.com으로 접속하나 asd.example.com으로 접속하나 모두 인스턴스로 연결된다. A 타입 레코드로 로드밸런서에 등록된 라우팅대상으로 등록하면된다.
약 30분 정도 소요되었다. 언제되냐고 안절부절하지마라 30분이면 된다!
로드밸런서의 역할은 클라이언트에 대한 단일 접점 역할을 수행합니다.
로드 밸런서 AWS에서는 이것을 Elastic Load Balancer라고 합니다.
보통 클라이언트들이 보내는 요청이 많아지면 (트래픽이 증가하면) 이를 감당하기 위해서 보통 두가지의 방법이 있습니다.
scale up : 수직적 증가 : 서버 컴퓨터 자체의 컴퓨팅 기능을 증가한다.
scale out : 수평적 증가 : 여러대의 서버 컴퓨터를 두어 트래픽을 분산시킨다.
여기서 로드밸런서는 scale out을 담당합니다. 또한 클라이언트의 요청을 acm 인증을 이용해서 https 프로토콜 통신을 가능하게 합니다.
사용자의 https 프로토콜로 오는 요청을 로드밸런싱을 거치면서 acm인증서를 통해서 https 프로토콜 요청을 받고 인스턴스에는 http 통신으로 변환시켜 주게 합니다.
❗️ 물론 인스턴스 자체내의 코드 단계에서 https 통신을 받을 수 있지만 ssl인증을 acm으로 했기 때문에 그방법은 사용하지 않았다. 따라서 기존의 8080포트를 통해서 요청을 받으면 된다.
로드 밸런서로 들어가서 Load Balancer 생성 버튼을 누르자
위의 Application Load Balancer를 선택한다.
처음구성은 다음과 같다
AWS의 로드밸런서는 대부분의 영역에서 추후 수정이 가능하므로 설정하는데 있어 부담없이 해도되며 얼마든지 삭제와 재생성이 가능하므로 안되면 다양하게 시도해보자.
아래와 같은 구성으로 추가해준다.
리스너 : http, https
가용영역 : 서브넷을 추가해서 가용영역을 많이 설정해야 접근성이 높아진다. 최소 2개이상
보안설정으로 넘어간다.
이미 ACM에 인증서가 있으므로 자동으로 선택되었다 아래 보안 정책에 대해 있는데 따로 건들지 말자.
다음으로 보안 그룹 구성으로 넘어간다.
여기서 선택된 보안그룹은 위에서 ec2를 처음 등록할때 보안그룹을 지정해 놓은 그룹이다.
라우팅 구성은 ec2와 ACM인증서를 연결해주는 작업이다.
라우팅 구성의 이름을 지정해주고 프로토콜을 HTTP로 설정해준다.
❗️ 프로토콜은 HTTPS으로 지정한다면 라우터를 거쳐 인스턴스가 HTTPS 프로토콜 요청신호를 받게되는데 우리 인스턴스는 HTTP 포트로 신호를 받고 포트포워딩을 통해 8080포트로 신호를 넘겨받아 요청을 처리하므로 반드시 HTTP로 설정하자. HTTPS로 설정한다면
502 Bad Gateway
오류를 받게된다.
다음으로 넘어가면 인스턴스를 선택한다.
위에서 설정한 인스턴스를 선택한다.
이렇게 등록한다.
완성!
이제 route53의 호스팅 영역으로 들어가서 레코드 세트를 편집해주자.
대상 상태 평가를 아니오로 한다.
리다이렉션
리다이렉션의 경우 인스턴스안에서 해도되고 nginx에서 해도되고 로드밸런서에서 해도 되지만 aws에서 제공해주는 리다이렉션기능을 살펴보자
만들어 놓은 로드밸런서로 들어가서 리스너 탭을 클릭해보자
이중 HTTP : 80 리스너의 규칙 보기/ 편집 을 클릭하자
규칙을 클릭하고 위의 필기 탭을 클릭해서 기존의 THEN 탭의 규칙을 삭제하고 리다이렉션 대상을 HTTPS로 설정한다음 포트번호를 443 으로 설정후 체크 버튼을 누르고 위의 업데이트를 누른다.
이렇게하면 HTTP가 HTTPS로 리다이렉션된다.
ec2에 nginx를 설치해서 서버에서도 혹시 모를 다른 접근을 https 보안 접근으로 커버해보자
여기까지 했다면 이제 웹서버에 들어오는 트래픽을 ELB가 관리해준다.
부하 분산처리를 상황에 따라 관리할수 있게 되는 것이다.
http://tooravel.be
https://tooravel.be
https://www.tooravel.be
모두 접근 완료
개발환경에서 터미널을 종료하면 ec2 프로세스도 자동으로 종료된다.
이를 방지하기 위해서 forever
라는 패키지가 있다.
쉘 스크립트 언어로서 사용은 다음과 같다.
# forever 설치
$ npm install forever -g
# app.js 실행
$ forever start app.js
여기까지 성공했다면 프론트엔드에서 fetch 할때 요청하는 api 주소를 변경해야한다. 이과정은 다음 포스팅에서 마저 하겠다.