애플리케이션을 개발하다보면 빠지지않는 용어 CI/CD!
용어의 정확한 의미는 무엇이고, 왜 해야하며 어떻게 해야하는지에 대해 담아본다.
CI는 Continuous Intergration의 약자로 지속적 통합이라는 뜻이다.
CD는 Continuous Delivery/Deploy의 약자로 지속적 배포란 뜻이다.
CD/CD 자동화를 통해 코드를 자동으로 빌드, 테스트, 배포할 수 있고 효율적인 애플리케이션 개발을 할 수 있다.
CD는 대략적으로 배포 자동화라는 것을 눈치챌 수 있지만 CI는 직관적으로 잘 와닿지 않는 개념이다.
CI란 개발자들이 작성한 코드 변경사항을 공유 저장소(레포지토리)에 정기적으로 통합하고 자동으로 빌드 및 테스트하는 프로세스다.
일반적으로 개발한 코드를 PR을 날리고 머지를 하면 기존의 코드와의 통합 과정을 거친 것이다.
CI는 통합 과정에서 더 나아가 코드를 테스트하고 유효한지 검사하는 작업이다.
github에서 PR을 성공적으로 날린 것과는 별개로 머지가 불가하다고 나오는 것을 본 적이 있을 것이다.
바로 이것이 github에서 진행한 CI다.
github는 PR을 보낼 때, 자동으로 CI를 실행해 변경 사항을 테스트하고 실패시 머지할 수 없게 한다.
이 과정을 통해 개발자들은 머지하기 전에 충돌을 해결하고 안정적으로 코드를 통합할 수 있다.
일반적으로 CI로는 Jest를 사용한 단위테스트 실행, 통합테스트 실행, 정적 코드 분석, 빌드 및 배포 자동화 등이 있다.
이를 통해 코드 변경 사항이 기존 코드와 충돌하는지, 예상대로 동작하는지를 빠르게 확인할 수 있다. 즉, 기존 코드와 충돌 문제가 없는지에 대한 테스트를 실행한 후 빌드를 하는 프로세스를 자동화하여 레포지토리에 통합시키는 것을 말한다.
여러 개발자가 동시에 코드를 작업할 때 코드 변경 사항이 충돌되는 경우가 있다. CI를 통해 변경 사항이 레포지토리에 통합되기 전에 충돌을 확인하고 최소화할 수 있다.
자동화된 빌드 및 테스트를 통해 코드 품질을 지속적으로 관리할 수 있다. 이를 통해 안정적이고 신뢰할 수 있는 소프트웨어를 개발할 수 있어 품질을 향상시킬 수 있다.
CD와 마찬가지로 반복적인 작업을 자동화하여 시간과 비용을 절감하고 개발에 집중할 수 있도록 한다.
우리는 열심히 개발한 애플리케이션을 다른 사람들도 이용할 수 있게 하기 위해서 배포한다. 배포를 통해 local 환경뿐만 아니라 global 환경에서도 애플리케이션에 접근가능하기 때문이다.
내가 가장 처음 했던 배포 방식은 github가 지원하는 github-pages를 이용한 것이었다.github-pages는 배포 브랜치로 설정한 브랜치에 push가 되면 자동적으로 최신 커밋에 대한 배포를 해준다.이게 바로 자동화 배포다.
만약 이러한 자동화 과정이 없다면 매번 배포를 하기 위해 반복적인 작업을 거쳐야하는데 자동화를 통해 시간과 비용을 효율적으로 절감할 수 있으며 사람의 실수로 인한 오류를 줄일 수 있어 안전성을 향상시킬 수 있다.
또한 자동화 배포는 릴리스 수를 늘릴 수 있다. 배포를 자주한다는 것은 작은 변경 사항도 릴리스한다는 의미다. 이는 큰 변경 사항을 릴리스하는 것보다 피드백을 빨리 받을 수 있고 문제가 발생했을 때 빠르게 파악하고 수정할 수 있음을 의마한다. 한 번에 많은 변경 사항을 릴리스하는 것보다 위험을 분산시킬 수 있으며 제품을 고객에게 제공하는 시간이 단축되어 시장에서의 경쟁력을 향상시킬 수 있따.
netlify, vercel 같은 호스팅 사이트에서도 레포지토리와 브랜치를 선택하면 커밋이 push 될 때마다 자동화 배포를 해준다.
이처럼 CD는 대부분의 사람들이 편리성을 경험했을 것이다.
CI와 CD 모두 빌드를 포함하는데, 각각의 목적과 시점이 다르다.
CI는 개발자들이 작성한 코드의 통합과 테스트를 위한 빌드,
CD는 성공적인 CI빌드를 프로덕션 환경으로 배포하기 위한 빌드
git flow 방식을 따르면 다음 과정에서 CI와 CD를 적용할 수 있다.
feature -> develop 브랜치로 병합 (CI)
develop -> deploy 브랜치로 병합 (CD)
다만, develop 브랜치와 deploy 브랜치 간에는 환경 변수, 구성 파일(yaml 파일 등), 라이브러리 버전 등 일부 차이가 있을 수도 있다.
따라서 개발 브랜치에서 배포 브랜치로의 코드 병합시에도 CI가 필요하다.
이는 개발 브랜치와 배포 브랜치의 차이점을 확인하고 적절한 테스트를 수행하여 배포되는 코드의 품질과 안전성을 보장하기 위함이다.
feature -> develop (CI)
develop -> deploy (CI, CD)
다음은 Github에서 제공하는 클라우드형 CI/CD 툴인 GitHub Actions를 사용해 AWS에 자동화 배포하는 workflow를 작성한 코드다.
GitHub Pages에 배포하는 workflow script은 따로 포스팅했다.
.github/workflows
디렉토리에 .yaml
확장자 파일을 생성한다.
name
은 workflow의 이름을 정의한다.on
: 언제 workflow를 실행할지를 설정한다. jobs
: workflow가 포함하는 작업을 정의한다. runs-on
: 작업을 실행할 환경을 최신 버전의 Ubuntu로 설정한다.steps
: 작업 내에서 실행할 단계들을 정의한다.uses
: 다른 레포지토리 액션을 가져와서 현재의 workflow에 적용할 수 있다. uses: owner/repo@ref
owner
: 액션 소유자의 GitHub 사용자명이나 조직명repo
: 액션을 포함한 레포지토리의 이름ref
: 사용할 액션의 브랜치, 태그 또는 커밋 해시로 기본값은 main
브랜치다음은 feature -> develop, develop -> deploy 브랜치로 merge 하는 과정에서 실행되는 CI workflow다.
name: CI
on:
push:
branches:
- deploy
- develop
pull_request:
branches:
- deploy
- develop
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: npm install
- name: Run lint
run: npm run lint
- name: Run tests
run: npm run test
- name: Run build
run: npm run build
jobs
속성을 통해 build 작업을 정의하고 있다. uses: actions/checkout@v2
ctions/checkout@v2
: GitHub Actions에서 제공하는 액션으로 코드를 체크아웃한다.name
: 각 steps 이름을 정의한다.with
: 액션의 옵션을 지정한다. run
: npm 명령어를 사용하여 종속성을 설치하거나 lint 및 빌드를 실행한다.위의 CI workflow script에서는 종속성을 설치하고, 린트, 테스트 및 빌드를 자동화하고 있다.
다음은 deploy에 push 이벤트가 발생할 때 AWS S3에 배포하는 CD workflow다.
name: Deploy to S3
on:
push:
branches:
- deploy
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Transfer to S3 for serving static
uses: jakejarvis/s3-sync-action@master
with:
args: --acl public-read --follow-symlinks --delete
env:
AWS_REGION: ${{ secrets.AWS_BUCKET_REGION }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_S3_BUCKET: ${{ secrets.AWS_BUCKET_NAME }}
SOURCE_DIR: "build"
- name: Transfer to S3 for serving static
uses: jakejarvis/s3-sync-action@master
with:
args: --acl public-read --delete
uses
: CD의 일부분으로, 정적 파일을 S3로 파일을 동기화하고 업로드한다.--acl public-read
: 전송된 파일의 ACL(Access Control List)를 public-read로 설정하여 업로드된 파일에 공개 읽기 권한을 설정한다. --delete
: 로컬 디렉토리와 S3 버킷을 동기화하여 로컬에 없는 파일이나 객체를 S3 버킷에서 삭제한다.env
${{환경변수}}
로 GitHub secret environment variables에 접근할 수 있다.