🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

GitHub Actions Jobs와 Steps 심화 가이드 - 슬라이드 1/7
A

AI Generated

2025. 11. 28. · 15 Views

GitHub Actions Jobs와 Steps 심화 가이드

GitHub Actions에서 여러 Job을 정의하고 의존성을 설정하며, 조건부 실행과 에러 처리까지 마스터하는 심화 가이드입니다. 실무에서 바로 활용할 수 있는 CI/CD 파이프라인 구성 노하우를 담았습니다.


목차

  1. 여러_Job_정의하기
  2. needs로_Job_의존성_설정
  3. Job_간_데이터_전달
  4. if_조건부_실행
  5. continue-on-error_활용
  6. timeout-minutes_설정

1. 여러 Job 정의하기

김개발 씨는 회사의 CI/CD 파이프라인을 처음 담당하게 되었습니다. 기존에는 하나의 Job에 모든 작업을 몰아넣어 빌드 시간이 30분이나 걸렸습니다.

"이걸 좀 더 빠르게 할 수 없을까요?" 팀장님의 질문에 김개발 씨는 고민에 빠졌습니다.

여러 Job 정의하기는 하나의 워크플로우 안에서 독립적인 작업 단위를 분리하는 것입니다. 마치 공장의 조립 라인에서 각 파트별로 담당자를 나누는 것과 같습니다.

이렇게 하면 병렬 실행이 가능해져 전체 빌드 시간을 획기적으로 단축할 수 있습니다.

다음 코드를 살펴봅시다.

name: Multi-Job Pipeline

on: [push]

jobs:
  # 첫 번째 Job: 코드 품질 검사
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run ESLint
        run: npm run lint

  # 두 번째 Job: 유닛 테스트
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Tests
        run: npm test

  # 세 번째 Job: 빌드
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build Project
        run: npm run build

김개발 씨는 입사 6개월 차 DevOps 엔지니어입니다. 오늘 팀장님이 다가와 이런 이야기를 했습니다.

"우리 CI 파이프라인 너무 느려요. 개발자들이 PR 올리고 30분을 기다린대요." 기존 워크플로우 파일을 열어보니 모든 작업이 하나의 Job에 순차적으로 나열되어 있었습니다.

린트 검사, 테스트, 빌드, 배포까지 한 줄로 쭉 이어져 있었던 것입니다. 그렇다면 여러 Job을 정의한다는 것은 정확히 무엇일까요?

쉽게 비유하자면, 이것은 마치 레스토랑 주방과 같습니다. 한 명의 요리사가 전채부터 디저트까지 모두 만들면 시간이 오래 걸립니다.

하지만 전채 담당, 메인 요리 담당, 디저트 담당으로 나누면 동시에 준비할 수 있어 손님에게 음식이 더 빨리 나갑니다. GitHub Actions에서도 마찬가지입니다.

jobs 키 아래에 여러 개의 Job을 정의하면, 기본적으로 이들은 병렬로 실행됩니다. lint, test, build 세 개의 Job이 동시에 시작되는 것입니다.

하나의 Job에 모든 것을 담았을 때는 어떤 문제가 있었을까요? 첫째, 앞선 단계가 끝나야 다음 단계가 시작됩니다.

린트에 5분, 테스트에 10분, 빌드에 15분이 걸린다면 총 30분이 소요됩니다. 둘째, 하나의 단계에서 실패하면 나머지 단계의 결과를 알 수 없습니다.

린트에서 실패하면 테스트 결과도, 빌드 결과도 모릅니다. 여러 Job으로 분리하면 이 문제가 해결됩니다.

lint, test, build가 동시에 실행되니 가장 오래 걸리는 15분만 기다리면 됩니다. 또한 린트가 실패해도 테스트와 빌드 결과는 확인할 수 있습니다.

위의 코드를 살펴보겠습니다. jobs 키 아래에 lint, test, build 세 개의 Job이 정의되어 있습니다.

각 Job은 runs-on으로 실행 환경을 지정하고, steps에서 실제 작업을 수행합니다. 이렇게 분리된 Job들은 서로 독립적인 가상 환경에서 실행됩니다.

실제 현업에서는 어떻게 활용할까요? 대규모 프로젝트에서는 프론트엔드 테스트, 백엔드 테스트, E2E 테스트를 별도의 Job으로 분리합니다.

각각 다른 환경과 의존성이 필요하기 때문입니다. 이렇게 하면 특정 영역의 테스트만 실패해도 다른 영역의 결과는 정상적으로 확인할 수 있습니다.

