CI는 Continuous Integration, 즉 지속적 통합을 의미합니다. 쉽게 말하면 코드를 푸시하거나 PR을 열었을 때 자동으로 정해진 작업을 실행해주는 파이프라인입니다.

빌드가 되는지, 테스트를 통과하는지, 린트 규칙을 지키는지 등을 사람이 일일이 확인하지 않아도 기계가 먼저 검사해줍니다. 사람은 코드 로직을 리뷰하는 데 집중할 수 있게 됩니다.
GitHub에서는 GitHub Actions라는 이름으로 CI 기능을 공식 지원합니다. 별도의 외부 서비스 없이 리포지토리 안에 파일 하나만 추가하면 바로 사용할 수 있습니다.
CI를 구축할 수 있는 툴은 GitHub Actions 외에도 여러 가지가 있습니다.
Jenkins는 플러그인 생태계가 방대해 커스터마이징이 자유롭지만, 직접 서버를 운영해야 하고 초기 설정이 복잡합니다.
CircleCI는 설정이 간단하고 빠르지만 무료 플랜에 크레딧 제한이 있습니다. GitLab CI/CD는 GitLab 사용자라면 별도 설정 없이 쓸 수 있지만, 저희 팀은 GitHub을 사용하고 있어 해당되지 않았습니다.
GitHub Actions를 선택한 이유는 단순합니다. 이미 GitHub을 쓰고 있어서 리포지토리에 파일 하나만 추가하면 바로 동작하고, 공개 리포지토리는 무료라 별도 비용 부담도 없습니다. 소규모 팀이나 사이드 프로젝트라면 가장 현실적인 선택입니다.
GitHub Actions는 리포지토리 루트에 .github/workflows/ 디렉토리를 만들고, 그 안에 .yml 파일을 추가하는 것으로 시작합니다. 파일 이름은 자유롭게 지어도 됩니다.
프로젝트 루트/
├── .github/
│ └── workflows/
│ └── fe-build.yml ← 이 파일 하나면 됩니다
├── frontend/
└── ...
파일을 만들어 내용을 작성하고 main 브랜치에 푸시하면, 이후 PR이 열릴 때마다 자동으로 워크플로우가 실행됩니다. 별도 설치나 서버 설정은 필요하지 않습니다.

직접 코드 에디터에서 해당 파일을 작성해도 되고, 해당 레포지토리의 Actions 탭에서 New workflow 버튼을 클릭해 깃허브에서 파일을 작성할 수 있습니다.

set up a workflow yourself 버튼을 클릭해 직접 코드를 작성할 수도 있고, 검색을 통해 템플릿을 적용할 수도 있습니다.

실제 적용한 워크플로우 코드를 하나씩 살펴보겠습니다.
name: FE 빌드 테스트
on: [pull_request]
워크플로우의 이름을 FE 빌드 테스트로 지정하고, PR이 열릴 때마다 실행되도록 설정합니다. on 필드에 push를 넣으면 커밋 푸시 시에도 실행할 수 있습니다.
jobs:
build:
if: |
github.actor == 'wo-o29' ||
github.actor == 'eunoia-jaxson' ||
github.actor == 'jin123457' ||
github.actor == 'mlnwns'
if 조건으로 특정 팀원이 PR을 열었을 때만 실행되도록 제한했습니다. 해당 레포지토리가 백엔드 팀원과 공용으로 활용하기 때문에, 프론트엔드 팀원이 PR을 열때만 워크플로우가 실행되도록 했습니다.
runs-on: ubuntu-latest
워크플로우가 실행될 가상 환경을 지정합니다. GitHub이 제공하는 Ubuntu 서버 위에서 빌드가 돌아갑니다. 내 컴퓨터가 꺼져 있어도 됩니다.
steps:
- name: 코드 체크아웃
uses: actions/checkout@v4
GitHub 서버 위에 레포지토리 코드를 내려받는 단계입니다. 이 단계가 없으면 서버는 빈 상태이므로 반드시 맨 처음에 와야 합니다.
- name: 노드 설치
uses: actions/setup-node@v4
with:
node-version: "20.x"
Node.js를 설치합니다. 버전을 20.x로 고정해 로컬 환경과 CI 환경을 맞춥니다. "내 로컬에서는 됐는데 왜 CI에서 안 되지?" 라는 상황을 방지하는 데 중요한 부분입니다.
- name: pnpm 설치
run: npm install -g pnpm
프로젝트가 pnpm을 패키지 매니저로 사용하기 때문에 별도로 설치합니다. npm이나 yarn을 사용한다면 이 단계는 생략해도 됩니다.
- name: 의존성 설치
run: pnpm install
working-directory: ./frontend
- name: 빌드 실행
run: pnpm run build
working-directory: ./frontend
./frontend 디렉토리에서 의존성을 설치하고 빌드를 실행합니다. 모노레포 구조처럼 루트와 프론트엔드 폴더가 분리된 경우 working-directory로 경로를 명시해야 합니다.

위 스크린샷처럼 PR 페이지에서 체크 결과를 바로 확인할 수 있습니다.

빌드가 성공하면 초록색 체크 표시, 실패하면 위의 이미지처럼 빨간색 표시가 붙습니다.

해당 워크플로우를 클릭하면 실패한 경우, 어떤 이유로 빌드 테스트가 실패했는지 원인을 확인할 수 있어서 문제를 빠르게 파악하고 수정할 수 있습니다.
이를 통해 코드의 안정성을 유지하고, 협업 과정에서 발생할 수 있는 오류를 사전에 방지할 수 있습니다.
CI를 도입하기 전을 떠올려 보면, 아래와 같은 상황들이 존재했었습니다.
CI는 사람으로 인해 발생할 수 있는 실수를 머지 전에 잡아주는 안전망 역할을 합니다.
빌드 안정성 보장
PR 단계에서 빌드가 깨지는 코드를 걸러낼 수 있습니다. main 브랜치는 항상 빌드가 가능한 상태를 유지하게 됩니다.
팀 신뢰도 증가
CI가 통과된 PR은 최소한의 신뢰를 인증합니다. 팀 전체의 코드베이스에 대한 신뢰도가 올라갑니다.
자동화로 인한 반복 작업 제거
매번 수동으로 pnpm install && pnpm run build를 직접 실행하지 않아도 됩니다.