(최종 프로젝트 진행중)
오늘은 서버 배포를 진행하였다.
※ 이하는 스스로 공부하며 적어둔 노트이며 불확실한 내용이 있을 수 있습니다. 학습용으로 적합하지 않음을 유념해주세요. ※
Heroku로 배포를 결정하기까지 의사 결정 과정
Heroku로 배포를 결정하기까지 의사 결정 과정
로컬 컴퓨터에서 만든 웹 서비스를 빌드하여(정적 파일로 만든 다음에) S3에 배포할 수 있다고 한다.
빌드(Build)란?
소스 코드 파일을 컴퓨터에서 실행할 수 있는 독립적인 형태로 변환하는 과정과 그 결과를 말한다.
인간이 짠 코드를 한 번에 기계어로 변환해주는 작업을 컴파일이라고 하는데, 빌드는 이렇게 컴파일 된 코드를 실제 실행할 수 있는 상태로 만드는 일. (빌드 과정을 도와주는 도구를 Build Tool이라고 함)
정리:
Build = Complie + 그 외 작업 (테스팅(testing)과 배포(distribution) 등)
Run = Build + 실행
= (Complie + 그외작업) + 실행
현업에서는 두 가지 의미로 build라는 단어를 사용하는 듯 한데,
- Compile -> Deploy의 두 단계를 합친 것을 Build라고 하기도 하고
- Compile -> Build -> Deploy 중 가운데 단계를 Build라고 부르기도 한다.
- 빌드를 할 때
"build": "cross-env=production nest build"
아니면cross-env NODE_ENV=production
,?"heroku-postbuild": "ng build --prod"
여기다 cross-env=production 덧붙이기?procfile 도 설정해서 푸시해줘야 한다.,,, (여기 참조: Deploy NestJS with Docker, Heroku, and GitHub Actions)
- 빌드를 하면 정적 파일이 되는 것인가? 넵
- 그러면 정적 호스팅 클라우드 서비스(?)인 S3나 Heroku에 올려도 되는 것인가? 넵
⇒ 다만 Heroku나 S3에서 후처리를 해줘야 한다. (Heroku - RDS 연결하기: https://devcenter.heroku.com/articles/amazon-rds)
- 동적이라는 것은 백엔드단에서 다른 DB와 통신하거나 인증하는 등의 일을 말한다고 하는데, (그리고 라우팅?) 이게 들어가면 왜 S3에서는 동작하지 않게 되는 것인가?
⇒ S3 버켓과 DB 서버를 연동시켜주면 S3에 빌드 파일을 올려도 잘 동작하게 할 수 있다.,,, ⇒ EC2 하나를 일단 써야 S3로 디플로이할 수 있다고… RDS를 쓰기 위해서는! 백 용으로는. 프론트는 S3 버켓 하나로 배포가능한 것이 맞다.
- 그래서 Heroku로 혹시 배포해보셨나요..? PHP 어플리케이션으로 위장하여 배포한다는데 저희 Nest.js 프로젝트를 배포할 때 문제가 없을까요? 넵 Node.js로 선택해주면 된다고.
- 그래서 Heroku로 배포하면 기존의 RDS DB랑 연결이 가능할까요? 따로 연결하는 작업을 해줘야 하는 것 같던데… 넵
⇒ (Heroku - RDS 연결하기: https://devcenter.heroku.com/articles/amazon-rds)
- Heroku로 배포하면 기본이 HTTPS 도메인이다.
- Heroku로 배포하자..!
Heroku로 배포하기
Heroku로 배포하기
(대부분 이곳을 참고하여: https://doiler.tistory.com/13)
- “start”: “nest start” ⇒ “start”: “node dist/main.js”로 수정함
// package.json “start”: “node dist/main.js”
빌드가 완료가 되면 heroku 쪽에서 서버를 실행 시켜야 하기 때문에 서버 실행 명령어에 빌드된 파일의 실행파일 경로를 적어줘야 한다고 한다.
이제부터는 로컬 환경에서 실행할 때 npm run start을 실행하면 서버가 제대로 안 열리게 된다. 잊지 말고 npm run start:dev를 사용해줄 것.
- Heroku에 회원 가입 후 Heroku CLI 설치 완료함
설치 후 전역변수 설정을 제대로 해줬는데, 프로젝트의 루트 폴더로 들어가면 “heroku --version”같은 heroku 명령어가 인식되지 않는 문제가 있었다. 일단 완전 시스템 루트 폴더 (cmd 창 처음 켜면 지정되는 경로)에서 이후 단계를 진행하였다.
$ heroku login
을 명령하면 브라우저로 이동하게 되는데 여기서 로그인 진행 (이후로 Heroku 홈페이지에서 계속 진행함)⇒ 뭔가 QR 코드 주고 인증하라는데, AWS 로그인 할 때 사용하는 Google OTP 모바일 앱으로 등록해서 사용 가능했다!
$ heroku create
명령어로 생성하려니 카드 등록으로 본인인증을 해야 한다 그래서 등록함.https://mooin-cat.herokuapp.com/과 https://git.heroku.com/mooin-cat.git 주소를 얻음.
(2022년 11월 28일부터 free-dyno정책이 폐지되었다고 한다. 지금 basic-plan으로 돌리는 중)
- deploy 탭에서 깃허브와 연동해주고 (깃헙 레파지토리 소유자의 공유 허락이 필요하다)
- settings 탭에서 하라는 대로 빌드 팩 2개 차례로 등록해줌.
- settings 탭에서 add config vars에 “PROJECT_PATH: ‘/’” 키-밸류 쌍을 등록해준다. (중요)
- settings 탭에서 add config vars에 .env 파일에서 쓰던 환경 변수를 전부 등록해준다.
- deploy 탭에서 Deploy a GitHub branch “main”을 deploy 버튼을 눌러 배포해준다.
(자동 배포 체크도 가능하다: )
- 이렇게 deploy 버튼을 누르면 build 작업에 들어가게 되는데 여기서 계속 실패가 떠서 튜터님과 함께 트러블 슈팅을 진행하였다. (과정생략)
- 어쨌든 이후 AWS RDS 데이터베이스 서버까지 연결에 성공하여 잘 사용중.
연결 과정에서 참고하고 사용한 사이트들
- Heroku - RDS 연결하기 참고 문서 3대장 (이대로 다는 안 했다. 1~4번의 단계가 있으면 1,2만 했다.)
- Heroku 공식 문서 - https://devcenter.heroku.com/articles/amazon-rds
- 위 문서가 참고했다는 Stackoverflow - https://stackoverflow.com/questions/9741072/specify-ssl-for-heroku-external-mysql-database-connection/19831204#19831204
- 뭔가 4번까지 (AWS RDS측에서 할 일 2개 포함) 해야 하 ㄹ일을 안내하고 있지만 해결책은 되지 않은 - https://stackoverflow.com/questions/35247347/point-heroku-application-to-aws-rds-database
- 튜터님이 찾은 링크 - Heroku GitHub Actions YAML For CI/CD 외 Heroku - NestJs 배포 관련
- 하라는 대로 1번 단계를 위해 AWS Certificate?을 다운 받는데, (https://stackoverflow.com/questions/54938026/curl-unknown-error-0x80092012-the-revocation-function-was-unable-to-check-r) 이런 에러가 떠서 아래 방법을 썼었다.
- 튜터님 링크 - 현재 작동하는 AWS SSL Certificate (서울)을 다운 받은 곳 - 2019년 버전을 /src/config 파일에 넣어두고 앞에 슬래시(/)만 뺀 경로를 그대로 갖다 붙였었다.
- Heroku - RDS 연결하기 참고 문서 3대장 (이대로 다는 안 했다. 1~4번의 단계가 있으면 1,2만 했다.)
스크린샷(참고용)
어떻게 해결했나:
처음부터 계속 똑같이 이런 에러가 떠서 위의 여러가지 방법을 시도해 본 것이었다.
typeOrmConfig에서 host, port, username, password, dbname 이렇게 다 따로 떨어져 있던 것 대신, DATABASE_URL이라고 하나로 설정해서 넣어주니 되었다.
// src/config/typeorm.config.service.ts @Injectable() export class TypeOrmConfigService implements TypeOrmOptionsFactory { constructor(private readonly conigService: ConfigService) {} createTypeOrmOptions(): TypeOrmModuleOptions { return { type: 'mysql', // host: this.conigService.get<string>('DATABASE_HOST'), // port: this.conigService.get<number>('DATABASE_PORT'), // username: this.conigService.get<string>('DATABASE_USERNAME'), // password: this.conigService.get<string>('DATABASE_PASSWORD'), // database: this.conigService.get<string>('DATABASE_NAME'), url: this.conigService.get<string>('DATABASE_URL'), entities: [ User, Cat, ...
- 그렇담 Heroku에 따로 환경변수로 잡아준 건 없애도 작동하게 되는 건가?
- dev 버전이랑 production 버전이랑 어떻게 가르지?
Heroku는 무료인가?
카드 등록까지 마친 ‘personal’사용자는 한 달에 1000 free dyno hours를 쓸 수 있다고 한다. ‘web’ 앱 하나 하나가 dyno hours를 사용한다.
아닛, 2022년 11월 28일부터 더이상 아니라고 한다 (https://devcenter.heroku.com/articles/free-dyno-hours)
그래서 지금 $1.82 청구되고 있음. 1시간당 $0.01라고… 하면 지금 182시간 이상 사용 중이라는 것?
그 밖에 참고자료들
- Heroku로 Node.js 배포하기 공식 가이드
- 튜터님이 말씀해주신 것과 비슷한 코드가 있는…
let port=process.env.PORT||4000 app.listen(port, () => { console.log(`App running on port ${port} `); });
그리고 이렇게 if/else로 나눠서 deploy버전과 dev 버전 나누는 것 같다..!
// import the Sequelize constructor from the library const Sequelize = require('sequelize'); require('dotenv').config(); let sequelize; // when deployed on Heroku if (process.env.JAWSDB_URL) { sequelize = new Sequelize(process.env.JAWSDB_URL); } else { // localhost sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, { host: 'localhost', dialect: 'mysql', port: 3306 }); } module.exports = sequelize;
- Nest 빌드 커맨드를 이렇게 수정해봐야 하는 줄 알았지만 안 하고 잘 작동되었다 - 그래도
cross-env NODE_ENV=production
가 무슨 뜻인지는 알아봐야 할 듯. https://www.inflearn.com/questions/160663/nest-빌드-관련-질문입니다
- 진행중! new relic add-ons 추가를 위해 - 수면 모드 없는 지속 배포를 위해 - https://snakehips.tistory.com/entry/Heroku-배포-백엔드-배포-과정-중-나를-당혹스럽게-만들었던-상황-모음집
배포 (세미)완료
배포 도메인주소
https://mooin-cat.herokuapp.com
카카오 developers 내 애플리케이션에 이렇게 도메인 등록도 해줬다 (kakao map api 사용을 위함)(잘 됨 확인함)
Heroku 에러 로그 최신 것 하나 확인할 때 썼던 명령어: (프로젝트 디렉토리 말고 /USER>에서) heroku git:remote -a mooin-cat
Heroku 설정 파일 (어떤 환경 변수가 등록되어 있나) 확인하는 명령어: heroku config -a mooin-cat
Heroku는 Paas다
Heroku는 Paas다
PaaS
: Platform as a Service
: 클라우드에서 제공되는 완전한 개발 및 배포 환경.
: 개발적으로는 서버, 저장소, 네트워킹, 미들웨어, 개발도구, BI, 서비스, 데이터베이스 , 빌드, 테스트, 배포, 관리, 업데이트 등 모든 어플리케이션 수명 주기를 지원하는 서비스.
: 앱개발자는 소스 코드만 등록을 하고 클라우드에서 모든것을 알아서 처리해주는 서비스. 대표적으로 Heroku가 있다.
Iaas
: Intrstructure as a Service
아마존 AWS의 EC2 / S3 + CloudFront, 구글의 GCP
Faas
: Function as a Service
아마존 AWS 이용해 HTTPS로 배포하려면
아마존 AWS 이용해 HTTPS로 배포하려면
순서
- HTTPS를 적용할 도메인 구입하기. Route53에서 구매시 네임서버는 자동으로 등록됨.
- ACM으로 SSL인증서 등록하기
- 콘솔 → certificate manager
- CloudFront가 N.Virginia만 지원하니까 이걸 선택해줘야 한다고 한다. (왜 CloudFront를 사용하지? )
- Provision certificates 선택
- 공인인증서용 public certificate 선택, 도메인 입력해주기.
- select validation method에서 DNS 검증 선택
- 제공받은 값을 Route53에 등록한다.
- 인증서 발급 완료!
- CloudFront를 이용해 HTTPS를 적용하기.
- 콘솔 → CloudFront
- create distribution 클릭
- 버킷 endpoint 지정. …?
- 허용할 HTTP 메소드를 체크 및 rediract HTTP to HTTPS옵션도 체크.
- ACM에서 받은 SSL인증서를 등록.
- 정상 작동 확인하기. CloudFront에서 ‘Enabled’되었나.
- Route53에서 www.domain.com과 domain.com에 대한 DNS를 등록해주기. (www를 쓴 유저와 그렇지 않은 유저 모두 제대로 접근이 가능하도록)
AWS의 서비스 (EC2, S3, Cloud Front)명 정리
- S3: Simple Storage Service. 온라인 스토리지 웹 서비스. 파일 서버 역할.
객체 < 버킷
정적인 html이나 이미지 등을 제공하는데 용이해서 …
HTTP 프로토콜로 파일에 접근 가능. SSL 인증서 적용은 불가능(=HTTPS 프로토콜 사용이 불가능)
- EC2: Elastic Compute Cloud. 가상 컴퓨터 머신. 웹 서버 구축에 사용.
- Cloud Front: AWS에서 제공하는 CDN 서비스.
SSL 인증서를 이용한 HTTPS 호스팅을 지원함.
원본 데이터를 갖는 서버인 Origin(S3나 EC2 인스턴스)과, 캐시 기능을 제공하는 중계 서버인 Edge Location 서버들로 나뉨.
- S3: Simple Storage Service. 온라인 스토리지 웹 서비스. 파일 서버 역할.
Uploaded by N2T