주의할 점도 있습니다. 모든 Job은 독립적인 환경에서 실행되므로, 한 Job에서 설치한 의존성이나 생성한 파일은 다른 Job에서 사용할 수 없습니다.

이 문제는 뒤에서 배울 아티팩트를 통해 해결할 수 있습니다. 김개발 씨는 기존 워크플로우를 세 개의 Job으로 분리했습니다.

결과는 놀라웠습니다. 30분 걸리던 파이프라인이 15분으로 단축된 것입니다.

팀장님도, 동료들도 모두 만족했습니다.

실전 팁

💡 - Job 이름은 역할을 명확히 나타내도록 lint, test, build, deploy 등으로 짓습니다

  • 완전히 독립적인 작업만 별도의 Job으로 분리하세요

2. needs로 Job 의존성 설정

김개발 씨가 Job을 분리하고 나서 새로운 문제가 발생했습니다. 테스트가 실패했는데도 배포 Job이 실행되어 버그가 있는 코드가 프로덕션에 올라간 것입니다.

"배포는 테스트가 성공한 후에만 해야 하는 거 아닌가요?" 박시니어 씨가 말했습니다.

needs 키워드는 Job 간의 의존 관계를 설정하는 것입니다. 마치 도미노처럼 앞의 Job이 성공적으로 완료되어야만 다음 Job이 시작됩니다.

이를 통해 안전한 파이프라인 흐름을 구성할 수 있습니다.

다음 코드를 살펴봅시다.

name: Dependent Jobs Pipeline

on: [push]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test

  build:
    # test Job이 성공해야 build 시작
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run build

  deploy:
    # test와 build 둘 다 성공해야 deploy 시작
    needs: [test, build]
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying to production"

박시니어 씨의 지적을 들은 김개발 씨는 당혹스러웠습니다. 분명히 Job을 분리했는데, 왜 테스트 실패와 관계없이 배포가 되어버린 걸까요?

이유는 간단했습니다. 기본적으로 여러 Job은 병렬로 실행되기 때문입니다.

테스트가 실패하는 동안에도 배포 Job은 이미 시작되어 버린 것입니다. needs 키워드는 이런 문제를 해결해 줍니다.

비유하자면, needs는 마치 릴레이 경주의 바통과 같습니다. 첫 번째 주자가 바통을 넘겨주어야만 두 번째 주자가 달리기 시작합니다.

중간에 첫 번째 주자가 넘어지면 두 번째 주자는 아예 달리지 않습니다. GitHub Actions에서 needs를 사용하면, 지정된 Job이 성공적으로 완료된 후에만 해당 Job이 시작됩니다.

만약 앞선 Job이 실패하면, 의존하는 Job은 건너뛰기(skipped) 상태가 됩니다. 코드를 자세히 살펴보겠습니다.

build Job에 needs: test가 설정되어 있습니다. 이는 test Job이 성공해야만 build가 시작된다는 의미입니다.

deploy Job은 **needs: [test, build]**로 배열 형태로 지정되어 있습니다. test와 build 둘 다 성공해야만 deploy가 실행됩니다.

이렇게 하면 파이프라인의 흐름이 명확해집니다. test가 실패하면 build와 deploy 모두 건너뛰어집니다.

build가 실패하면 deploy만 건너뛰어집니다. 모두 성공해야만 최종 배포가 이루어지는 안전한 구조가 완성됩니다.

실무에서는 이런 패턴을 자주 사용합니다. 코드 품질 검사, 유닛 테스트, 통합 테스트를 모두 통과한 후에만 스테이징 환경에 배포합니다.

스테이징 배포가 성공하면 E2E 테스트를 돌리고, 그것마저 통과하면 프로덕션에 배포하는 식입니다. 주의할 점이 있습니다.

needs로 연결된 Job들은 순차 실행되므로, 과도하게 사용하면 병렬 실행의 이점을 잃게 됩니다. 정말로 순서가 필요한 경우에만 needs를 사용하세요.

예를 들어 lint와 test는 서로 의존하지 않으니 병렬로 실행하고, 둘 다 성공한 후에 build를 시작하는 것이 효율적입니다. 김개발 씨는 deploy Job에 **needs: [test, build]**를 추가했습니다.

이제 테스트가 실패하면 배포는 자동으로 건너뛰어집니다. 다시는 버그가 있는 코드가 프로덕션에 올라가는 일은 없을 것입니다.

