서비스 운영 ·
GitHub Actions로 커밋마다 테스트가 도는 흐름 이해하기
먼저 답부터
GitHub Actions의 CI는 push나 pull request 같은 사건이 생기면 별도 실행 컴퓨터인 러너에서 설치와 테스트 단계를 자동 수행하는 방식입니다. 워크플로 파일의 실행 조건, 권한, 비밀값 사용, 통과한 정확한 커밋을 확인해야 하며 초록 표시가 실제 배포나 모든 기능의 정상 동작까지 보장하지는 않습니다.
내 컴퓨터에서 테스트가 통과해도 다른 운영체제나 깨끗한 설치 환경에서는 실패할 수 있습니다. 팀원이 테스트를 빼먹을 수도 있습니다. CI는 continuous integration의 줄임말로, 변경을 함께 모을 때 정해진 검사를 자동으로 반복하는 방식입니다.
GitHub Actions는 GitHub 저장소에서 이런 자동 작업을 만드는 기능입니다. 택배 물류센터에서 상자가 들어올 때마다 무게, 주소, 파손 여부를 같은 순서로 검사하는 것처럼 커밋이나 pull request마다 설치와 테스트를 다시 실행할 수 있습니다.
워크플로는 자동 검사 전체의 작업 지시서다
워크플로는 언제 어떤 일을 실행할지 적은 YAML 파일입니다. YAML은 들여쓰기로 구조를 나타내는 설정 형식입니다. GitHub 공식 문서에 따르면 워크플로 파일은 저장소의 .github/workflows 폴더에 둡니다.
한 저장소에는 테스트, 배포, 이슈 분류처럼 목적이 다른 워크플로가 여러 개 있을 수 있습니다. 파일이 존재한다고 자동으로 안전한 것은 아닙니다. 실행 조건과 권한, 외부 액션, 비밀값 사용을 함께 읽어야 합니다.
event와 job과 step을 위에서 아래로 읽는다
event는 실행을 시작하는 사건입니다. push, pull_request, 수동 실행, 정해진 시간이 예가 됩니다. job은 러너라는 별도 실행 컴퓨터에서 수행할 작업 묶음이고, step은 job 안의 한 단계입니다. 공식 문서도 사건이 워크플로를 시작하고 job이 runner에서 여러 step을 실행하는 구조로 설명합니다.
name: test
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
이 예시는 pull request가 생기면 Ubuntu 러너에서 코드를 받은 뒤 npm test를 실행합니다. 실제 프로젝트에서는 Node 설치와 의존성 설치 단계가 더 필요합니다. 예시는 구조를 읽기 위한 것이며 그대로 붙여 넣어 완성된 워크플로라고 생각하면 안 됩니다.
러너는 내 컴퓨터와 다른 깨끗한 작업대다
러너는 워크플로를 실행하는 컴퓨터 환경입니다. GitHub가 제공하는 러너나 직접 관리하는 self-hosted runner를 쓸 수 있습니다. self-hosted는 내 서버에서 실행된다는 뜻이라 네트워크와 비밀 자료 접근 범위를 더 엄격하게 관리해야 합니다.
러너는 매번 새 환경일 수 있어 로컬에만 설치된 프로그램이나 저장되지 않은 파일을 알지 못합니다. package-lock.json 같은 잠금 파일을 커밋하고 설치 명령을 명시해야 재현하기 쉽습니다. 운영체제와 도구 버전이 다르면 결과도 달라질 수 있으므로 runs-on과 런타임 버전을 확인합니다.
초록 체크는 적힌 검사만 통과했다는 뜻이다
워크플로가 성공하면 그 파일에 적힌 단계가 해당 커밋에서 종료 코드 0으로 끝났다는 뜻입니다. 실행하지 않은 모바일 화면, 외부 결제, 실제 도메인, 데이터 마이그레이션까지 정상이라는 뜻은 아닙니다. 테스트 범위가 좁으면 초록 표시도 좁은 보장만 제공합니다.
- 어떤 커밋 SHA를 검사했는지 봅니다.
- 어떤 job과 step이 실제 실행됐는지 확인합니다.
- 건너뛴 단계가 있는지 확인합니다.
- 테스트 로그에서 경고와 재시도를 구분합니다.
- 배포 job이 별도라면 상태를 따로 기록합니다.
실패했을 때는 가장 먼저 실패한 step과 오류 첫 줄을 봅니다. 뒤에 이어진 연쇄 오류보다 처음 깨진 설치, 타입, 테스트 단계가 원인에 가까운 경우가 많습니다.
secret은 워크플로에서 쓰는 민감한 값을 보관한다
secret은 API 키나 접근 토큰처럼 공개하면 안 되는 값을 GitHub 설정에 저장해 워크플로에 전달하는 기능입니다. GitHub 공식 문서는 secret을 워크플로에 명시적으로 포함해야 액션이 읽을 수 있다고 설명합니다. 필요한 저장소와 환경에만 최소 권한으로 나눠야 합니다.
로그에서 자동으로 가려지는 기능이 있어도 모든 변형이 항상 가려진다고 믿으면 안 됩니다. secret 값을 출력하거나 파일 전체를 업로드하지 않습니다. pull request가 외부 포크에서 왔을 때 어떤 비밀값이 전달되는지도 확인합니다. 운영 결제키와 테스트키는 다른 환경으로 분리합니다.
외부 action도 실행하는 코드로 검토한다
uses 줄에 적힌 action은 다른 코드 묶음을 가져와 실행할 수 있습니다. 유명한 이름만 보고 무조건 신뢰하지 않습니다. 공식 제작자, 문서, 필요한 권한, 버전 고정 방식을 확인합니다. 광범위한 write 권한보다 필요한 읽기 권한부터 시작합니다.
워크플로의 permissions 설정과 GITHUB_TOKEN 범위를 읽습니다. 배포나 릴리스 생성처럼 외부 상태를 바꾸는 작업은 테스트와 job을 분리하고 보호 환경이나 승인 단계를 둡니다. 자동화가 실패를 반복해 비용을 만들 수 있으므로 동시 실행과 중단 기준도 설정합니다.
CI와 배포는 다른 결과로 기록한다
CI 통과는 코드를 검사한 상태입니다. CD는 continuous delivery 또는 deployment의 줄임말로, 검증된 결과물을 배포 준비하거나 실제 환경에 내보내는 과정입니다. 하나의 워크플로에 함께 있어도 test와 deploy job은 서로 다른 증거를 남깁니다.
배포가 성공해도 실제 URL이 새 버전을 제공하는지, 캐시가 남았는지, 환경변수가 맞는지는 공개 화면에서 다시 봅니다. 자동화 로그, 배포 상태, 실제 브라우저 확인을 각각 기록하면 문제가 난 위치를 찾기 쉽습니다.
오늘 바로 해볼 작은 실습
저장소의 Actions 화면과 워크플로 파일을 읽기만 합니다.
- .github/workflows 폴더에서 YAML 파일 하나를 찾습니다.
- on 항목에서 어떤 사건이 실행을 시작하는지 적습니다.
- jobs 아래의 job 이름과 runs-on 환경을 적습니다.
- steps에서 설치, 검사, 배포를 서로 다른 색으로 표시합니다.
- secret 참조와 permissions 항목이 있는지 보되 값은 열거나 복사하지 않습니다.
- 최근 실행 한 건의 커밋과 실패 또는 성공 step을 확인합니다.
모르는 외부 action을 추가하거나 secret, 결제키, 배포 토큰을 로그에 출력하지 마세요. 워크플로 수정은 저장소 비용과 운영 배포를 일으킬 수 있으므로 테스트 브랜치와 최소 권한에서 검토한 뒤 반영합니다.