
최근에 사이드 프로젝트를 만들면서
GitHub Actions를 활용해 자동화된 CI 환경을 구축한 경험을 정리해보려고 합니다.
✅ 왜 CI가 필요했을까?
프로젝트가 커지고 브랜치가 많아지다 보니 이런 문제가 생기더라고요.
• 코드 수정할 때마다 직접 build, test를 돌려봐야 하는 번거로움
• 과거의 내가 만든 코드가 기존 기능을 깨뜨릴 수도 있음
• 자잘한 수정만 했을 때도 전체 테스트를 돌리는 건 시간 낭비
그래서 자연스럽게 이런 생각이 들었습니다.
“PR 올리면 자동으로 테스트 돌고, 이상 있으면 merge 못 하게 만들 수 없을까?”
➡️ 이걸 해결해줄 수 있는 게 바로 CI (Continuous Integration) 입니다.
🤖 왜 GitHub Actions를 선택했을까?
CI 도구는 정말 많습니다. Jenkins, Travis CI, CircleCI…
그런데 전 GitHub에서 코드 관리하고 있으니까, GitHub Actions가 가장 자연스럽더라고요.
• 별도 설치 필요 없이 .yml 파일 하나면 끝!
• GitHub PR과 바로 연동됨
• 무료 사용량도 넉넉
즉, 가볍게 시작하고도 꽤 강력하다!
🎯 목표: 이런 자동화를 만들고 싶었어요
• PR이 열릴 때
• 변경된 파일 중 테스트가 필요한 경로가 있다면
• pnpm install, pnpm build, pnpm test 자동 실행
• 테스트 실패 시 merge 불가 메시지 출력
📂 테스트가 필요한 경로 기준은?
src/components/
src/utils/
src/hooks/
src/context/
src/pages/
src/App.tsx
src/index.tsx
위 경로 중 하나라도 수정되었다면 → 테스트 실행!
아니면 → 테스트 생략!
⚙️ GitHub Actions 설정
.github/workflows/ci.yml 경로에 아래와 같이 작성했습니다.
<pre><code class="language-yaml">name: Project CI
on:
pull_request:
branches: [ main ]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check changed files
id: changed_files
run: |
git fetch origin main
CHANGED_FILES=$(git diff --name-only origin/main HEAD)
echo "Changed files:"
echo "$CHANGED_FILES"
# 테스트가 필요한 파일들이 변경되었는지 확인
NEEDS_TESTING=false
while IFS= read -r file; do
case "$file" in
src/components/*|src/utils/*|src/hooks/*|src/context/*|src/pages/*|src/App.tsx|src/index.tsx)
NEEDS_TESTING=true
break
;;
esac
done <<< "$CHANGED_FILES"
if [ "$NEEDS_TESTING" = "true" ]; then
echo "needs_testing=true" >> $GITHUB_OUTPUT
else
echo "needs_testing=false" >> $GITHUB_OUTPUT
fi
- name: Setup Node.js
if: steps.changed_files.outputs.needs_testing == 'true'
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install pnpm
if: steps.changed_files.outputs.needs_testing == 'true'
uses: pnpm/action-setup@v2
with:
version: 8
- name: Install dependencies
if: steps.changed_files.outputs.needs_testing == 'true'
run: pnpm install
- name: Build
if: steps.changed_files.outputs.needs_testing == 'true'
run: pnpm build
- name: Run tests
if: steps.changed_files.outputs.needs_testing == 'true'
run: pnpm test -- --passWithNoTests
- name: Check test status
if: steps.changed_files.outputs.needs_testing == 'true' && failure()
run: |
echo "Tests failed. This PR cannot be merged until all tests pass."
exit 1
</code></pre>
🔍 구성 요소 설명
⚙️ GitHub Actions 설정 전체 코드 + 한 줄씩 설명
name: Project CI
• 이 워크플로우의 이름입니다. GitHub Actions 탭에서 표시되는 이름이에요.
• "프로젝트의 CI 자동화"라는 의미로 이름을 붙였어요.
on:
pull_request:
branches: [ main ]
• 이 워크플로우는 **PR(Pull Request)**이 main 브랜치로 열릴 때 자동으로 실행됩니다.
• 즉, PR이 생성되거나 업데이트될 때마다 CI가 동작하게 됩니다.
jobs:
build-and-test:
runs-on: ubuntu-latest
• build-and-test라는 **작업(Job)**을 정의합니다.
• GitHub이 제공하는 최신 우분투 환경에서 이 작업을 실행합니다.
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
• GitHub 저장소의 코드를 체크아웃(다운로드)합니다.
• fetch-depth: 0은 전체 git 기록을 가져온다는 의미입니다.
→ 나중에 git diff로 변경된 파일을 확인하기 위해 꼭 필요합니다.
- name: Check changed files
id: changed_files
run: |
• 변경된 파일 목록을 확인하는 스크립트를 실행합니다.
• id: changed_files → 이 step의 결과를 나중에 if: 조건에서 사용하기 위해 ID를 지정해둔 것입니다.
git fetch origin main
CHANGED_FILES=$(git diff --name-only origin/main HEAD)
• main 브랜치와 현재 PR의 차이점(변경된 파일 목록)을 가져옵니다.
echo "Changed files:"
echo "$CHANGED_FILES"
• 디버깅 용도로 어떤 파일이 변경되었는지 로그에 출력합니다.
NEEDS_TESTING=false
while IFS= read -r file; do
• 테스트가 필요한 변경이 있는지 확인하기 위한 변수입니다.
case "$file" in
src/components/*|src/utils/*|src/hooks/*|src/context/*|src/pages/*|src/App.tsx|src/index.tsx)
NEEDS_TESTING=true
break
;;
esac
done <<< "$CHANGED_FILES"
• 위에 나열된 경로에 속한 파일이 변경되었는지 case 문으로 하나하나 검사합니다.
• 해당되면 NEEDS_TESTING=true로 설정하고 루프를 종료합니다.
if [ "$NEEDS_TESTING" = "true" ]; then
echo "needs_testing=true" >> $GITHUB_OUTPUT
else
echo "needs_testing=false" >> $GITHUB_OUTPUT
fi
• 결과를 GitHub Actions의 output 변수로 전달합니다.
• 이 값을 이용해서 나머지 단계들이 실행될지 말지 판단합니다.
- name: Setup Node.js
if: steps.changed_files.outputs.needs_testing == 'true'
uses: actions/setup-node@v4
with:
node-version: '20'
• 테스트가 필요한 경우에만 Node.js 20을 설치합니다.
• pnpm도 Node.js 위에서 작동하므로 반드시 설치 필요!
- name: Install pnpm
if: steps.changed_files.outputs.needs_testing == 'true'
uses: pnpm/action-setup@v2
with:
version: 8
• GitHub Actions에서 공식적으로 제공하는 pnpm 설치용 액션을 사용합니다.
• 여기서 중요한 포인트 👉 pnpm/action-setup은 GitHub Actions에서 공식적으로 지원됩니다!
- name: Install dependencies
if: steps.changed_files.outputs.needs_testing == 'true'
run: pnpm install
• package.json을 기반으로 의존성(라이브러리)을 설치합니다.
- name: Build
if: steps.changed_files.outputs.needs_testing == 'true'
run: pnpm build
• 빌드 명령어를 실행합니다.
• 프로젝트가 Vite, Webpack, Next 등 어떤 도구를 사용하든 여기서 빌드됩니다.
- name: Run tests
if: steps.changed_files.outputs.needs_testing == 'true'
run: pnpm test -- --passWithNoTests
• 테스트 명령어를 실행합니다.
• --passWithNoTests는 테스트 파일이 없더라도 실패하지 않게 해주는 옵션입니다.
- name: Check test status
if: steps.changed_files.outputs.needs_testing == 'true' && failure()
run: |
echo "Tests failed. This PR cannot be merged until all tests pass."
exit 1
• 테스트가 실패한 경우, 명시적인 오류 메시지를 출력하고 PR 병합을 막습니다.
• CI에서 실패하면 GitHub에서 빨간불 표시가 뜨고 merge 불가!
🔄 pnpm과 GitHub Actions의 호환성은?
항목내용
✅ 공식 지원 | pnpm/action-setup이라는 GitHub Actions 공식 플러그인 존재 |
✅ Node와 호환 | actions/setup-node와 잘 연동됨 |
✅ lockfile 사용 | pnpm-lock.yaml을 통해 버전 고정 및 캐시 최적화 가능 |
✅ workspace 호환 | 모노레포 구성에서도 pnpm workspace 완벽하게 동작함 |
✅ 속도 | GitHub Actions 캐시 + pnpm 조합 → 빠른 빌드와 테스트 가능 |
✅ GitHub Actions 구축 효과
항목효과
PR 자동 체크 | 빌드 & 테스트 자동 수행 |
PR 병합 전 안정성 확보 | 깨지는 코드 PR은 머지 차단 |
선택적 테스트 | 불필요한 테스트 낭비 방지 |
개발 생산성 향상 | 사람 손이 덜 감, 실수도 줄어듬 |
🔚 마무리
이번에 CI를 직접 구성하면서 느낀 건…
“자동화는 개발자의 집중력을 지켜주는 방패다.”
앞으로는 더 고도화된 작업도 할 계획입니다.
• pnpm workspace + 모노레포 연동
• Lint, Prettier 자동 실행
• PR 제목 체크 등 자동화 확장
'개발 > Git' 카테고리의 다른 글
🔐 GitHub에서 CI를 실제로 강제하려면? (0) | 2025.04.02 |
---|---|
Husky의 동작 과정과 원리 (0) | 2025.03.17 |
Git Bash 와 Git, vi 명령어 모음 (0) | 2023.05.11 |
ignore 처리했는데 파일이 changes에 있을 때. (0) | 2023.03.20 |
개발 블로그
포스팅이 좋았다면 "좋아요❤️" 누르기 !