37일차 배포 분기

osdsoonhyun·2023년 4월 6일
0

코드캠프

목록 보기
22/22
  1. 두 가지 정적, 동적 배포를 분기시켜보자! -> CDN - LB
  2. AWS 안에서 동적페이지를 배포하기 위해서 yarn start 켜놨는데 안전하게 하기 -> Doker 사용

CloudFront 라우팅 연결

  • 지금까지는 브라우저에서 출발하여 주소를 IP로 바꿔주는 DNS(Route 53)에서 CDN을 거쳐 CDN에는 ACM 이용해서 SSL 인증서 설치해서 https 형태로 되어 있고 이것은 storage로 연결되어 있다.
  • 정적페이지는 storage에 있고 여기서는 동적페이지에 접속이 되지 않았다. EC2에서 동적페이지는 LB로 접속했기 때문에 LB의 IP주소로 접속을 해줘야 한다. 원래는 LB가 아닌 EC2로 다이렉트로 접속이 가능하지만 LB는 한 개의 컴퓨터에 사용자가 많아져서 컴퓨터가 많이 필요하므로 그 때 부하를 분산시키기 위해 LB가 필요한 것이다.
  • 지금은 LB를 타고 접속하기 위해 인스턴스 EC2 연결시키고 컴퓨터 쉘(SSH)에 접속을 하여 연결하고 yarn start 한다.

ps -ef

  • 기존의 실행시켜 놓은 프로그램 확인(yarn start 실행되고 있는지 확인)
  • ps는 process의 약자 , e는 environmnet의 약자로 환경을 보고 싶을 때 사용
  • 프로세스와 쓰레드, 프로세스가 하나의 컴퓨터 프로그램이라 하면 프로그램 안에서 실행되고 있는 것이 쓰레드이다.

너무 많은 프로그램들이 실행 중이라 찾기 힘들다
-> node로 실행되고 있는게 있는지 확인

  • ps -ef | grep node
  • |는 파이프라 부르고 앞에 있는 명령의 결과에서 다른 명령을 조립하고 싶을 때 사용
  • grep는 잡으라는 명령어 node로 실행하고 있는 것을 잡아라
  • 두 번째 줄은 내가 grep node를 실행했기에 나오는 명령어이다.
  • 첫 번째 줄에 node로 실행되는 명령어가 있기 때문에
  • kill -9 + 프로세스 ID를 통해 프로그램을 종료시킬 수 있다.
    -> kill -9 938

