Skip to main content

워크플로 속도를 높이기 위한 종속성 캐싱

워크플로를 더 빠르고 효율적으로 만들기 위해 종속성 및 일반적으로 재사용되는 기타 파일에 대한 캐시를 만들고 사용할 수 있습니다.

캐싱 워크플로 종속성 정보

워크플로 실행은 한 실행에서 다른 실행으로 동일한 출력 또는 다운로드된 종속성을 다시 사용하는 경우가 많습니다. 예를 들어 Maven, Gradle, npm 및 Yarn과 같은 패키지 및 종속성 관리 도구는 다운로드한 종속성의 로컬 캐시를 유지합니다.

GitHub에서 호스트되는 실행기에서의 작업은 깨끗한 실행기 이미지에서 시작되며 매번 종속성을 다운로드해야 하므로 네트워크 사용률이 증가하고 런타임이 길어지고 비용이 증가합니다. 종속성과 같은 파일을 다시 만드는 데 걸리는 시간을 단축하기 위해 GitHub은 워크플로에서 자주 사용하는 종속성을 캐시할 수 있습니다.

작업에 대한 종속성을 캐시하려면 GitHub의 cache 작업을 사용할 수 있습니다. 작업은 고유 키로 식별된 캐시를 만들고 복원합니다. 또는 아래에 나열된 패키지 관리자를 캐싱하는 경우 해당 설치-* 작업을 사용하려면 최소한의 구성이 필요하며 종속성 캐시를 만들고 복원합니다.

패키지 관리자캐싱에 대한 setup-* 작업
npm, Yarn, pnpmsetup-node
pip, pipenv, Poetrysetup-python
Gradle, Mavensetup-java
RubyGemssetup-ruby
Go go.sumsetup-go
.NET NuGetsetup-dotnet

Warning

GitHub Actions에서 캐싱을 사용할 때 다음 사항에 유의하세요.

  • 캐시에 중요한 정보를 저장하지 않는 것이 좋습니다. 예를 들어 중요한 정보에는 캐시 경로의 파일에 저장된 액세스 토큰 또는 로그인 자격 증명이 포함될 수 있습니다. 또한 CLI(명령줄 인터페이스) 프로그램과 마찬가지로 docker login 구성 파일에 액세스 자격 증명을 저장할 수 있습니다. 읽기 액세스 권한이 있는 사용자는 리포지토리에서 끌어오기 요청을 만들고 캐시의 콘텐츠에 액세스할 수 있습니다. 리포지토리의 포크는 베이스 분기에 끌어오기 요청을 만들고 기본 분기의 캐시에 액세스할 수도 있습니다.
  • 자체 호스팅 실행기를 사용하는 경우 워크플로 실행의 캐시는 GitHub 소유 클라우드 스토리지에 저장됩니다. 고객 소유 스토리지 솔루션은 GitHub Enterprise Server에서만 사용할 수 있습니다.

아티팩트 및 종속성 캐싱 비교

아티팩트 및 캐싱은 GitHub에 파일을 저장할 수 있는 기능을 제공하지만 각 기능은 서로 다른 사용 사례를 제공하므로 서로 바꿔서 사용할 수 없습니다.

  • 패키지 관리 시스템의 빌드 종속성 등 작업 또는 워크플로 실행 간에 자주 변경되지 않는 파일을 다시 사용하려는 경우 캐싱을 사용합니다.
  • 빌드된 이진 파일 또는 빌드 로그와 같이 워크플로 실행이 종료된 후 볼 작업에서 생성된 파일을 저장하려는 경우 아티팩트를 사용합니다.

워크플로 실행 아티팩트에 대한 자세한 내용은 “워크플로에서 데이터 저장 및 공유”을(를) 참조하세요.

캐시 액세스 제한 사항