실전 팁

💡 - needs에 배열을 사용하면 여러 Job에 동시에 의존할 수 있습니다

  • 독립적인 검증 작업은 병렬로, 배포 같은 위험한 작업만 needs로 보호하세요

3. Job 간 데이터 전달

김개발 씨는 build Job에서 생성한 빌드 결과물을 deploy Job에서 사용하고 싶었습니다. 하지만 deploy Job에서 빌드 폴더를 찾을 수 없었습니다.

"분명히 build Job에서 만들었는데 왜 없지?" 각 Job이 독립적인 환경에서 실행된다는 사실을 깨닫는 순간이었습니다.

Job 간 데이터 전달은 아티팩트와 outputs를 활용하여 서로 다른 Job 사이에서 파일이나 값을 공유하는 것입니다. 마치 택배 서비스처럼 한 Job에서 포장한 데이터를 다른 Job으로 배송해주는 역할을 합니다.

다음 코드를 살펴봅시다.

name: Data Sharing Pipeline

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      # 다른 Job에서 참조할 수 있는 output 정의
      version: ${{ steps.version.outputs.value }}
    steps:
      - uses: actions/checkout@v4
      - run: npm run build
      - name: Set version output
        id: version
        run: echo "value=1.0.${{ github.run_number }}" >> $GITHUB_OUTPUT
      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: dist
          path: ./dist

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download build artifact
        uses: actions/download-artifact@v4
        with:
          name: dist
      - name: Use version from build
        run: echo "Deploying version ${{ needs.build.outputs.version }}"

김개발 씨는 곤란한 상황에 처했습니다. build Job에서 열심히 빌드한 결과물이 deploy Job에서는 보이지 않는 것입니다.

파일이 증발한 것처럼 사라져 버렸습니다. 박시니어 씨가 설명해 주었습니다.

"각 Job은 완전히 독립된 가상 머신에서 실행돼요. build Job의 가상 머신이 꺼지면 그 안의 파일도 함께 사라지는 거죠." 그렇다면 어떻게 Job 간에 데이터를 전달할 수 있을까요?

GitHub Actions는 두 가지 방법을 제공합니다. 아티팩트outputs입니다.

아티팩트는 마치 택배 서비스와 같습니다. 한 Job에서 파일을 포장해서 GitHub의 저장소에 맡겨두면, 다른 Job에서 그 택배를 수령해서 사용할 수 있습니다.

빌드 결과물, 테스트 리포트, 로그 파일 등 파일 형태의 데이터를 전달할 때 사용합니다. outputs는 마치 메모 전달과 같습니다.

간단한 문자열 값을 다른 Job에 알려주고 싶을 때 사용합니다. 버전 번호, 빌드 상태, 환경 변수 등 작은 값을 전달할 때 유용합니다.

코드를 살펴보겠습니다. build Job의 outputs 섹션에서 version이라는 출력값을 정의합니다.

steps에서 GITHUB_OUTPUT 파일에 값을 기록하면 이 출력값이 설정됩니다. 그리고 upload-artifact 액션으로 dist 폴더를 아티팩트로 업로드합니다.

deploy Job에서는 download-artifact 액션으로 아티팩트를 다운로드합니다. 그리고 needs.build.outputs.version으로 build Job의 출력값을 참조합니다.

이렇게 파일과 값 모두 다른 Job에서 사용할 수 있게 됩니다. 실무에서 이 패턴은 정말 많이 사용됩니다.

빌드 Job에서 생성한 Docker 이미지 태그를 배포 Job에 전달하거나, 테스트 커버리지 리포트를 별도의 리포팅 Job에서 처리하는 식입니다. 대규모 모노레포에서는 변경된 패키지 목록을 첫 번째 Job에서 파악하고, 이 목록을 다른 Job들에 전달하여 필요한 패키지만 빌드하기도 합니다.

주의할 점이 있습니다. 아티팩트는 기본적으로 90일간 보관되며, 용량에 따라 저장 비용이 발생할 수 있습니다.

불필요하게 큰 파일을 아티팩트로 올리지 않도록 주의하세요. 또한 outputs는 문자열만 전달할 수 있으므로, 복잡한 데이터는 JSON 문자열로 변환해서 사용해야 합니다.

김개발 씨는 이제 빌드 결과물을 안전하게 배포 Job에 전달할 수 있게 되었습니다. 버전 정보도 함께 전달되니 어떤 버전이 배포되었는지 명확하게 추적할 수 있습니다.