CDN과 LB연결하기

  • 주소창에서 브라우저를 입력하게 되면 DNS(AWS-Route 53)를 거쳐 CDN(AWS-CloudFront)으로 오고 입력한 주소에 따라 정적페이지이면 스토리지로, 동적페이지이면 LB로 이동하도록 분기처리를 해주어야 한다.
  • CloudFront로 들어가면 이미 DNS A레코드와 연결되어 있어 주소쳐서 들어가면 Domain Name의 값이 나오는 것이었다.
  • ID로 들어가서 동작으로 들어가면 경로에 따라 이동할 곳을 저장되어 있다.
  • 현재는 경로패턴을 보면 Default 기본값으로 s3로 가라고 지정해주었다. 여기에 추가로 boards로 시작하는 페이지들(/boars/*)은 LB로 이동하라고 추가해준다.
  • 원본 또는 원본 그룹에 s3는 자동으로 만들어지는데 여기에 LB를 만들어줘야 한다.

배포 원본(origin) 생성하기

  1. 원본 도메인에 LB를 선택하여 지정한다.

  2. 프로토콜은 HTTP만 해당하도록 선택한다.

    • SSL을 CDN에 적용하기 때문에 https로 이후 스토리지나 LB로 이동시 http로만 설정하는 것이 일반적이면 다른 곳에서도 https로 설정하기 위해서는 SSL을 각각 설치해주어야 한다.
    • SSL을 설치하게 되면 secure를 푸는데 시간이 걸리므로 서비스의 보안이 중요한 곳에서만 추가로 https를 설치해야 한다.
    • 여기서 프로토콜은 CDN에서 LB, storage로 보내주는데 HTTP로 갈지 HTTPS로 갈지 선택하는 것이다. 만약 LB로 갈때 HTTPS를 선택한다면 LB에도 SSL 인증서를 설치해주어야 한다.
    • HTTP는 80번 포트이다.(HTTP에서는 80이 Default port라 생략된다)
  3. 원본 생성

  • 원본이 2개가 된 것을 확인할 수 있다.
  • 이것을 이제 정적페이지는 s3로 동적페이지는 lb로 분기시켜주면 된다.

배포 동작 생성하기

  • 경로 패턴에 boards/*를 입력하여 동적페이지들의 경로를 설정해준다.
  • 동작 목록에서 위와 같이 동적페이지들은 LB로 정적페이지들은 s3로 동작이 연결된 것을 확인할 수 있다.
  • 그럼 브라우저에서 도메인 주소를 입력해서 접속하면 DNS로 가고 DNS A레코드는 아직 변경하지 않았기에 CDN으로 이동한다. 지금 CDN에서 동작을 생성해놨기 때문에 뒤쪽의 주소에 따라 분기처리가 된다.

분기처리 확인하기

  • CDN에 캐시가 있을 수 있기 때문에 invalidation 무효화에서 /*를 추가하여 모든 페이지에 대해서 무효화한다.
  • 크롬 브라우저 설정에서 개인정보 및 보안에서 캐시를 삭제한다.
  • yarn start를 끄고 동적페이지에 들어가면 화면이 보이지 않는 것을 확인할 수 있다.
  • 지금 동적 페이지에 id 값이 안나오고 있는 것이 확인된다. 이것은 다운로드를 받아오지 못하는 파일들이 있어서 정상적으로 작동되지 못하고 있다.

buildId 폴더 통일시키기

  • 파일들의 다운로드 위치를 보니 /boards/*로 되어야 LB로 가는데 _next/에서 다운 받는 것을 보니 storage 안에서 next 폴더 안에서 다운받고 있다는 것을 알 수 있다. storage에 next에는 css, js파일들이 들어있다.
  • next 폴더 안의 buildId가 랜덤하게 만들어져 있기 때문에 ec2안의 next 폴더 안의 buildId랑 다르기 때문에 Html을 ec2에서 다운 받아오고 storage에서 정적파일 받아와야 하는데 ec2안의 buildId랑 다르기 때문에 다운받을 수 없는 문제가 생긴다.
  • yarn build 할때마다 빌드 아이디가 바뀐다 빌드 아이디는 폴더명이다. 그러니 다운로드 위치가 바뀐다는 의미이다. 이것을 위해 해결할 수 있는 두 가지 방법이 있다.
    1. LB에 정적 파일들을 위한 폴더를 따로 만들어서 그쪽으로 우회시키는 방법(복잡하고 어려움)
    1. storage에 있는 buildId랑 ec2 vm에 있는 _next 안의 boardId가 달라서 생기는 문제인데 둘의 buildId를 합친다. (buildId는 랜덤값)
  • 따라서 간편한 buildId를 일치시켜보자 어디서 build하든 똑같은 _next 폴더가 나오도록 한다.
  • next.config.js에서 generateBuildId: () => "deploy"로 해줌으로써 storage와 ec2 안의 next/deploy로 통일시킨다.

업데이트 하기

  1. 이제는 yarn build:ssg 하면 out/next/deploy 가 생성되었는데 이것을 다시 storage로 올려두어야 한다.
  2. git push 한 후 EC2 안에 들어가서 yarn build하고 yarn start를 해줘야 업데이트 된다.
  • 동적 페이지에서도 css, js파일이 제대로 들어오는 것을 확인할 수 있다.

서버사이드렌더링

export const getServerSideProps = () => {
  // 만약 서버사이드 렌더링을 한다면?
  // => out 폴더로 생성 불가
};
  • 서버사이드렌더링이 있다면 아예 out 폴더 생성이 불가능해진다.
  • next.config.js 파일에 getServerSideProps가 들어있는 페이지는 제외하고 빌드시키도록 한다.
exportPathMap: () => ({
    "/": {page: "/"},
    "/boards": {page: "boards"},
    "/404": {page: "/404"}, 
  })

정리
S3에 업로드된 빌드 파일을 CloudFront를 이용하여 캐싱하여 빠른 속도로 최초 화면을 표시한 다음, 나머지 페이지와 데이터들은 SSR 방식으로 전달한다. 그렇기 때문에 사용자는 빠르고 역동적인 경험이 가능하다.
또한, 잦은 변경이 필요하지 않은 파일(기본 레이아웃 및 디자인 등)들을 S3로 분리하여 EC2 인스턴스에 대한 부하를 줄일 수 있고, 이를 통해 안정적인 서비스 제공 및 비용 절감 효과를 도모할 수 있다.


Docker

Docker 사용 이유

  • 회사에서 신입사원이 들어와서 세팅을 해야 한다. 이때 Git을 통해 코드를 내려 받는다면 yarn install은 node로 설치할 수 있는 것만 세팅이 되어있는 것이고 회사에서는 node 뿐만 아니라 node 버전도 맞춰야 하고(node16 설치) 백엔드 소스 코드도 설치해야 할 수 있다(Mysql8 설치). 이렇게 버전까지 맞추어 설치를 해도 문제가 발생할 수 있다. 이때는 운영체제의 문제가 발생한 것이다. 운영체제에 따라 달라지는 환경이 큰 이슈가 되었다.
  • 이것을 해결하고자 가상머신을 만들어 컴퓨터 안에서 새로운 컴퓨터를 실행시켰다. 가상머신은 가볍고 용량도 적고 성능도 빠른 Linux를 사용하였다. 이 안에서 Node, Mysql을 설치하였다. 그런데 컴퓨터 안에 컴퓨터가 있으니 느린 이슈가 발생하였다.
  • 이것을 해결하고자 부팅 등 운영체제의 핵심 기능(커널) 공유하는 가상머신인 Doker를 사용하게 되었다.
  • 도커는 운영체제가 밖에 있는데 가상머신 안에 운영체제를 또 설치할 필요가 없다. 즉 운영체제 중에서 공유할 수 있는 부분을 공유하는 것이다. 그래서 OS전체를 새로 설치하지 않아도 되는 빠르고 가벼운 가상머신이 되었다.
  • Docker는 Linux 기반이므로 Linux와 Mac-OS는 상관없지만 Windows는 WSL2(Window Subsystem for Linux)를 설치해야 한다.
  • 이렇게 하면 회사에 새로운 사람이 들어오더라도 Docker 파일만 주고 실행시키면 Window를 사용하든 Mac을 사용하든 Linux로 통일되고 이미 설치할 목록이 셋팅되어 있으니 설치하지 않아도 되어 매우 편하고 효율적이다. 뿐만 아니라 이 모든 것은 VMware에서도 가능하지만 매우 가벼운 가상컴퓨터에서 할 수 있다.

정리 : Docker의 장점
1. 개발 / 배포환경 통일(개발자들 간의 개발환경, EC2-Local)
2. 프로그램 미리 설치
3. 가벼운 가상컴퓨터

# FROM ubuntu:22.04

# RUN curl -sL https:rpm.nodesource.com/setup_14.x | sudo bash
# RUN sudo apt install -y nodejs
# RUN sudo npm install -g yarn

FROM node:16

WORKDIR /class_build/     // 폴더 안에서 커서 깜박이게 하는 것
# RUN mkdir class_build   // 아래에서 COPY 할 때, 자동으로 만들어 주므로 굳이 안써도 됨
COPY . /class_build/     // (. -> 모든 파일)을 복사해서 Docker에 class_build에 넣어줘

RUN yarn install
RUN yarn build
CMD yarn start

CMD vs RUN

  • CMD는 한 번 밖에 사용하지 못한다.
  1. 도커 허브에서 node 설치된 우분투 운영체제가 설치되고
  2. 내 컴퓨터 파일들을 도커 컴퓨터에 복사
  3. yarn install, yarn build 실행
  4. 최종 프로그램 실행(yarn start)
  • 이것을 매번하면 너무 느리기 때문에 1~3번까지 1번만 실행하고 이미지(사진x, 최적화된 압축 파일)로 저장해놓는다.
  • 그 다음에는 이미지 파일 불러와서 프로그램을 실행만 시킨다. 그래서 RUN은 저장대상이고 CMD는 저장에서 제외되고 실행한다.
  • 도커 파일은 한 개가 아니고 컴퓨터 한개만 실행시키는 것이 아니라 예를 들어 프론트 한대, 백엔드 한대, DB 한대 컴퓨터 3대, 도커파일 3개가 있고 이것을 하나로 묶어서 on/off 할 수 있다.
  • 이렇게 그룹핑하는 것을 Docker-compose라고 한다.

Docker-compose의 이해

  • 여러가지 컨테이너를 다룰 때 좀더 복잡한 설정이 필요하다. 이럴 때 Docker-compose를 사용한다.
  • docker-compose.yml 파일을 미리 만들어서 설정을 어떻게 할지 적어둡니다. 그리고 docker-compose up 명령어를 입력해서 컨테이너를 실행한다.
  • 컴퓨터 한대 한대를 service라고 한다.

docker-compose.yml 파일 예시 ( yml 파일은 들여쓰기를 꼭 지켜주셔야한다! )

version: "3.3"

services:
  class_build:
    build:                 // 어떤 도커 파일을 가지고 실행할지 Docker 파일을 가리켜야함
      context: .            // 파일의 위치: 현 위치(.)
      dockerfile: Dockerfile       // 도커 파일명
    ports:
      - 3000:3000
  • $ docker-compose up 하면 저장되어 있는 이미지(최적화된 압축파일)을 꺼내서 오고 거기서 CMD 실행시킨다.

  • $ docker ps 하면 현재 실행중인 도커 프로세스가 나온다.
  • 실행중인 컴퓨터를 CONTAINER라 부르고 실행중인 컨테이너로 들어가서(exec) 수정하고 볼 수 있게하고(-it) 어디에 접속하는지(4c6b8131b4fb) 무엇을 하고싶은지: 빈 쉘에서 커서 깜박이게(/bin/bash) $ docker exec -it 4c6b8131b4fb /bin/bash 한다.
  • Docker 컴퓨터 안에 있는 것을 확인할 수 있다.
  • $ exit로 빠져 나올 수 있다.

포트포워딩

  • 여기서 문제는 localhost: 3000 했을때 접속이 되지 않는 문제가 있다. 내 컴퓨터 안에서 localhost:3000을 찾아야 하는데, 도커에서 yarn start 되어 찾지 못한다.
  • 이것을 해결하기 위해 도커 컴퓨터 안에서 입구를 만들어 3000번 포트로 실행을 시켜준다. 그리고 바깥에서 3000번으로 들어온 것을 도커 컴퓨터 안으로 들여보내고 3000번 포트를 찾아 연결시키고 html를 받아온다.
  • 이 도커 입구에서 3000번 포트 받은 것을 3000번으로 넘겨주는 과정을 포트전송 포트포워딩이라고 한다.
  • 이것을 응용하여 ports: - 2000:3000 2000번으로 열려있어서 2000번으로 접속을 하면 3000번으로 내보내준다. (내컴퓨터: localhost:2000, 도커: localhost:3000)
  • 이렇게 눈 앞에서 실행하는 foreground 실행은 실제 서비스에서 ctrl + c하면 꺼지기 때문에 좋은 방법이 아니고 뒤에서 실행시키는 도커를 활용하여 실행해야 한다.
  • docker-compose up -d : 백그라운드에서 실행 (ctrl + c해도 종료x)
  • docker ps : 현재 실행중인 프로세스 확인 (실행, 종료 됨을 확인)
  • docker-compose stop : 백그라운드에서 실행하는 것을 종료

도커 주의 사항(.dockerignore)

  1. 로컬와 도커 node 버전 다를 경우 방지
  • 지금 COPY 를 한 다음에 yarn install을 하고 있다. 만약 내컴퓨터에서 yarn install을 해놨다면 밖에서도 yarn install 해놓고 다시 yarn install을 두 번하게 되는데 매우 이상하다. 이 경우는 내컴퓨터의 node 버전과 Docker의 node 버전이 다를 수 있다. 이럴 때는 Docker node 버전을 기준으로 해야한다. 이렇게 하면 각자 node 버전이 다를지라도 도커 안에서는 같은 node 버전을 세팅할 수 있다. 그러고 밖에서의 다른 버전의 node_modules 가 들어오는 것을 막기 위해 .dockerignore파일을 통해 막을 수 있다.
// .dockerignore 파일
node_modules
.next
  1. 소스코드를 바꿀 경우
  • 소스코드가 바뀌면 docker-compsoe build를 다시해야 한다.
  • 도커는 한 줄 실행할 때마다 다음 실행을 위해 cache에 저장을 해둔다.
  • 도커는 캐시에서 가져와서 사용하다가 캐시에 없거나 다른 것을 발견한 순간 그 밑으로는 캐시에 있어도 다시 재시작한다. 문제는 소스코드는 수정했는데 build가 새로되는 것이 맞으나 yarn install은 굳이 다시할 필요 없기 때문에 개선해주어야 한다.
  • 그래서 yarn install을 상단으로 두어 소스코드가 바뀌었을때만 재시작하도록 한다. package.json, yarn.lock 을 복사해 놓는다.
  • 이렇게 하면 소스코드 한 줄 바뀔 때마다 yarn install 되는 것을 방지하고 바뀐 것이 없기 때문에 캐시에서 package.json, yarn.lock, 커서 깜박이게 하여 yarn install까지 가지고 와서 캐시에 저장된다.
  • 이후에 up해서 진행하면 된다. 그리고 소스코드가 바뀌면 로컬은 바뀐 것이 저장되었지만 도커는 업데이트가 되지 않았기 때문에 재빌드(docker-compose build) 해주어야 한다. yarn install은 이미 설치가 되어있기 때문에 캐시에서 가지고 온다.
  • yarn install을 새로 해야 할 때는 package.json이 바뀌었을 때 새로해야 한다.

소소한 꿀팁

  • LB가 왜 필요할까?
    EC2에 IP가 있기 때문에 방화벽 풀고 접속하면 되지만 LB는 사용자가 너무 많아서 한 개의 컴퓨터가 아닌 여러 대의 컴퓨터가 필요할 때 여러 컴퓨터에 트래픽을 분산처리 하기 위함이다. 그렇기에 사용자가 많지 않다면 LB는 필요없다.

0개의 댓글