액세스 제한은 서로 다른 분기 또는 태그 간에 논리적 경계를 만들어 캐시 격리 및 보안을 제공합니다. 워크플로 실행은 현재 분기 또는 기본 분기(일반적으로 main)에서 만든 캐시를 복원할 수 있습니다. 끌어오기 요청에 대해 워크플로 실행이 트리거되면 포크된 리포지토리의 기본 분기를 포함하여 베이스 분기에서 생성된 캐시를 복원할 수도 있습니다. 예를 들어 분기 feature-b에 베이스 분기 feature-a이(가) 있는 경우 끌어오기 요청에서 트리거된 워크플로 실행은 기본 main 분기, 베이스 feature-a 분기 및 현재 feature-b 분기에서 생성된 캐시에 액세스할 수 있습니다.

워크플로 실행은 자식 분기 또는 형제 분기에 대해 생성된 캐시를 복원할 수 없습니다. 예를 들어 자식 feature-b 분기에 대해 생성된 캐시는 부모 main 분기에서 트리거된 워크플로 실행에 액세스할 수 없습니다. 마찬가지로 베이스 main이(가) 있는 feature-a 분기에 대해 생성된 캐시는 베이스 main을(를) 사용하여 해당 형제 feature-c 분기에 액세스할 수 없습니다. 워크플로 실행은 다른 태그 이름에 대해 생성된 캐시를 복원할 수도 없습니다. 예를 들어 베이스 main이(가) 있는 태그 release-a에 대해 생성된 캐시는 베이스 main이(가) 있는 태그 release-b에 대해 트리거된 워크플로 실행에 액세스할 수 없습니다.

끌어오기 요청에서 트리거된 워크플로 실행에 의해 캐시가 생성되면 병합 참조(refs/pull/.../merge)에 대한 캐시가 생성됩니다. 이 때문에 캐시의 범위가 제한되며 끌어오기 요청을 다시 실행해야만 복원할 수 있습니다. 베이스 분기 또는 해당 베이스 분기를 대상으로 하는 다른 끌어오기 요청으로는 복원할 수 없습니다.

리포지토리에서 여러 워크플로 실행을 통해 캐시를 공유할 수 있습니다. 워크플로 내의 분기에 대해 만든 캐시는 동일한 리포지토리 및 분기에 대한 다른 워크플로 실행에서 액세스하고 복원할 수 있습니다.

cache 작업 사용

cache 작업은 사용자가 제공한 key를 기반으로 캐시를 복원하려고 시도합니다. 작업이 키와 정확히 일치하는 캐시를 찾으면 캐시된 파일을 사용자가 구성한 path(으)로 복원합니다. key이(가) 기존 캐시와 일치하지 않는 경우 필요에 따라 사용할 restore-keys 목록을 입력할 수 있습니다. restore-keys이(가) 캐시 키를 부분적으로 일치시킬 수 있으므로 restore-keys 목록 다른 분기에서 캐시를 복원할 때 유용합니다. restore-keys 일치에 대한 자세한 내용은 “캐시 키 일치”를 참조하세요.

제공된 key과(와) 정확히 일치하는 항목이 있는 경우 캐시 적중으로 간주됩니다. 제공된 key과(와) 정확히 일치하는 캐시가 없으면 캐시 누락으로 간주됩니다. 캐시 누락 시 작업이 성공적으로 완료되면 작업이 자동으로 새 캐시를 생성합니다. 새 캐시는 사용자가 제공한 key를 사용하고 path에서 지정한 파일을 포함합니다. 이 처리 방법에 대한 자세한 내용은 "캐시 적수 및 누락"을 참조하세요.

기존 캐시의 콘텐츠는 변경할 수 없습니다. 대신 새 키를 사용하여 새 캐시를 만들 수 있습니다.

