[SEB_FE_45] 2023.08.01 / CI/CD

Kay·2023년 8월 2일
0

개발 프로세스

전통적인 개발 프로세스

폭포와 같이 한 방향으로만 프로세스가 진행되는 개발 과정을 뜻하며 워터폴(Waterfall) 즉, 폭포수 개발 방식이라고 함

애자일 개발 프로세스

계획에 의존하여 형식적인 절차를 끝까지 따라야 하고 중간에 뒤로 회귀할 수 없는 전통적인 개발 프로세스보다는 훨씬 효율적으로 개발에 착수 가능
이러한 방식은 SaaS(Software as a Service, 서비스형 소프트웨어)를 개발하는 데에 적합

DevOps

DevOps는 특정한 업무라던지 부서가 아닌 일종의 개발 문화
만약 서비스가 중단된다면, 누구든지 문제점을 진단하고 시스템을 복구하여 운영할 수 있는 절차를 알고 있어야 함
개발에서 운영까지 하나의 통합된 프로세스로 묶어내고 사용하는 툴과 시스템을 표준화하여 의사소통의 효율성을 확보하고 일련의 작업들을 자동화

CI/CD

지속적 통합(Continuous Integration, CI)

개발자를 위한 자동화 프로세스

  • Code : 개발자가 코드를 원격 코드 저장소 (Ex. github repository)에 push하는 단계
  • Build : 원격 코드 저장소로부터 코드를 가져와 유닛 테스트 후 빌드하는 단계
  • Test : 코드 빌드의 결과물이 다른 컴포넌트와 잘 통합되는지 확인하는 과정

지속적 배포(Continuous Delivery/Deployment, CD)

지속적인 서비스 제공(Continuous Delivery) 및 지속적인 배포(Continuous Deployment)를 의미

  • Release : 배포 가능한 소프트웨어 패키지를 작성
  • Deploy : 프로비저닝을 실행하고 서비스를 사용자에게 노출. 실질적인 배포 부분
  • Operate : 서비스 현황을 파악하고 생길 수 있는 문제를 감지

배포 자동화

  • 수동적이고 반복적인 배포 과정을 자동화함으로써 시간이 절약
  • 휴먼 에러(Human Error)를 방지

CI/CD 파이프라인 기본 단계

  • Source 단계: Source 단계에서는 원격 저장소에 관리되고 있는 소스 코드에 변경 사항이 일어날 경우, 이를 감지하고 다음 단계로 전달하는 작업을 수행
  • Build 단계: Build 단계에서는 Source 단계에서 전달받은 코드를 컴파일, 빌드, 테스트하여 가공합니다. 또한 Build 단계를 거쳐 생성된 결과물을 다음 단계로 전달하는 작업을 수행
  • Deploy 단계: Deploy 단계에서는 Build 단계로부터 전달받은 결과물을 실제 서비스에 반영하는 작업을 수행

Github Action

GitHub Actions는 Github가 공식적으로 제공하는 빌드, 테스트 및 배포 파이프라인을 자동화할 수 있는 CI/CD 플랫폼
비공개 레포지토리의 경우 Github Actions가 작동할 때의 용량과 시간이 제한되어 있으며 공개 레포지토리는 무료로 사용 가능

참고 링크: GitHub Actions: CRA(Create React App) 빌드 + GitHub Pages 배포 자동화하기

1. 디렉토리 및 파일 만들기

  • .github/workflows 디렉토리 생성
  • .github/workflows 디렉토리 안에 MyWorkflow.yml 파일 생성 => 파일명 자유

2. 스크립트 작성

예시

# .github/workflows/client.yml

# name: workflow 이름
name: client
# on: workflow가 실행될 조건
on:
  # 즉, reference 브랜치에 푸시가 될 때마다 실행
  push:
    branches:
      - reference

  # workflow를 수동으로 실행할 수 있도록 하는 옵션
  workflow_dispatch:

# 하나의 workflow는 여러 개의 job으로 구성되어 있으며,
# 기본적으로 병렬로 수행되지만 needs를 추가하면 특정 job이 끝난 후에 수행 가능
jobs:
  # job 이름
  build:
    # runs-on: 실행할 환경
    runs-on: ubuntu-latest
    
    # 하나의 job은 여러 개의 step으로 구성되며, 순차적으로 실행
    steps:
      # actions/checkout@v3: 체크아웃 액션: 저장소로부터 코드를 받아와 주 브랜치로 전환
      - name: Checkout source code.
        uses: actions/checkout@v3
      # node.js 런타임 사용
      - name: Node setting
        uses: actions/setup-node@v1
        with:
          node-version: '16'
      # 의존 라이브러리 설치
      - name: Install dependencies
        run: npm install
        working-directory: my-agora-states-client-react
      # react app 빌드
      - name: Build
        run: npm run build && pwd && ls -al
        working-directory: my-agora-states-client-react
      # aws 버전 체크
      - name: SHOW AWS CLI VERSION
        run: |
          aws --version
      # github에 등록한 secrets로 부터 env를 읽어와 사용하도록 설정
      # sync: 우리가 올리고자하는 파일과 버킷 내 파일을 비교하여 동기화
      # 버킷의 폴더/파일을 지우고 build 폴더를 올리도록 함
      - name: Sync Bucket
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_EC2_METADATA_DISABLED: true
        run: |
          aws s3 sync \
            --region ap-northeast-2 \
            build s3://fe-98-kay0829-s3 \
            --delete
        working-directory: my-agora-states-client-react

과제1 결과

Proxy

CORS(교차 출처 리소스 공유(Cross-Origin Resource Sharing))

추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제

CORS 에러를 해결하는 정석적인 방법은 프론트엔드 개발자가 백엔드 개발자에게 프론트엔드 개발 서버 도메인을 허용해달라고 요청을 해야하고, 백엔드 개발자는 응답 헤더에 필요한 값들을 담아서 전달 해야 함

Proxy

React 라이브러리, 혹은 Webpack Dev Server에서 제공하는 proxy 기능을 사용하면 CORS 정책을 우회 가능

webpack dev server proxy

  1. 클라이언트 프로젝트의 package.json 가장 하단
{
	// 중략...
  	"proxy": "우회할 API 주소"
}
  1. API 호출 코드 url 부분에서 도메인 부분 제거
    이전 '우회할 api주소/params'
    -> 이후 '/params'

webpack dev server proxy를 사용한 과제 2-1 결과

CORS 에러

  1. 클라이언트 프로젝트의 package.json 가장 하단
{
  	// 중략...
	"proxy": "http://localhost:3080"
}
  1. API 호출 코드 url 부분에서 도메인 부분 제거
    src/services/Bookservice.js
export const getAllBooks = async () => {
  const response = await fetch("/api/books");
  return await response.json();
};

proxy 설정 이후 API 호출 정상적으로 성공

http-proxy-middleware 라이브러리

  1. 설치
    npm install http-proxy-middleware --save
  2. setupProxy.js 파일 생성
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api', //proxy가 필요한 path prameter를 입력합니다.
    createProxyMiddleware({
      target: 'http://localhost:5000', //타겟이 되는 api url를 입력합니다.
      changeOrigin: true, //대상 서버 구성에 따라 호스트 헤더가 변경되도록 설정하는 부분입니다.
    })
  );
};
  1. API 호출 코드 url 부분에서 도메인 부분 제거
    이전 '우회할 api주소/params'
    -> 이후 '/params'

http-proxy-middleware를 사용한 과제 2-2 결과

src/setupProxy.js

const { createProxyMiddleware } = require("http-proxy-middleware");

module.exports = function (app) {
  app.use(
    "/api",
    createProxyMiddleware({
      target: "http://localhost:3080",
      changeOrigin: true,
    })
  );

  app.use(
    "/api2",
    createProxyMiddleware({
      target: "http://localhost:3070",
      changeOrigin: true,
    })
  );
};

api/booksapi2/todos 모두 잘 불러온 것을 확인할 수 있다.

0개의 댓글