소개
대규모 팀과 함께 책을 쓴다고 생각해 보세요. 누군가 새 장을 제출할 때마다 맞춤법 오류와 줄거리의 빈틈을 확인해야 합니다. 이 작업을 매번 수동으로 하는 것은 매우 힘듭니다.
소프트웨어 개발에서는 지속적 통합(CI) 으로 이 문제를 해결합니다. CI 는 일반적으로 의존성을 설치하고, 테스트를 실행하고, 업데이트가 있을 때마다 프로젝트를 검증하는 방식으로 변경 사항을 초기에 자동으로 확인합니다.
핵심은 빠른 피드백입니다. 변경 후 며칠이 지나서 문제를 발견하는 것보다 변경 직후 문제를 발견하는 편이 훨씬 쉽게 수정할 수 있습니다.
CI 를 팀이 가장 먼저 구축하는 자동화 계층으로 사용하는 이유도 바로 이 속도입니다. 모든 push 를 자동 품질 검사로 바꾸어 main 브랜치를 보호합니다.
이 실습에서는 간단한 Node.js 애플리케이션을 위한 안전망을 구축합니다. 다음 작업을 수행합니다.
- 기본적인 수학 연산을 수행하는 작은 애플리케이션을 만듭니다.
- 수학 연산이 올바른지 확인하는 테스트를 작성합니다.
- 코드를 push 할 때마다 이 테스트가 자동으로 실행되도록 GitHub Actions 를 구성합니다.
- 의도적으로 코드를 망가뜨려 안전망이 오류를 어떻게 감지하는지 확인합니다.
사전 요구 사항
이 실습은 이전 실습을 기반으로 합니다. 앞에서 만든 github-actions-basics 저장소를 계속 사용합니다.
Node.js 프로젝트 준비
먼저 테스트할 코드가 필요합니다. 작은 Node.js 애플리케이션을 만듭니다. 프로그래밍 경험이 없어도 걱정하지 마세요. 필요한 코드를 모두 제공합니다.
프로젝트 디렉터리로 이동합니다. 새 실습 환경이므로 저장소를 다시 다운로드해야 합니다.
cd ~/project
git clone https://github.com/your-username/github-actions-basics.git
cd github-actions-basics
참고: your-username을 실제 GitHub 사용자 이름으로 바꾸세요.
실제 프로젝트를 구성하는 것처럼 세 개의 파일을 만듭니다. 명령줄에서 콘텐츠가 포함된 파일을 빠르게 만들 수 있는 cat 명령을 사용합니다.
1. "레시피"(package.json)
이 파일은 프로젝트의 종류와 필요한 도구를 컴퓨터에 알려 줍니다. 여기서는 프로젝트가 jest라는 테스트 도구에 의존한다고 지정합니다.
cat > package.json << EOF
{
"name": "ci-demo",
"version": "1.0.0",
"scripts": {
"test": "jest"
},
"dependencies": {
"jest": "^29.7.0"
}
}
EOF
2. "음식"(index.js)
실제 애플리케이션 코드입니다. 두 숫자를 더하는 간단한 함수입니다.
cat > index.js << EOF
function sum(a, b) {
return a + b;
}
module.exports = sum;
EOF
3. "시식 테스트"(index.test.js)
자동화된 테스트입니다. 1 과 2 를 더하면 결과가 반드시 3 인지 확인합니다.
cat > index.test.js << EOF
const sum = require('./index');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
EOF
파일을 만들었으므로 이제 GitHub 에 저장해야 합니다. 표준 Git 명령을 실행해 작업 내용을 업로드합니다.
git add .
git commit -m "Add Node.js project files"
git push
GitHub 에 다시 로그인하라는 메시지가 표시될 수 있습니다. 이전과 동일하게 사용자 이름과 Personal Access Token(PAT) 을 사용합니다.
CI 워크플로 만들기
이제 로봇 도우미가 이 코드를 테스트하는 방법을 알려 줘야 합니다. 표준 .github/workflows 폴더에 ci.yml이라는 새 워크플로 파일을 만듭니다.
touch .github/workflows/ci.yml
nano 편집기에서 이 파일을 엽니다.
nano .github/workflows/ci.yml
다음 구성을 추가합니다. 아래에서 새로 등장한 부분을 설명합니다.
name: Node.js CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16
여기서는 강력한 새 키워드인 uses를 사용합니다.
이는 GitHub Actions 의 중요한 패턴입니다. 모든 셸 단계를 직접 작성하는 대신, 워크플로에서는 체크아웃, 언어 설정, 아티팩트 업로드처럼 자주 사용하는 작업을 패키징한 재사용 가능한 액션을 조합하는 경우가 많습니다.
uses를 로봇의 두뇌에 기술을 다운로드하는 기능이라고 생각하면 됩니다. 복잡한 스크립트를 처음부터 작성하지 않고 다른 사람들이 만든 액션을 사용할 수 있습니다.
actions/checkout@v4: 이 표준 액션은 로봇에게 "내 코드를 다운로드해"라고 지시합니다. 이 단계가 없으면 로봇의 작업 공간은 비어 있습니다.actions/setup-node@v3: 실행 환경에 Node.js 를 설치합니다. 일관된 환경을 유지하기 위해 특정 버전 (16) 도 전달합니다.
편집기를 저장하고 종료합니다 (Ctrl+X, Y, Enter).
설치 및 테스트 단계 추가
코드 (체크아웃) 와 도구 (Node.js) 를 준비했습니다. 이제 실제로 테스트를 실행해야 합니다.
Node.js 환경에서는 이를 위해 다음 두 가지 표준 명령을 사용합니다.
npm install:package.json에 나열된 모든 의존성 (예:jest테스트 도구) 을 다운로드합니다.npm test:package.json에 정의된 테스트 스크립트를 실행합니다.
이 두 단계는 CI 의 핵심 흐름을 구현합니다. 정상적인 변경으로 처리하기 전에 실행 환경을 준비하고, 의존성을 설치하고, 깨끗한 실행 환경에서 코드를 검증합니다.
이 단계들을 워크플로에 추가합니다. .github/workflows/ci.yml을 다시 엽니다.
nano .github/workflows/ci.yml
파일 끝에 다음 두 단계를 추가합니다. 앞의 단계와 들여쓰기가 맞는지 확인합니다.
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
완성된 파일은 다음과 같아야 합니다.
name: Node.js CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
편집기를 저장하고 종료합니다.
이제 이 파일을 GitHub 에 push 해 안전망을 활성화합니다.
git add .
git commit -m "Add CI pipeline"
git push
GitHub 에서 저장소로 이동해 Actions 탭을 클릭합니다. "Node.js CI"라는 새 워크플로가 실행 중인 것을 볼 수 있습니다. 실행이 끝나면 초록색 체크 표시가 나타납니다. 이는 코드가 정상적으로 동작한다는 뜻입니다.