cache 작업에 대한 입력 매개 변수입니다.

  • key: 필수 사항 캐시를 저장할 때 생성되는 키와 캐시를 검색하는 데 사용되는 키입니다. 변수, 컨텍스트 값, 정적 문자열 및 함수의 조합일 수 있습니다. 키의 최대 길이는 512자이며 최대 길이보다 키가 길면 작업이 실패합니다.

  • path: 필수 사항 캐시하거나 복원할 실행기의 경로입니다.

    • 단일 경로를 지정하거나 별도의 줄에 여러 경로를 추가할 수 있습니다. 예시:

      - name: Cache Gradle packages
        uses: actions/cache@v3
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
      
    • 디렉터리 또는 단일 파일을 지정할 수 있으며 GLOB 패턴이 지원됩니다.

    • 절대 경로 또는 작업 영역 디렉터리를 기준으로 상대적인 경로를 지정할 수 있습니다.

  • restore-keys: 선택적 대체 복원 키가 포함된 문자열로, 각 복원 키가 새 줄에 배치됩니다. key에 대해 캐시 적중이 발생하지 않는 경우 이러한 복원 키는 캐시를 찾고 복원하기 위해 제공된 순서대로 순차적으로 사용됩니다. 예시:

    restore-keys: |
      npm-feature-${{ hashFiles('package-lock.json') }}
      npm-feature-
      npm-
    
  • enableCrossOsArchive: 선택적 사용하도록 설정된 경우 Windows 실행기가 캐시가 생성된 운영 체제와 관계없이 캐시를 저장하거나 복원할 수 있도록 하는 부울 값입니다. 이 매개 변수가 설정되지 않으면 기본적으로 false(으)로 설정됩니다. 자세한 내용은 작업 캐시 설명서의 OS 간 캐시를 참조하세요.

cache 작업에 대한 출력 매개 변수입니다.

  • cache-hit: 키에 대한 정확한 일치 항목을 나타내는 부울 값입니다.

캐시 적중 및 누락

key이(가) 기존 캐시와 정확하게 일치하면 _캐시 적중_이라고 하며 작업은 캐시된 파일을 path 디렉터리로 복원합니다.

key가 기존 캐시와 일치하지 않는 경우 _캐시 누락_이라고 하며 작업이 성공적으로 완료되면 자동으로 새 캐시를 만듭니다.

캐시 누락이 발생하면 작업은 지정된 restore-keys에서 일치 항목을 검색합니다.

  1. restore-keys를 입력하면 cache 작업은 restore-keys 목록과 일치하는 캐시를 순차적으로 검색합니다.
    • 정확히 일치하는 경우 작업은 캐시의 파일을 path 디렉터리로 복원합니다.
    • 정확히 일치하는 항목이 없으면 작업은 복원 키의 부분 일치 항목을 검색합니다. 작업이 부분 일치 항목을 찾으면 가장 최근 캐시가 path 디렉터리로 복원됩니다.
  2. cache 작업이 완료되면 작업의 다음 단계가 실행됩니다.
  3. 작업이 성공적으로 완료되면 작업은 path 디렉터리의 콘텐츠가 포함된 새 캐시를 자동으로 만듭니다.

캐시 일치 프로세스에 대한 자세한 설명은 “캐시 키 일치”를 참조하세요.

cache 작업을 사용하는 예시

이 예시에서는 package-lock.json 파일의 패키지가 변경되거나 실행기 운영 체제가 변경되는 경우 새 캐시를 만듭니다. 캐시 키는 컨텍스트 및 식을 사용하여 실행기의 운영 체제와 package-lock.json 파일의 SHA-256 해시를 포함하는 키를 생성합니다.

YAML
name: Caching with npm
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Cache node modules
        id: cache-npm
        uses: actions/cache@v3
        env:
          cache-name: cache-node-modules
        with:
          # npm cache files are stored in `~/.npm` on Linux/macOS
          path: ~/.npm
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-build-${{ env.cache-name }}-
            ${{ runner.os }}-build-
            ${{ runner.os }}-

      - if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
        name: List the state of node modules
        continue-on-error: true
        run: npm list

      - name: Install dependencies
        run: npm install

      - name: Build
        run: npm run build

      - name: Test
        run: npm test

컨텍스트를 사용하여 캐시 키 만들기

