[TIL] CI/CD, Github Action, YAML

ㅜㅜ·2022년 12월 7일
1

Today I learn

목록 보기
68/77
post-thumbnail

배경지식

❓ 개발 프로세스가 뭘까?

소프트웨어 시스템이나 애플리케이션 개발 및 유지보수 목적으로 수행되는 활동의 절차로 개발에 대한 전체적인 가이드라인을 제공

  • 소프트웨어 개발 프로세스 모델
    : 소프트웨어 개발 생명주기(SDLC = Software Development Life Cycle)를 기반으로 만들어짐
    요구분석 및 시스템 명세 작성 => 설계 => 구현 => 테스트 => 배포 및 유지보수=>(다시 이어짐)

🧐 개발 프로세스의 발전 과정

전통적인 개발 프로세스

: Waterfall 방식 = 폭포와 같이 한 방향으로만 프로세스 진행

보통 아래와 같은 사이클 가지며, 유지보수가 끝나면 다시 처음 단계로 돌아가 시작하는 것이 가장 기본적. 여기서 변형된 모델이 나오기도 하지만, 보통은 프로세스가 기본 모델에 추가되거나 하나의 프로세스가 세부적으로 나뉘는 수준에 그침.

요구분석 => 설계 => 개발 => 테스트 => 유지보수

워터폴 개발 방식은 실제 출시 기한을 정해놓고 순차적으로 프로세스가 진행시켜 어플리케이션(소프트웨어)를 완성해 배포하기 때문에 실제로 배포되어 유저에게 전달되는 시간이 오래 걸림. 또한 실제 디자인 또는 개발된 화면을 시각적으로 확인할 수 있는 단계는 이미 많은 단계가 지나온 시점이기 때문에 어떤 버그나 수정 사항이 생기면 다시 처음으로 돌아가 수정되기 때문에 일정과 비용 등 많은 부분에서 에로 사항이 생기게 된다. 그래서 출시 시점에 소프트웨어의 신뢰성 및 안정성을 보장 받기가 힘들며, 배포 직후에도 수많은 버그를 마주하게 될 가능성이 있음.

그래서 전통적 소프트웨어 개발 프로세스에서는 소프트웨어 안정성 개선을 위해 테스트 단계에 다양한 테스트들을 도입하기도 한다.

  • 시스템 테스트 : 모든 모듈을 통합한 후 최종적으로 완성된 시스템이 요구사항을 만족하는지 확인한다. 요구사항을 만족하지 않는다면 다시 요구분석 단계로 돌아가 새로 개발하기도 함.
  • 알파 테스트 : 완전히 개발된 시스템을 개발 현장에서 비공개로 테스트하는 것으로, 주문형 제품의 경우 개발진과 클라이언트 사이에서 동의가 이루어질 때까지 수행됨. 대기업의 경우 이 업무를 주로 하는 전문 QA팀이 존재한다.
  • 베타 테스트 : 고객의 실제 사용 환경에서 수행되는 테스트로, 미리 선별된 유저들이 해당 제품을 사용해 보고 이 과정에서 에러나 버그가 발견되면 수정하는 식으로 진행됨.

워터폴 한계
다양한 테스트 방식을 도입했더라도 사용자가 항상 최신 상태로 업데이트 해주어야 하고, 버스 수정(patch)된 버전을 유저에게 즉각적으로 전달하기 어렵다.

모던 개발 프로세스

: Asile(애자일)방식 = 스프린트라고 불리는 짧은 주기 개발 사이클 계속해서 반복함.

요구사항이 변하는 것을 당연한 전제로 두고 있는 방식으로, 계획에 의존해 형식적 절차를 끝까지 따라야하고 중간에 회귀할 수 없는 전통 개발 프로세스보다 훨씬 효율적으로 개발에 착수할 수 있다.

애자일 개발 프로세스를 적절히 사용하면 빠르게 문제를 해결해 하루에도 여러 번의 배포가 가능해진다. 이런 방식은 SaaS(Software as a Service : 서비스형 소프트웨어)를 개발하는 데 적합.