빌드 망가뜨리기
안전망은 넘어졌을 때 잡아 줄 수 있어야 유용합니다. CI 시스템이 실제로 작동하는 모습을 확인하기 위해 의도적으로 코드를 "망가뜨립니다".
테스트 파일을 수정해 사실과 다른 결과를 주장하도록 합니다. 1 + 2 의 결과가 4 라고 지정합니다.
nano로 index.test.js를 엽니다.
nano index.test.js
테스트의 기대값을 3에서 4로 변경합니다.
const sum = require("./index");
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(4); // CHANGED 3 to 4
});
저장하고 종료합니다. 이제 이 "버그"를 커밋하고 push 합니다.
git add .
git commit -m "Intentionally break the test"
git push
즉시 GitHub 의 Actions 탭으로 돌아갑니다. 새 워크플로가 실행되는 모습을 확인합니다.
잠시 후 실행이 실패해야 합니다. 커밋 옆에 빨간색 X 아이콘이 표시됩니다. 이는 CI 시스템이 "중지하세요! 문제가 있습니다!"라고 알리는 것입니다.
실패한 실행을 클릭한 다음 build 작업을 클릭합니다. Run tests 단계를 펼쳐 오류 로그를 확인합니다.
Error: expect(received).toBe(expected) // Object.is equality
Expected: 4
Received: 3
이 간단한 빨간색 X 는 버그가 발생한 순간 이를 감지해 개발자가 며칠 또는 몇 주 후에 문제를 발견하는 대신 수많은 시간을 절약하도록 도와줍니다.

요약
이 실습에서는 실무 수준의 지속적 통합 파이프라인을 만들었습니다.
다음 내용을 배웠습니다.
package.json으로 프로젝트 "레시피"를 정의하는 방법uses키워드로actions/checkout및actions/setup-node같은 강력한 도구를 사용하는 방법- 모든 코드 변경 사항을 로봇이 검증하도록 테스트를 자동화하는 방법
- 코드의 안전망으로서 "빨간색 X"가 갖는 중요성
다음 실습에서는 정상적으로 동작하는 코드를 패키징해 세상에 공개하는 방법을 배웁니다!



