TIL 51 | 첫 배포 AWS

dabin *.◟(ˊᗨˋ)◞.*·2021년 10월 23일
2

etc

목록 보기
8/14
post-thumbnail

코드 작성 후 서비스가 원활하게 돌아가게 하기 위해 인프라를 구축한다. 인프라에는 클라우드와 하드웨어 인프라가 있다. 이 중에서 AWS를 사용해 '배포'를 진행해보자.

먼저, AWS를 사용하기 전에 알고 있으면 좋을 개념들을 짚고 넘어가자.

네트워크

네트워크는 여러 디바이스들이 연결을 유지하는 공간이다. 라우터들이 모여서 거대한 인터넷 공간을 만들고, 라우터에는 컴퓨터들이 붙어 있다. 하나하나의 디바이스들은 Mac, IP, Port를 통해 구별된다. 전기적 신호를 사용해 빛의 속도로 통신하여 연결되지만, 대역폭이 정해져 있어 속도감이 다르게 느껴진다. 하나의 컴퓨터는 서버가 될 수도 있고 클라이언트가 될 수도 있다. 스마트폰도 하나의 라우터가 될 수 있다. 핫스팟이라는 기능으로 스마트폰 하나가 라우터가 되어 하위 디바이스에 대한 네트워크를 구성해주기 때문이다. 가까이에 있는 네트워크, 쉽게 생각하자..!

TCP / IP 4계층

LLayer
L4응용 계층(Application Layer)
L3전송 계층(Transport Layer)
L2인터넷 계층(Internet Layer)
L1네트워크 엑세스(Network Access Layer)
  • L4 : HTTP, SSH, FTP 등이 어떤 데이터를 전송할지 결정
  • L3 : TCP, UDP 등 어떻게 데이터를 전송할지 결정
  • L2 : IP 등 어디로 데이터를 움직일지 결정
  • L1 : 랜 케이블, 라우터, 패킷망 등의 하드웨어 장비를 의미

이렇게 레이어를 나누어 놓은면 유지 보수 측면에서 유리하다. 관심사의 분리를 통해 어떤 레이어에 문제가 있는지 살펴보고 문제를 보완하면 되기 때문이다.

공인 IP, 사설 IP 대역


[이미지 출처] https://www.avg.com/en/signal/public-vs-private-ip-address

  • 공인 IP : 전세계에서 유일하게 식별될 수 있는 IP
  • 사설 IP : 해당 대역에서만 식별될 수 있는 IP

IP를 도로명 주소라고 생각했을 때, -시 -구 -로 까지는 공인 IP, 1동 1호가 사설 IP라고 이해하자.

inbound & outbound

  • inbound : 요청을 받는 연결, <ip or dnsname>:port로 접속
  • outbound : 요청을 하는 연결, npm i/git clone/fetch/pull 등

인프라

인프라는 IT 서비스가 배포되어 유저가 서비스에 접속할 수 있게 만드는 공간이다. 인프라를 관리하는 영역을 DevOps라고 말하며, 물리적인 장비를 의미하는 온 프레미스(On-premise, On-site라고도 함) 인프라와 물리적 장비가 필요 없는 클라우드 인프라로 나뉜다.

AWS

Amazon Web Service의 약자로, 아마존에서 운영하는 클라우드 서비스다. 저렴한 비용, 민첩성, 즉각적 탄력성, 개방성, 유연성, 보안 등의 장점이 있다.

VPC

Virtual Private Cloud의 약자로 AWS의 인프라 중에 하나의 공간을 설정할 수 있다. 거대한 AWS 인프라에서 구역을 임대하는 개념이라고 생각하면 된다.

Subnet

VPC 내부에서 하나의 공간을 설정하는 부분이다. Inbound의 정책을 선택해 Public Subnet이나 Private Subnet을 결정할 수 있다.

EC2

Elastic Compute의 약자로 가상화된 컴퓨팅 자원을 할당 받을 수 있는 서비스다. scale이 조정 가능하기 때문에 CPU, RAM, OS 등 사양 및 환경에 맞춰 구성이 가능하다.

RDS

Relational Database Service의 약자로 관계형 데이터베이스를 제공해주는 서비스다. 백업, 복제, 보안 등 운영에 필요한 환경을 제공하기 때문에 인프라적인 관리가 불필요하다.

Security Group

보안그룹이라고 하며 서비스들의 방화벽이 되어주는 서비스다. 어떤 IP를 허용할 것인가 하는 문제를 다룬다. Inbound와 Outbound는 보안그룹에서 설정하며 이 보안그룹은 VPC에 종속된다.

S3

Simple Storage Service의 약자로 정적인 파일(바뀌지 않는 파일)을 관리하기 위한 서비스다. VPC에 속하지 않고 리전(국가?지역?)에 속해 VPC의 보안그룹이 적용되지 않는다. 파일 단위를 객체라고 부른다.

배포

VPC와 Subnet 생성