캐시 키에는 GitHub Actions에서 지원하는 컨텍스트, 함수, 리터럴 및 연산자가 포함될 수 있습니다. 자세한 내용은 "워크플로 실행에 대한 컨텍스트 정보에 액세스" 및 "워크플로 및 작업에서 식 평가"을(를) 참조하세요.

식을 사용하여 key를 만들면 종속성이 변경되는 경우 자동으로 새 캐시를 만들 수 있습니다.

예를 들어 npm package-lock.json 파일의 해시를 계산하는 식을 사용하여 key를 만들 수 있습니다. 따라서 package-lock.json 파일을 구성하는 종속성이 변경되면 캐시 키가 변경되고 새 캐시가 자동으로 만들어집니다.

npm-${{ hashFiles('package-lock.json') }}

GitHub는 hash "package-lock.json"라는 식을 평가하여 최종 key를 파생합니다.

npm-d5ea0750

cache 작업의 출력 사용

cache 작업의 출력을 사용하여 캐시 적중 또는 누락이 발생했는지 여부에 따라 작업을 수행할 수 있습니다. 지정된 key에 대한 캐시와 정확히 일치하는 항목이 발견되면, cache-hit 출력이 true로 설정됩니다.

위의 예시 워크플로에는 캐시 누락이 발생한 경우 노드 모듈의 상태를 나열하는 단계가 있습니다.

- if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
  name: List the state of node modules
  continue-on-error: true
  run: npm list

캐시 키 일치

cache 작업은 먼저 워크플로 실행을 포함하는 분기의 key 및 캐시 _버전_에 대한 캐시 적중 항목을 검색합니다. 적중 항목이 없으면 restore-keys 및 _버전_을 검색합니다. 현재 분기에 적중 항목이 없으면 cache 작업은 기본 분기 동일한 단계를 다시 시도합니다. 검색 중에는 범위 제한이 적용됨을 유의하시기 바랍니다. 자세한 내용은 “캐시 액세스 제한 사항”을(를) 참조하세요.

캐시 버전은 캐시를 만드는 동안 사용된 path 및 압축 도구의 메타데이터를 사용하여 캐시를 스탬프하는 방법입니다. 이렇게 하면 소비 워크플로 실행이 실제로 압축을 해제하고 사용할 수 있는 캐시와 고유하게 일치합니다. 자세한 내용은 작업 캐시 설명서의 캐시 버전을 참조하세요.

restore-keys을(를) 사용하면 key에 캐시 누락이 있을 때 사용할 대체 복원 키 목록을 지정할 수 있습니다. 가장 구체적인 키부터 정렬된 여러 복원 키를 만들 수 있습니다. cache 작업은 순차적으로 restore-keys을(를) 검색합니다. 키가 직접 일치하지 않으면 작업은 복원 키가 접두사로 지정된 키를 검색합니다. 복원 키에 대해 여러 부분 일치 항목이 있는 경우 작업은 가장 최근에 만든 캐시를 반환합니다.

여러 복원 키를 사용하는 예시

restore-keys: |
  npm-feature-${{ hashFiles('package-lock.json') }}
  npm-feature-
  npm-

실행기는 다음 restore-keys로 확인되는 식을 평가합니다.

restore-keys: |
  npm-feature-d5ea0750
  npm-feature-
  npm-

복원 키 npm-feature-는 문자열 npm-feature-로 시작하는 모든 키와 일치합니다. 예를 들어 npm-feature-fd3052denpm-feature-a9b253ff 두 키 모두 복원 키와 일치합니다. 가장 최근 생성 날짜의 캐시가 사용됩니다. 이 예시의 키는 다음 순서로 검색됩니다.

  1. npm-feature-d5ea0750 는 특정 해시와 일치합니다.
  2. npm-feature-npm-feature-를 접두사로 사용하는 캐시 키와 일치합니다.
  3. npm-npm-를 접두사로 사용하는 모든 캐시 키와 일치합니다.