SaaS
클라우드 서비스의 한 방식으로 브라우저에 접속하기만 해도 새 버전을 즉시 사용할 수 있는 서비스 방식. 애플리케이션부터 서버, 가상화, 스토리지, 네트웨킹까지 전부 공급자쪽에서 관리하므로 고객이 제어하거나 관리할 부분이 거의 없게 됨. 따라서 사용자 업데이트에 대한 걱정에서 벗어나며 하루에 여러 번의 배포도 가능. (빠른 배포 속도는 덤)

애자일 단점

  • 스프린트에 대한 경험이 있으며 빠른 반복 작업에 익숙한 스크럼 마스터가 필요함
  • 고객이 수많은 변경 사항을 검토해야만 하는 번거로움 발생
  • 팀원이 잘 조직되어 있지 않거나 자립성이 떨어지는 경우 애자일론을 채택할 시 문제가 발생

전통 개발 프로세스 vs 모던 개발 프로세스

  • 전통 개발 프로세스가 적합한 상황
    - 높은 예측 가능성과, 순차적인 프로젝트 타임라인, 사전 확정 예산이 필요한 경우
    - 프로젝트 팀의 경험이 적은 경우
    - 요구사항이 간단하거나, 타임라인이 긴 프로젝트를 수행하는 경우
  • 모던 개발 프로세스가 적합한 상황
    - 요구사항이 간단하거나, 타임라인이 긴 프로젝트를 수행하는 경우
    - 프로젝트가 완벽히 수행될 때까지 결과물을 기다리는 것보다 결과물에 대해 빠른 피드백이 필요한 경우



❓ DevOps

전통적 IT 조직 구조로는 개발팀과 운영팀이 소프트웨어 개발과 관리 및 유지보수를 담당함.

DevOps
특징잦은 배포 및 업데이트, 애플리케이션을 통해 새로운 기능(리소스)제공프로덕션 앱의 안정성 확보, 인프라 관리, 모니터링 및 제어

특징을 보면 알 수 있듯 변화와 안정성의 충돌로 갈등을 야기하기도 함. 이런 갈등은 제품의 릴리즈 주기를 길어지게 만듦.

DevOps는 소프트웨어 개발과 IT 운영의 합성으로 소프트웨어를 자주, 빨리 그리고 안전하게 배포하는 것을 목표로 하며, 그렇기 때문에 애자일 개발 프로세스를 기반으로 한 것이라고 볼 수 있음.

DevOps는 특정 업무라던지 부서가 아닌 일종의 ‘개발 문화’임. 만약 서비스가 중단된다면 누구든 문제점을 진단하고 시스템을 복구해 운영할 수 있는 절차를 알고 있어야 한다. 이를 위한 기술과 지식이 제공되기 위해 훈련과 효과적 협업체계를 마련하는 것이 매우 중요. 그러나 실제 업무에서는 업무 분리를 위해 DevOps 팀, 혹은 부서를 두고 있을 수도 있다.

DevOps 특징

  • DevOps는 개발에서 운영까지 하나의 통합된 프로세스로 묶어내고 사용하는 툴과 시스템을 표준화하여 의사소통의 효율성을 확보하고 일련의 작업들을 자동화한다. ⇒ 코드 통합, 테스트, 배포 과정을 자동화
  • 이 부분은 지속적으로 유지되어야 할 필요가 있는데, 지속적 통합 및 배포(CI/CD)라고 하며 DevOps의 핵심 원칙이다. 잘 구축된 CI/CD는 애플리케이션의 배포 시간을 크게 단축시킴.

DevOps 사례

: 넷플릭스, Flicker, 스포티파이





CI/CD

🧩 CI

개발자를 위한 자동화 프로세스인 지속적인 통합 = Continuous Integration

CI를 성공적으로 구현할 경우 어플리케이션에 대한 코드 변경 사항이 정기적으로 빌드 및 테스트되어 공유 리포지토리에 통합되므로 여러 명의 개발자가 동시에 어플리케이션 개발과 관련된 코드 작업 할 경우 충돌할 수 있는 문제 해결 가능.

Code - Build - Test 단계에서 할 수 있음.


🧩 CD

지속적인 서비스 제공 = Continuous Delivery & 지속적 배포 = Continuous Deployment