[이미지 출처] https://towardsdatascience.com/vpc-subnet-and-router-in-aws-cloud-17c8f421af21

Internet Gateway는 VPC 내부에서 외부로 통신가능하게 해주는 서비스다. Subnet이 Internet Gateway로 연결되어 있어 인터넷 연결이 들어올 수 있으므로 Public Subnet이 된다.

위의 개념이 이해되었다면, 인프라를 생성해보자.

  1. VPC를 검색해 VPC 대쉬보드로 들어가고, VPC 생성버튼을 눌러준다.

    • 이름: dasinco(service name 입력)-vpc
    • IPv4 CIDR 블록: 10.0.0.0/16
  2. VPC 생성을 누르고, 다음으로 Subnet 생성 버튼을 누른다.

    • vpc ID: dasinco-vpc(이전에 생성한 vpc)
    • 서브넷 이름: dasinco-subnet-public-1(서브넷은 VPC 하나에 여섯개 까지 만들 수 있으므로 몇 번째 서브넷인지 명시해준다)
    • 가용 영역: 아시아태평양(서울) 2a
    • IPv4 CIDR 블록: 10.0.0.0/24
  3. 서브넷을 생성하고, 인터넷 게이트웨이 생성 버튼을 누른다.

    • 이름: dasinco-igw
  4. 생성 버튼을 누르고 오른쪽 작업 토클 버튼을 클릭해 'VPC에 연결'을 누르고, 생성해둔 VPC로 설정하고 저장을 한다.

  5. 기존 설정은 VPC 내부에서만 통신할 수 있도록 설정이 되어 있기 때문에 외부와 통신할 수 있는 라우팅 테이블을 생성한다. 라우팅 테이블 생성 버튼을 누른다.

    • 이름: dasinco-routingtable-internet
    • vpc: 생성해둔 dasinco-vpc

    5-1. 라우팅 편집 버튼을 눌러 인터넷 게이트웨이를 설정해준다.

    • 대상: 0.0.0.0/0
    • 대상: 인터넷 게이트웨이

    5-2. 라우팅테이블에서 서브넷 연결을 해준다. 서브넷 연결 편집을 클릭해 서브넷을 선택하고 변경사항을 저장해준다.

  6. 서브넷을 하나 더 생성한다.

    • vpc ID: dasinco-vpc(이전에 생성한 vpc)
    • 서브넷 이름: dasinco-subnet-public-2
    • 가용 영역: 아시아태평양(서울) 2c
    • IPv4 CIDR 블록: 10.0.1.0/24
  7. 라우팅 테이블에 새로 생성한 서브넷을 연결한다.

  8. VPC로 이동해서 오른쪽 작업 버튼을 클릭하고 'DNS 호스트 이름 편짐'에 들어가 활성화에 체크하고 변경사항을 저장한다.

EC2 & RDS

subnet-public-1에 rds를, subnet-public-2에 ec2를 생성해보자. 서브넷 1과 2는 IP 대역만 다를 뿐이다.

  1. EC2를 검색하고 EC2 대쉬보드에 들어가 인스턴스를 클릭하고 인스턴스 시작을 누른다.
  2. RDS를 검색해서 들어가 보안그룹을 생성한다.
    • 이름: dasinco-sg-internet
    • 설명: sg for internet
    • 인바운드 : 모든 트래픽, Anywhere IPv4
  3. Amazon Linux를 선택한다. Free Tier로 설정한다.
    • 서브넷: subnet-public-2
    • 퍼블릭 IP 자동 할당: 활성화
  4. 단계 5에서 태그를 추가해준다.
    • 키: Name
    • 값: dasinco-ec2-front/back(서비스에 따라 많은 인스턴스가 생길 수 있기 때문에 이를 구분할 수 있도록 해준다)
  5. 단계 6 보안 그룹 생성
    • dasinco-sg-internet
  6. 단계 7 이후 새 키 페어 생성 후 다운로드
    • 키 페어 이름: Dasinco2

이제 RDS를 설정해보자.

  1. RDS를 검색해 들어가 DB 서브넷 그룹을 생성한다.
    • 이름: dasinco-subnetgroup-rds
    • 설명: subnetgroup for rds
    • VPC: dasinco-vpc
    • 가용 영역: 2a, 2c
    • 서브넷: public-1, public-2
  2. 엔진 옵션으로 mysql을 선택한다.
    • DB 인스턴스 식별자: dasinco-rds-test
    • 자격증명 설정 : 기억해두세요!!!!
    • 퍼블릭 엑세스 : '예'로 바꾼다
    • VPC 보안 그룹: default를 지우고 생성해둔 dasinco-sg-internet으로 설정한다.
    • 가용 영역: 2a에 위치시킨다

deploy