실전 팁

💡 - 아티팩트는 파일을, outputs는 간단한 값을 전달할 때 사용하세요

  • retention-days 옵션으로 아티팩트 보관 기간을 조절할 수 있습니다

4. if 조건부 실행

어느 날 김개발 씨는 PR에서만 코드 리뷰 봇을 실행하고, main 브랜치 푸시에서는 배포를 실행하고 싶었습니다. 하지만 모든 이벤트에서 모든 Job이 실행되어 불필요한 리소스가 낭비되고 있었습니다.

"상황에 따라 다르게 동작하게 할 수는 없을까요?"

if 조건부 실행은 특정 조건이 참일 때만 Job이나 Step을 실행하도록 제어하는 것입니다. 마치 신호등처럼 조건에 따라 진행할지 멈출지를 결정합니다.

이를 통해 효율적이고 유연한 워크플로우를 구성할 수 있습니다.

다음 코드를 살펴봅시다.

name: Conditional Workflow

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    # main 브랜치 push일 때만 배포 실행
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    steps:
      - run: echo "Deploying to production"

  code-review:
    runs-on: ubuntu-latest
    # PR일 때만 코드 리뷰 봇 실행
    if: github.event_name == 'pull_request'
    steps:
      - run: echo "Running code review bot"

김개발 씨의 워크플로우는 모든 상황에서 동일하게 동작했습니다. PR을 올려도 배포 Job이 실행되고, main에 푸시해도 코드 리뷰 봇이 돌아갔습니다.

물론 대부분 의미 없이 건너뛰어지긴 했지만, 그래도 리소스 낭비인 것은 마찬가지였습니다. if 조건문은 이런 상황을 해결해 줍니다.

비유하자면, if는 마치 공항의 출입국 심사대와 같습니다. 여권과 비자를 확인해서 조건에 맞는 사람만 통과시키듯이, if는 조건을 확인해서 해당하는 Job이나 Step만 실행시킵니다.

GitHub Actions는 다양한 컨텍스트를 제공합니다. github 컨텍스트에서는 이벤트 종류, 브랜치 이름, 커밋 정보 등을 확인할 수 있습니다.

env 컨텍스트에서는 환경 변수를, secrets 컨텍스트에서는 시크릿 존재 여부를 확인할 수 있습니다. 코드를 살펴보겠습니다.

deploy Job에는 **if: github.event_name == 'push' && github.ref == 'refs/heads/main'**이 설정되어 있습니다. 이는 main 브랜치에 직접 push했을 때만 실행된다는 의미입니다.

PR 이벤트에서는 이 Job이 아예 건너뛰어집니다. 반대로 code-review Job은 **if: github.event_name == 'pull_request'**로 설정되어 PR에서만 실행됩니다.

main에 푸시할 때는 코드 리뷰가 필요 없으니 건너뛰는 것입니다. 실무에서는 더 다양한 조건을 사용합니다.

**contains(github.event.head_commit.message, '[skip ci]')**로 특정 커밋 메시지가 포함되면 CI를 건너뛸 수 있습니다. **github.actor != 'dependabot[bot]'**으로 dependabot의 PR에서는 특정 Job을 제외할 수도 있습니다.

Step 레벨에서도 if를 사용할 수 있습니다. **if: failure()**를 사용하면 이전 Step이 실패했을 때만 실행됩니다.

슬랙 알림을 보내거나 에러 로그를 수집하는 용도로 많이 씁니다. **if: always()**는 이전 결과와 관계없이 항상 실행됩니다.

정리 작업이나 리소스 해제에 유용합니다. 주의할 점이 있습니다.

if 조건에서 문자열 비교를 할 때는 따옴표 사용에 주의하세요. 표현식 안에서 문자열은 작은따옴표로 감싸야 합니다.

또한 복잡한 조건은 가독성이 떨어지므로, 환경 변수로 분리하거나 주석을 달아두는 것이 좋습니다. 김개발 씨는 이제 상황에 맞는 Job만 실행되도록 워크플로우를 최적화했습니다.

PR에서는 테스트와 코드 리뷰만, main 푸시에서는 테스트와 배포만 실행됩니다. 불필요한 리소스 낭비가 사라졌습니다.

실전 팁

💡 - failure(), success(), always(), cancelled() 함수로 이전 결과에 따른 조건을 설정하세요

  • 복잡한 조건은 환경 변수로 분리하면 가독성이 좋아집니다