검색 우선 순위의 예

key:
  npm-feature-d5ea0750
restore-keys: |
  npm-feature-
  npm-

예를 들어 끌어오기 요청에 feature 분기가 포함되어 있고 기본 분기(main)를 대상으로 하는 경우 작업은 다음 순서로 keyrestore-keys를 검색합니다.

  1. feature 분기의 npm-feature-d5ea0750
  2. feature 분기의 npm-feature-
  3. feature 분기의 npm-
  4. main 분기의 npm-feature-d5ea0750
  5. main 분기의 npm-feature-
  6. main 분기의 npm-

사용 제한 및 제거 정책

GitHub는 7일 동안 액세스되지 않은 캐시 항목을 제거합니다. 저장할 수 있는 캐시 수에는 제한이 없지만 리포지토리에 있는 모든 캐시의 총 크기는 제한됩니다10GB까지. 리포지토리가 최대 캐시 스토리지에 도달하면 캐시 제거 정책에 따라 리포지토리에서 가장 오래된 캐시가 삭제되고 공간이 만들어집니다.

이 제한을 초과하면 GitHub는 새 캐시를 저장하지만 총 크기가 리포지토리 한도 미만이 될 때까지 캐시 제거를 시작합니다. 캐시 제거 프로세스로 인해 캐시가 높은 빈도로 생성되고 삭제되는 캐시 스래싱을 일으킬 수 있습니다. 이를 줄이려면 리포지토리의 캐시를 검토하고 특정 워크플로에서 캐싱을 제거하는 등의 수정 단계를 수행할 수 있습니다. 자세한 내용은 "캐시 관리"를 참조하세요.

캐시 관리

워크플로에서 생성된 캐시를 관리하려면 다음을 수행할 수 있습니다.

  • 리포지토리의 모든 캐시 항목 목록을 봅니다.
  • 캐시 크기, 생성 시간 또는 마지막으로 액세스한 시간과 같은 특정 메타데이터를 사용하여 캐시 목록을 필터링하고 정렬합니다.
  • 리포지토리에서 캐시 항목을 삭제합니다.
  • 리포지토리 및 조직의 집계 캐시 사용량을 모니터링합니다.

리포지토리에 대한 캐시를 관리하는 방법에는 여러 가지가 있습니다.

  • 아래와 같이 GitHub 웹 인터페이스를 사용합니다.

  • REST API를 사용합니다. 자세한 내용은 "GitHub Actions 캐시에 대한 REST API 엔드포인트"을(를) 참조하세요.

  • 명령줄에서 캐시를 관리하기 위해 gh cache 하위 명령을 설치합니다. 자세한 내용은 GitHub CLI 설명서를 참조하세요.

    Note

    이 작업을 수동으로 수행하는 경우 CLI 버전 2.32.0 이상이 설치되어 있는지 확인하세요.

캐시 항목 보기

웹 인터페이스를 사용하여 리포지토리에 대한 캐시 항목 목록을 볼 수 있습니다. 캐시 목록에서는 각 캐시가 사용하는 디스크 공간, 캐시가 생성된 시기 및 캐시가 마지막으로 사용된 시기를 확인할 수 있습니다.

  1. GitHub에서 리포지토리의 기본 페이지로 이동합니다.

  2. 리포지토리 이름 아래에서 작업을 클릭합니다.

    "github/docs" 리포지토리에 대한 탭 스크린샷. "작업" 탭은 주황색 윤곽선으로 강조 표시되어 있습니다.

  3. 왼쪽 사이드바의 "관리" 섹션에서 캐시를 클릭합니다.

  4. 리포지토리의 캐시 항목 목록을 검토합니다.

    • 특정 분기에 사용되는 캐시 항목을 검색하려면 분기 드롭다운 메뉴를 클릭하고 분기를 선택합니다. 캐시 목록에는 선택한 분기에 사용되는 모든 캐시가 표시됩니다.
    • 특정 캐시 키가 있는 캐시 항목을 검색하려면 필터 캐시 필드의 구문 key: key-name을(를) 사용합니다. 캐시 목록에는 키가 사용된 모든 분기의 캐시가 표시됩니다.

    캐시 항목 목록의 스크린샷입니다.