deploy전에 해주어야할 두 가지가 있다.

  1. chmod 400 <key파일이름>.pem 으로 권한 변경하고 진행해야 한다. 다운로드시 key가 너무 공개되어 있어 발생하는 문제 때문이라고 한다.
    [참고링크] https://github.com/rangyu/TIL/blob/master/ubuntu/SSH-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%A0%91%EC%86%8D-%EC%8B%9C-%ED%8D%BC%EB%AF%B8%EC%85%98-%EB%AC%B8%EC%A0%9C-UNPROTECTED-PRIVATE-KEY-FILE.md

  2. 프론트엔드 fetch 코드를 수정해 merge를 하여 최신상태로 clone 받을 수 있도록 한다. 프론트엔드 src 폴더 내에 api.js파일을 만들어준다. 배포했을 때, 배포를 하지 않았을 때 endpoint를 다르게 해야 한다. 따라서 작성해주어야 할 코드는 아래와 같다.

const host = process.env.REACT_APP_API_ENDPOINT || 'localhost';
const port = 8000; //백엔드에 설정해놓은 port

const API_ENDPOINT = `http://${host}:${port}`;

export { API_ENDPOINT };

fetch 요청하는 곳의 endpoint를 모두 수정해준다.

import { API_ENDPOINT } from '../../../api';

fetch(`${API_ENDPOINT}/product/${id}/info`)
  .then(res => res.json())

위의 두 가지 과정을 거쳤다면 다시 deploy를 해보자.

  1. ec2 대쉬보드에서 실행중인 인스턴스를 클릭해 퍼블릭IPv4를 복사한다.
  2. 터미널에서 키 파일이 있는 곳으로 이동하여 인스턴스에 접근한다.
cd Desktop //파일이 있는 위치로 이동

ssh -i Dasinco2.pem ec2-user@복사한퍼블릭IPv4주소

sudo yum update

sudo yum install git

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

. ~/.nvm/nvm.sh

nvm install 14.18.1 

//프론트 npm run build시 node-sass error
npm rebuild node-sass
  1. git clone
git clone 프론트 주소
git clone 백엔드 주소
  1. pm2 설치
npm i -g pm2
  1. 프론트엔드 설정
cd 프론트엔드 폴더
npm i 
//우리 팀의 경우 package-lock.json에 문제가 있어 삭제 후 npm i를 했다.
//rm package-lock.json => npm i

//프론트엔드 코드 수정이 된 경우
git pull merge main

vi .env
REACT_APP_API_ENDPOINT='ec2 endpoint 복붙!'
:wq

pm2 serve -h // serve option 확인
npm run build //프론트엔드 코드 빌드
pm2 serve --name 'dasinco-front' --spa ./build //배포
  1. 배포 화면을 확인하려면 aws에서 퍼블릭 IPv4 DNS를 복사해 주소창에 붙여넣기 한다. 포트번호를 따로 지정하지 않으면 8080이 되니 :8080을 붙여 확인한다.
  2. 백엔드 설정
cd ..
cd 백엔드 폴더
npm i

vi .env //기존 .env 파일을 배포 상황에 맞게 수정

DATABASE_URL="mysql://마스터id:비밀번호@rds엔드포인트:3306/dasinco"
PORT = 8000
secret="시크릿키입력"

:wq //저장하고 나가기

//새로운 터미널 창을 열어 rds에 dasinco 데이터베이스를 만들어준다. 
mysql.server start
mysql -h rds데이터베이스endpoint -u 마스터id -p
CREATE DATABASE dasinco;

//기존 터미널 창으로 돌아가서
npx prisma db push

pm2 start --name 'dasinco-back' -i max npm -- run start

//서버 정상 작동 확인하기
pm2 list
  1. 데이터베이스에 csv file Import
    https://aws.amazon.com/ko/premiumsupport/knowledge-center/connect-rds-mysql-workbench/
    위의 링크를 참고해 mysql workbench와 aws rds를 연결한다.

  2. 연결 => schema 우클릭 => table data import wizard 클릭 => 파일 경로 넣기(참조값이 없는 테이블 부터 넣기)

    [error]
    이 때 Unhandled exception: ‘ascii’ codec can’t decode byte 0xeb in position 15: ordinal not in range(128) 라는 에러가 났다. 파일 경로에 한글이 없었기 때문에 mysql workbench 버전 문제라고 판단해 삭제 후 8.0.22ver.으로 설치하니 정상적으로 csv 파일이 import 되었다.

  3. ec2 endpoint와 port를 주소창에 입력하면 누구나 접근할 수 있게 배포되어 있는 것을 확인할 수 있다.

Free-tier로 배포를 진행했고, 보안상의 이슈를 해결하기 위해서는 다른 옵션들을 적용해야 한다.

profile
모르는것투성이

6개의 댓글

comment-user-thumbnail
2021년 10월 23일

이걸 다 정리하시다니 대단하십니다~!

1개의 답글
comment-user-thumbnail
2021년 10월 24일

정리 맛집이라길래 왔습니다

1개의 답글
comment-user-thumbnail
2021년 11월 10일

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ3주뒤에 귀신같이 보러왔쬬

1개의 답글