CD 두 용어는 상호 교환적으로 사용되며 두 가지 의미 모두 파이프라인의 추가 단계에 대한 자동화를 뜻하지만 때로는 얼마나 많은 자동화가 이루어지고 있는지 설명하기 위해 별도로 사용되기도 함.

Release - Deploy - Operate 단계에서 가능.



❓ CI/CD 파이프라인

수없이 진행되는 배포 과정을 자동화시키는 방법을 CI/CD 파이프라인이라고 한다.
자동화를 하는 부분은 보통 코드가 빌드되면서 최종적으로 배포가 되는 단계 까지.

CI/CD 파이프라인 구성하는 기본 단계와 수행 작업

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

CI/CD 파이프라인 구성 요소

  • 빌드 (소프트웨어 컴파일)
  • 테스트 (호환성 및 오류 검사)
  • 릴리스 (버전 제어 저장소의 애플리케이션 업데이트)
  • 배포 (개발에서 프로덕션 환경으로의 변환)
  • 규정 준수 및 유효성 검사

이렇게 구축된 파이프라인은 최신 버전의 소프트웨어 애플리케이션을 업데이트하고 제공하려는 일련의 처리 단계에 걸리는 시간을 수동으로 하는 것보다 더 빠르고 안정적이며 효과적으로 줄여주고 CI/CD 인프라와의 호환성과 효율성을 높여준다.







Github Action

GitHub Actions는 Github가 공식적으로 제공하는 빌드, 테스트 및 배포 파이프라인을 자동화할 수 있는 CI/CD 플랫폼.

GitHub Action은 Github 레포지토리에서 바로 소프트웨어 개발 워크플로우를 자동화, 사용자 지정 및 실행할 수 있게 함. CI/CD를 포함하여 원하는 작업을 수행하기 위한 작업을 검색, 생성 및 공유하고 완전히 사용자 정의된 워크플로에서 작업을 결합할 수 있다.

레포지토리에서 Pull Requestpush 같은 이벤트를 트리거로 GitHub 작업 워크플로(Workflow)를 구성할 수 있는데, 워크플로는 하나 이상의 작업이 실행되는 자동화 프로세스로, 각 작업은 자체 가상 머신 또는 컨테이너 내부에서 실행된다.

워크플로는 .yml (혹은 .yaml ) 파일에 의해 구성되며, 테스트, 배포 등 기능에 따라 여러개의 워크플로도 만들 수 있음. 생성된 워크플로는 .github/workflows 디렉토리 이하에 위치한다.

비공개 레포지토리의 경우 Github Actions가 작동할 때의 용량과 시간이 제한되어있으며 공개 레포지토리는 무료로 사용 가능.





YAML

Yet Another Markup Language = 사람이 읽을 수 있는 데이터 직렬화 언어 의미

(YAML ain’t markup language(재귀 약어)로 생각하는 사람도 있는데 후자는 YAML이 문서가 아닌 데이터용임을 강조하는 말이라고 생각하시면 됨.)

파일로 작성시 확장자는 .yaml혹은 .yml 확장자를 가짐.

YAML은 사람이 읽을 수 있고 이해하기 쉬워 프로그래밍 언어 중에서도 인기가 높으며 다른 프로그래밍 언어와 함께 사용할 수도 있음.

YAML은 그 유연성과 접근성으로 인해 자동화 프로세스를 생성하는 데에도 사용된다.

JSON 🆚 YAML

공통점

  • key-value 형태로 작성
  • 계층 구조를 가진다

차이점

  • YAML은 큰따옴표 없이 문자열 작성이 가능해 설정을 위한 스펙이나 프로퍼티 값 등이 JSON에 비해 한 눈에 들어옴

  • YAML은 {} 형태로 감싸줄 필요가 없어서 스코프의 압박(잘못 쓰면 일일이 어디가 처음이고 끝인지 찾아야함)에서 벗어날 수 있음

  • YAML은 주석을 작성할 수 있음 (JSON은 불가) ⇒ 커뮤니케이션 하기에 수월함

  • YAML이 JSON의 상위 호환이므로 json 문서를 그대로 yaml 파일로 사용하거나 원하는 부분만 손볼 수도 있음. (반대로 yaml 파일을 json 파일로 변환해 사용할 수도 있다)