5. continue-on-error 활용

김개발 씨는 E2E 테스트 Job이 가끔 실패하는 문제로 골치를 앓고 있었습니다. 네트워크 타이밍 이슈로 간헐적으로 실패하는데, 그때마다 전체 파이프라인이 중단되어 배포가 막히는 것입니다.

"이 테스트는 참고용인데, 실패해도 일단 배포는 되게 할 수 없을까요?"

continue-on-error는 Job이나 Step이 실패해도 워크플로우를 계속 진행하도록 하는 설정입니다. 마치 달리기 시합에서 넘어져도 실격이 아니라 계속 달릴 수 있게 해주는 것과 같습니다.

필수가 아닌 작업이 전체 파이프라인을 막지 않도록 할 때 유용합니다.

다음 코드를 살펴봅시다.

name: Resilient Pipeline

jobs:
  critical-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run unit tests
        run: npm test

  optional-test:
    runs-on: ubuntu-latest
    # 이 Job이 실패해도 워크플로우는 성공으로 처리
    continue-on-error: true
    steps:
      - uses: actions/checkout@v4
      - name: Run flaky E2E tests
        run: npm run test:e2e

  deploy:
    needs: [critical-test, optional-test]
    runs-on: ubuntu-latest
    # optional-test가 실패해도 배포 진행
    if: always() && needs.critical-test.result == 'success'
    steps:
      - run: echo "Deploying application"

E2E 테스트는 실제 브라우저를 띄워서 사용자 시나리오를 검증하는 중요한 테스트입니다. 하지만 네트워크 상태, 외부 서비스 응답 시간 등에 영향을 받아 간헐적으로 실패하는 경우가 많습니다.

이런 테스트를 flaky test라고 부릅니다. 김개발 씨의 고민은 이것이었습니다.

E2E 테스트는 참고용으로 보고 싶지만, 실패할 때마다 전체 배포가 막히는 것은 원치 않았습니다. 유닛 테스트처럼 반드시 통과해야 하는 것은 아니니까요.

continue-on-error는 이런 상황에 딱 맞는 해결책입니다. 비유하자면, 이것은 마치 학교 시험의 가산점 문제와 같습니다.

맞추면 좋지만, 틀려도 불합격은 아닙니다. 본 시험 점수만 합격선을 넘으면 됩니다.

continue-on-error를 Job 레벨에 설정하면, 해당 Job이 실패해도 워크플로우 전체는 성공으로 표시됩니다. 다만 해당 Job 자체는 실패로 기록되어 어떤 Job이 문제가 있었는지는 확인할 수 있습니다.

코드를 살펴보겠습니다. optional-test Job에 continue-on-error: true가 설정되어 있습니다.

이 Job이 실패해도 워크플로우는 멈추지 않습니다. deploy Job에서는 if: always() && needs.critical-test.result == 'success' 조건을 사용합니다.

always()로 이전 Job의 성공/실패와 관계없이 평가를 시작하고, critical-test만 성공이면 배포를 진행합니다. Step 레벨에서도 continue-on-error를 사용할 수 있습니다.

특정 Step이 실패해도 다음 Step으로 넘어가고 싶을 때 유용합니다. 예를 들어 캐시 복원에 실패해도 빌드 자체는 계속 진행하고 싶을 때 사용합니다.

실무에서는 다음과 같은 경우에 활용합니다. 외부 서비스에 의존하는 통합 테스트, 선택적인 성능 벤치마크, 슬랙이나 이메일 알림 발송 등입니다.

이런 작업들은 실패해도 핵심 기능에는 영향이 없기 때문입니다. 하지만 주의해야 합니다.

continue-on-error를 남용하면 진짜 문제를 놓칠 수 있습니다. 실패가 중요하지 않다고 생각했던 Job에서 심각한 버그가 숨어있을 수도 있습니다.

정기적으로 실패 현황을 모니터링하고, flaky test는 근본적으로 개선하는 것이 좋습니다. 김개발 씨는 E2E 테스트에 continue-on-error를 적용했습니다.

이제 E2E 테스트가 가끔 실패해도 배포는 정상적으로 진행됩니다. 물론 실패 알림은 받아서 나중에 원인을 분석하기로 했습니다.

실전 팁

💡 - 진짜 중요한 테스트에는 continue-on-error를 사용하지 마세요

  • 실패 현황을 모니터링하고 flaky test는 근본 원인을 해결하세요

6. timeout-minutes 설정