캐시 항목 삭제

리포지토리에 대한 write 액세스 권한을 가진 사용자는 GitHub 웹 인터페이스를 사용하여 캐시 항목을 삭제할 수 있습니다.

  1. GitHub에서 리포지토리의 기본 페이지로 이동합니다.

  2. 리포지토리 이름 아래에서 작업을 클릭합니다.

    "github/docs" 리포지토리에 대한 탭 스크린샷. "작업" 탭은 주황색 윤곽선으로 강조 표시되어 있습니다.

  3. 왼쪽 사이드바의 "관리" 섹션에서 캐시를 클릭합니다.

  4. 삭제하려는 캐시 항목의 오른쪽에 있는 을(를) 클릭합니다.

    캐시 항목 목록의 스크린샷입니다. 캐시를 삭제하는 데 사용되는 휴지통 아이콘은 진한 주황색 윤곽선으로 강조 표시됩니다.

캐시 항목 강제 삭제

캐시에는 분기 범위 제한이 있습니다. 즉, 일부 캐시에는 사용 옵션이 제한되어 있습니다. 캐시 범위 제한에 대한 자세한 내용은 이 문서의 앞부분에 있는 "캐시 액세스 제한 사항"을 참조하세요. 특정 분기로 제한된 캐시가 많은 스토리지 할당량을 사용하는 경우 default 분기의 캐시가 높은 빈도로 생성되고 삭제될 수 있습니다.

예를 들어 리포지토리에는 해당 분기로 제한되는 자체 캐시가 있는 많은 새로운 끌어오기 요청이 열릴 수 있습니다. 이러한 캐시는 해당 리포지토리에 대한 캐시 스토리지의 대부분을 차지할 수 있습니다. 리포지토리가 최대 캐시 스토리지에 도달하면 캐시 제거 정책에 따라 리포지토리에서 가장 오래된 캐시가 삭제되고 공간이 만들어집니다. 이 경우 캐시 스래싱을 방지하기 위해 캐시 제거 정책보다 더 빠른 주기로 캐시를 삭제하도록 워크플로를 설정할 수 있습니다. GitHub CLI를 사용하여 특정 분기에 대한 캐시를 삭제할 수 있습니다.

다음 예시 워크플로는 gh cache을(를) 사용하여 끌어오기 요청이 닫힌 후 분기에서 만든 캐시를 최대 100개까지 삭제합니다.

리포지토리 간 끌어오기 요청 또는 포크에서 끌어오기 요청에서 다음 예제를 실행하려면 pull_request_target 이벤트를 사용하여 워크플로를 트리거하면 됩니다. pull_request_target를 사용하여 워크플로를 트리거하는 경우 보안에 유의해야 할 사항이 있습니다. 자세한 내용은 "워크플로를 트리거하는 이벤트"을(를) 참조하세요.

name: cleanup caches by a branch
on:
  pull_request:
    types:
      - closed

jobs:
  cleanup:
    runs-on: ubuntu-latest
    steps:
      - name: Cleanup
        run: |
          echo "Fetching list of cache key"
          cacheKeysForPR=$(gh cache list --ref $BRANCH --limit 100 --json id --jq '.[].id')

          ## Setting this to not fail the workflow while deleting cache keys.
          set +e
          echo "Deleting caches..."
          for cacheKey in $cacheKeysForPR
          do
              gh cache delete $cacheKey
          done
          echo "Done"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GH_REPO: ${{ github.repository }}
          BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge

또는 API를 사용하여 자체 주기에 따라 모든 캐시를 자동으로 나열하거나 삭제할 수 있습니다. 자세한 내용은 "GitHub Actions 캐시에 대한 REST API 엔드포인트"을(를) 참조하세요.