❓ YMAL 문법

# : 주석

--- : 문서의 시작 (선택사항)
... : 문서의 끝 

들여쓰기 : 기본적으로 2, 4칸 지원하는데 2칸 추천하며 스페이스 키로 들여써야 함. 

key : value (: 다음에는 무조건 공백 문자가 와야 함)

____________________________________________

자료형 
: int, string, boolean, 리스트, 매핑 지원 
=> int, string 타입은 Scalar라 부름.
=> 배열, 리스트는 시퀀스(Sequence)라 부름. 
=> 매핑에는 기본 표현인 key-value 쌍, hash, dictionary가 포함됨. 

#int(숫자)
int_type: 1

#string(문자열)
string_type: "1"

#blooean(/거짓)
boolean_true_type: true
boolean_false_type: false

#이외에 yes, no로 작성하기도 합니다.
yaml_easy: yes
yaml_difficult: no

#리스트(배열 형태)
person:
  name: Chungsub Kim
  job: Developer
  skills: 
    - docker
    - kubernetes
  # JSON 형식의 "skill" : [docker, kubernetes]와 같습니다.

____________________________________________

객체 표현 
: Key 작성 후 두 칸 들여써서 key-value 형태로 작성해주거나 
key 작성한 후 중괄호로 한 번 묶고 key-value 형태로 작성 

key: 
  key: value
  key: value

#또는 이렇게도 작성합니다. 가독성을 위해 사용합니다.
key: {
  key: value,
  key: value
}

____________________________________________

Text 
: 줄바꿈 표현 |, 줄바꿈 무시표현 > 

# |는 줄바꿈 표현입니다.
# JSON 형식의 "comment_line_break": "Hello codestates.\nIm kimcoding.\n"과 같습니다.
comment_line_break: |
  Hello codestates.
  Im kimcoding.

# >는 줄바꿈 무시 표현입니다.
# JSON 형식의 "comment_single_line": "Hello world my first coding."과 같습니다.
comment_single_line: >
  Hello world
  my first coding.

____________________________________________

문자열 따옴표 
: key-value 쌍에서 value에 :가 들어간 경우는 반드시 따옴표가 필요

# error가 납니다.
windows_drive: c:

# 이렇게 써야 합니다.
windows_drive: "c:"
windows_drive: 'c:'

YMAL은 일반적으로 설정 파일(configure file 등)에 사용하기에 좋음.

spring boot, github action 등 다양한 CI/CD 툴이나 프레임워크에서 사용되고 있다.

YAML을 실제로 사용하고 있는 프레임워크로 쿠버네티스를 들 수 있다. 기본적인 팟, 레플리카, 디플로이먼트 등 모든 내부 오브젝트가 yml문서로 작성되어 있으며, yaml고유 기능 중 하나인 문서 스트림을 사용해 클러스터 전체의 설정을 파일 하나로 관리하기도 함.





과제 : github Action 이용해 클라이언트 배포하기

클라이언트 배포 과정은 위에서 배웠듯 Source, Build, Deploy 세 단계로 이루어져 있다.

  • Source : 깃허브의 reference 브랜치에 코드가 커밋되면
  • Build : github actions의 YMAL 파일에 적힌 명령어 토대로 Webpack 이용해 빌드한다
  • Deploy : github actions의 YMAL 파일에 적힌 명령어를 토대로 S3 빌드 결과를 업로드한다.

✅ Bare Minimum Requirements

  • 래퍼런스 코드 중 클라이언트 부분을 S3으로 배포한다.
  • Github Action을 이용한다.

✅ 해결 과정

🟢 client.yml 파일 생성

과제에서 미리 client.yml 파일에 들어갈 내용들을 거의 작성해서 틀을 제공해주었다.
.github 폴더에 있는 workflows 폴더에 client.yml 파일을 생성하고, 아래 내용을 입력해주었다.

// .github/workflows/client.yml

name: client
on:
  push:
    branches:
      - <?>