어느 월요일 아침, 김개발 씨는 황당한 상황을 마주했습니다. 금요일 저녁에 올린 PR의 CI가 아직도 돌고 있었던 것입니다.

테스트 중 무한 루프에 빠져서 주말 내내 러너가 점유된 채로 있었습니다. 팀의 월간 GitHub Actions 사용량이 순식간에 바닥났습니다.

timeout-minutes는 Job이나 Step의 최대 실행 시간을 제한하는 설정입니다. 마치 요리 타이머처럼 정해진 시간이 지나면 자동으로 중단됩니다.

무한 루프나 행(hang)에 빠진 작업으로 인한 리소스 낭비를 방지할 수 있습니다.

다음 코드를 살펴봅시다.

name: Timeout Protected Pipeline

jobs:
  build:
    runs-on: ubuntu-latest
    # Job 전체 타임아웃: 30분
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      - name: Install dependencies
        # Step별 타임아웃: 10분
        timeout-minutes: 10
        run: npm ci
      - name: Run build
        timeout-minutes: 15
        run: npm run build

  test:
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@v4
      - name: Run tests with timeout
        timeout-minutes: 15
        run: npm test
      - name: Upload coverage
        timeout-minutes: 5
        run: npm run coverage:upload

주말 동안 CI가 멈추지 않고 돌아간 사건은 팀에게 큰 교훈을 주었습니다. GitHub Actions는 기본적으로 Job당 6시간의 타임아웃이 설정되어 있습니다.

하지만 대부분의 빌드와 테스트는 30분 이내에 끝납니다. 6시간이나 기다릴 이유가 없는 것입니다.

timeout-minutes는 이런 문제를 방지하는 안전장치입니다. 비유하자면, 이것은 마치 압력밥솥의 타이머와 같습니다.

밥이 다 됐는지 계속 확인하지 않아도, 정해진 시간이 지나면 자동으로 꺼집니다. 만약 무언가 잘못되어 압력이 계속 올라가더라도 타이머 덕분에 큰 사고를 막을 수 있습니다.

코드를 살펴보겠습니다. build Job에는 timeout-minutes: 30이 설정되어 있습니다.

이 Job의 모든 Step을 합쳐서 30분을 넘기면 자동으로 취소됩니다. 개별 Step에도 각각 타임아웃을 설정할 수 있습니다.

npm ci에 10분, npm run build에 15분을 할당했습니다. Step 타임아웃은 Job 타임아웃과 독립적으로 동작합니다.

npm ci가 10분을 초과하면 즉시 해당 Step이 실패하고, Job도 실패합니다. Job 전체가 30분을 넘지 않았더라도 마찬가지입니다.

실무에서는 각 작업의 예상 소요 시간에 여유를 두고 타임아웃을 설정합니다. 보통 2-3배 정도의 여유를 둡니다.

평소 빌드가 5분 걸린다면 15분으로 설정하는 식입니다. 너무 빡빡하게 설정하면 네트워크 지연 같은 일시적 문제로 실패할 수 있습니다.

타임아웃을 설정하면 또 다른 이점이 있습니다. 작업 시간이 갑자기 늘어나면 뭔가 문제가 있다는 신호입니다.

평소 5분이던 빌드가 갑자기 14분이 걸린다면, 타임아웃에 걸리기 전이라도 조사해볼 필요가 있습니다. 이런 모니터링 관점에서도 타임아웃 설정은 유용합니다.

주의할 점이 있습니다. 타임아웃으로 중단된 Job은 실패로 처리됩니다.

데이터베이스 마이그레이션처럼 중간에 끊기면 안 되는 작업은 충분한 타임아웃을 설정해야 합니다. 또한 타임아웃이 발생하면 정리 작업이 실행되지 않을 수 있으므로, 중요한 리소스 정리는 별도로 처리해야 합니다.

김개발 씨는 모든 Job에 적절한 타임아웃을 설정했습니다. 이제 무한 루프에 빠지더라도 최대 30분 후에는 자동으로 종료됩니다.

더 이상 주말 동안 러너가 점유되는 일은 없을 것입니다.

실전 팁

💡 - 평소 소요 시간의 2-3배로 타임아웃을 설정하세요

  • 외부 서비스 호출이 있는 Step은 네트워크 지연을 고려해 여유 있게 설정하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#GitHub Actions#Jobs#Steps#CI/CD#Workflow#GitHub Actions,CI/CD,DevOps

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.

함께 보면 좋은 카드 뉴스