jobs:
  build:
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout source code.
        uses: actions/checkout@v2
      - name: Install dependencies
        run: <?>
        working-directory: ./my-agora-states-client
      - name: Build
        run: <?>
        working-directory: ./my-agora-states-client
      - name: SHOW AWS CLI VERSION
        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: |
          <?>
      - 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 <?> \
            --region ap-northeast-2 \
            build s3://<?> \
            --delete
        working-directory: <?>

입력된 코드 내용은 아래 그림과 같이 단계로 구분되어 있다고 생각하면 된다.

실제로 깃허브에서 제대로 동작하는지 확인할 때에도 위와 같은 단계를 거친다는 것을 알 수 있다.

ymal 코드를 주석으로 분석한 내용을 스터디원 중 도사님 한 분이 공유해주셨다...🎅
그냥 복붙해서 올리는 건 너무 양아치 같으니... 아이패드로 직접 써가면서 다시 공부해서 올린다.

실제로 과제를 진행하면서는 대강만 이해를 한 상태로 진행한 거라 이렇게 각각의 키워드들이 어떤 것을 뜻하는지 알 수 있어서 좋았다.


🟢 AWS key들 env로 지정해주기

<?>로 되어 있는 부분들을 채우기 전에 AWS의 Access Key와 Secret key를 환경변수로 지정해주는 과정이 필요했다.

깃허브에서 해당 리포지토리의 settings - secrect - actions 로 들어가 new repository secret으로 시크릿을 생성한다. Name 부분에는 위 틀에서 미리 지정해준 'AWS_ACCESS_KEY_ID' , 'AWS_SECRET_ACCESS_KEY'를 입력해주었고, secret 부분에는 AWS의 ACCESS KEY와 SECRET KEY를 입력해주면 된다.

과제를 위해서 Aws 계정 자체를 코드스테이츠에서 생성해주었는데,
여러분에게 전달드린 계정 내용 중 AWS ACCESS KEY와 AWS SECRET KEY를 사용하게 되실 겁니다. 이 두 개의 key는 절대로 하드코딩 및 외부 노출이 일어나면 안 되는 key들입니다. 해당 key 두 개는 어떤 방식으로든 노출이 일어나게 되면 노출하신 분은 AWS에 접근하는 것 자체가 제한되기 때문에 꼭 명심해주시고 과제에 임해주시길 바랍니다. 라고 하셨었으니... 노출되지 않게 조심 또 조심해야한다 !


🟢 빈 부분들 채워주기

  • branches 부분에는 해당하는 브런치인 reference를 입력해주고,
    Install dependencies 단계와 Build 단계의 run 부분에는 각각 npm install과 npm run build를 입력해준다.

  • show AWS CLI version 단계의 run 부분은 처음에 이게 어떤 단계인지 잘 몰라 헤맸는데 AWS의 버전이 확인하고 싶은 것이기 때문에 간단하게 aws --verion이라고 입력해줄 수 있다.

  • 마지막으로 Sync Bucket 부분이 복병이었는데, aws s3 sync 명령어에 대해 잘 알지 못했기 때문이다.

    aws s3 sync 기본 명령어 형태는 아래와 같다.
    aws s3 sync /<ORIGIN_PATH:올라갈 파일의 경로> /<TARGET_PATH: 버킷의 경로>

    과제에서는 줄바꿈이 되어 있고 리전 옵션이 먼저 나와있어서 조금 헷갈렸는데,(알아서 옵션인 것을 인식하기 때문에 순서가 조금 뒤바뀌어도 상관없다고 함) 결국 build가 우리가 Build 단계에서 npm run build로 만들어진 build 파일의 경로를 뜻하고 있고, 이 파일이 s3에 올라갈 파일이다. 그리고 나머지 작성해주어야 할 것이 버킷의 경로인데, 버킷의 경로는 AWS의 S3에서 버킷 경로를 찾을 수 있었다.
    (이래저래 찾으면서 보니 버킷의 이름도 노출되는 것이 좋지 않다고 해서 환경변수로 함께 설정해주는 경우도 있다고 한다.)


🟢 git push 해주고 제대로 동작하는지 확인

$ git add .
$ git commit -m "커밋할 내용"
$ git push 레포지토리이름 브랜치이름 

profile
다시 일어나는 중

0개의 댓글