# 고급 Elixir 캐시 구성

<.localized_link href="/guides/features/cache/elixir">Elixir 캐시 설정 가이드</.localized_link>로 시작하세요. 아래 옵션은 프로젝트에 추가 컴파일 입력, 의존성 예외 또는 다른 체크아웃 경로가 있을 때만 필요합니다.

## 의존성 선택

`cache: true`는 지원되는 의존성을 자동으로 캐시합니다. 키워드 목록도 동일한 자동 선택을 적용하며, 선택적 재정의가 가능합니다:

```elixir
cache: [exclude: [:a_dependency_with_compile_time_side_effects]]
```

특정 의존성에만 캐싱을 제한하려면 다음과 같이 설정하세요:

```elixir
cache: [dependencies: [:nimble_options, :nimble_parsec]]
```

`dependencies: :all`는 모든 지원되는 의존성을 명시적으로 선택하고, `dependencies: []`는 아무것도 선택하지 않습니다. `exclude:`는 두 선택 모두보다 우선합니다. `cache`를 생략하거나 `false` 또는 `nil`로 설정하면 캐싱이 비활성화됩니다.

지원되는 의존성은 Hex 또는 Git을 통해 가져오며, Elixir/Erlang 소스와 함께 표준 Mix 컴파일러 파이프라인을 사용하거나 rebar3의 일반적인 순수 BEAM 컴파일을 사용합니다. Mix 의존성은 상위 의존성이 rebar3를 사용할 경우 아티팩트를 재사용할 수도 있습니다. Rebar 구성, 소스/헤더 파일 및 rebar3 실행 파일 지문이 키에 포함됩니다. 패키징된 `ebin/*.app` 메타데이터와 수동적인 Makefile도 지원됩니다. Rebar 구성 스크립트는 조회 전에 Mix에 의해 이미 평가되었으며, 해당 소스와 유효한 구성이 키에 들어갑니다. 애플리케이션 소스 스크립트(`*.app.src.script`)는 나중에 rebar3에 의해 평가되며, 빌드 플러그인과 컴파일 훅과 마찬가지로 감사된 빌더 계약이 필요합니다. 누락된 rebar3 런처는 Mix의 일반 설치 프로그램을 사용하여 지문 추출 전에 설치되며, 콜드 워커는 여전히 해당 설치 프로그램에 접근할 수 있어야 합니다.

사용자 정의 트레이서, 소스 심볼릭 링크, 엄브렐라 루트 및 로컬 의존성을 포함하는 체인은 정상적으로 컴파일됩니다. Tuist 자체의 부트스트랩 의존성도 콜드 워커에서 정상적으로 컴파일됩니다. 구조적 자격 조건이 임의의 컴파일 코드가 결정론적임을 증명하지는 않습니다.

## 추가 입력 선언

소스 트리, 잠긴 의존성 식별자, 상위 소스, BEAM 및 리소스, 의존성 런타임/선택적/애플리케이션 플래그, 해결된 애플리케이션 메타데이터, 명시적 유효 애플리케이션 구성, 컴파일러 옵션(렉서 및 파서 옵션 포함), Mix 환경 및 타겟, 툴체인 식별자는 자동으로 포함됩니다. 의존성별 `env:` 및 `system_env:`는 키에 들어가고 해당 환경에서 구성이 평가됩니다. 애플리케이션 기본값은 VM 로드 상태가 아닌 소스 입력을 통해 전달됩니다.

컴파일 시 소스 트리 외부의 파일을 읽거나 추가 환경 변수를 사용하는 의존성의 경우, 해당 입력을 선언하세요:

```elixir
cache: [
  inputs: ["schemas", "config/compiler-input.json"],
  env: ["YOUR_COMPILER_OPTION"]
]
```

Elixir 매크로와 모듈 본문은 임의의 파일, 환경, 주변 코드 경로, 네트워크 응답 및 시간을 읽을 수 있습니다. Tuist는 이러한 읽기를 자동으로 발견하지 않습니다. 선언되지 않은 입력을 변경하면 오래된 출력이 생성될 수 있습니다. 시간이나 네트워크에 종속된 컴파일 또는 모든 빌드에서 실행되어야 하는 부작용이 있는 의존성은 제외하세요; 더 엄격한 제어가 필요할 때는 `dependencies:`를 사용하여 감사된 의존성 허용 목록을 구성하세요.

표준 컴파일러/런타임 변수(`ERL_COMPILER_OPTIONS`, `ELIXIR_ERL_OPTIONS`, `ERL_AFLAGS`, `ERL_FLAGS`, `ERL_ZFLAGS`, `SOURCE_DATE_EPOCH`, `ERL_LIBS`, `MIX_PATH` 및 `MIX_ARCHIVES`)는 자동으로 캡처됩니다. 툴체인 식별자에는 Elixir 빌드, 가능한 경우 전체 OTP 버전, ERTS, 컴파일러 바이트코드, OS/버전, 아키텍처, 워드 크기 및 바이트 순서가 포함됩니다. 유효한 컨텍스트는 각 조회 전에 캡처됩니다. 의존성별 입력 모델은 한 준비 과정에서 조회 계획을 위해 공유될 수 있습니다; 컴파일은 계획을 지우고 복원은 설치된 애플리케이션의 기록을 무효화합니다. 단계별 설치 및 게시는 조회 계획을 재사용하지 않고 항상 새로운 입력을 확인합니다. 조회 미스도 컴파일 전에 새로운 키를 캡처합니다. 변경된 입력은 이전 입력용으로 빌드된 코드를 설치하는 대신 단계별 히트를 거부합니다.

키는 결정론적 용어 인코딩과 정렬된 파일 시스템 순회를 사용합니다. 정렬되지 않은 빌더 선언과 선언된 입력 집합은 정렬되고 중복 제거되며, 정렬된 컴파일러 옵션은 순서를 유지합니다. 파일 내용, 이름, 실행 비트 및 누락된 경로가 중요하며, 파일 시스템 타임스탬프는 중요하지 않습니다. 파일 선언은 소유권, 타임스탬프 또는 기타 파일 시스템 메타데이터를 모델링하지 않습니다; 이러한 값으로부터 출력을 파생하는 빌더는 제외하세요. 상위 컴파일러 매니페스트는 증분 관리 목적으로 제외되며, 해당 내용을 의도적으로 읽는 코드는 이를 추가 입력으로 선언해야 합니다. 정규식 구성은 소스와 옵션을 사용하며, VM 로컬 컴파일 참조는 사용하지 않습니다. 기타 불투명한 런타임 값은 캐싱을 우회합니다. 업데이트된 키 모델은 마이그레이션 없이 이전 항목을 무효화합니다.

결정론적 키 인코딩은 결정론적 컴파일러 출력과 별개입니다. 최근 Elixir 버전에서 otherwise identical 빌드 간에 상위 BEAM 메타데이터가 변경되면, SDK 부트스트랩, 시딩 및 캐시 소비 전에 `ERL_COMPILER_OPTIONS='[deterministic]'`를 설정하는 것을 고려하세요. 기존 컴파일러 옵션과 병합하고 설정 변경 시 의존성 출력을 한 번 다시 빌드하세요. SDK는 이를 자동으로 설정하지 않으며, 정확한 값은 키의 일부로 남습니다. 완전한 상위 바이트는 여전히 해시되며, 정규화되거나 제거되지 않습니다. 이는 크로스 체크아웃 또는 임의 빌더 재현성 보장이 아닙니다. 컴파일러 옵션은 또한 `module_info(:compile)`에서 소스/옵션을 생략하므로, 채택하기 전에 커버리지, 디버깅 및 소스 발견 도구를 검증하세요. 컴파일러 플래그는 정렬되지 않은 컴파일 타임 생성기를 수정하지 않습니다. SDK는 보안 백포트를 포함한 Mint 1.10.2 이상이 필요합니다. 이 릴리스는 HTTP/2 프레임 함수를 생성하는 데 사용되는 맵을 정렬하므로, SDK 업그레이드 시 이전 Mint 잠금 항목을 업데이트하세요. 다른 의존성과 컴파일러 패스는 `deterministic`가 활성화되어 있더라도 다양한 부트스트랩 BEAM을 생성할 수 있습니다.

렉서 및 파서 출력은 잠긴 Git 트리 또는 Hex 패키지 파일 매니페스트에 없을 때만 파생 파일로 처리됩니다. 제공된 `.erl` 파일과 불투명한 디렉터리/서브모듈 내용은 일반 입력으로 남아 있으며, 재생성된 제공 파일은 동일한 스테이징 후 입력 조정 과정을 통과해야 합니다. OTP의 `parsetools`에서 가져온 생성기 템플릿도 툴체인 식별자에 포함됩니다. 동시 빌드 간에 의존성 소스 체크아웃을 격리 상태로 유지하세요: 생성기와 네이티브 빌더가 `deps/`에 쓸 수 있습니다. 중첩/사용자 정의 rebar 생성기 레이아웃은 여전히 감사된 `generated` 선언이 필요할 수 있습니다.

## 네이티브 및 사용자 정의 빌더

감사된 Mix, rebar3 또는 Make 빌더의 경우, 의존성별 계약을 선언하세요:

```elixir
cache: [
  builders: [
    bcrypt_elixir: [
      platform: "build-image@sha256:YOUR_IMMUTABLE_IMAGE_DIGEST",
      outputs: ["priv/bcrypt_nif.so"],
      tools: ["cc", "make"],
      env: ["YOUR_BUILDER_OPTION"]
    ]
  ]
]
```

`platform`는 호환되는 네이티브 빌드 환경을 식별합니다. 컴파일러, SDK, 시스템 헤더 및 공유 라이브러리를 포함하는 불변의 이미지/툴체인 식별자를 사용하세요. `linux`와 같은 재사용 가능한 라벨은 사용하지 마세요. Elixir/OTP 및 일반적인 플랫폼 검사는 여전히 적용됩니다. 이는 빌더에 대한 명시적인 감사이며, 네이티브 입력이나 필수 부수 효과의 자동 검색이 아닙니다. 유효하지 않은 명시적 빌더 계약은 캐싱을 비활성화된 상태로 묵시적으로 남기는 대신, 조치 가능한 구성 오류를 발생시킵니다.

`outputs`는 의존성의 애플리케이션 빌드 디렉터리에 상대적인 필수 경로를 나열합니다. 런타임에 필요한 실제 라이브러리/실행 파일을 나열하세요. 출력이 누락되면 Mix가 BEAM을 최신으로 간주하더라도 복원이나 컴파일이 트리거되며, 불완전한 스냅샷은 거부됩니다. 빌더의 `env`를 사용하여 추가 환경 변수를 선언하고, `inputs`를 사용하여 소비 프로젝트에 상대적인 외부 파일/디렉터리를 선언하세요. 네이티브 키는 의존성의 유효한 `system_env` 재정의 값을 사용하여 `PATH`, `CC`, `CXX`, `CFLAGS`, `LDFLAGS`, `SDKROOT` 및 `RUSTFLAGS`와 같은 표준 빌드 환경 변수를 자동으로 포함합니다. 해결된 Mix 프로젝트 구성도 네이티브 빌더 키에 포함되며, 불투명한 함수 값 구성은 캐시할 수 없습니다.

선택적 `tools` 이름은 해당 유효한 `PATH`에서 확인됩니다. 상대 도구 경로는 의존성 소스 디렉터리에 상대적입니다. 실행 파일 바이트와 확인된 경로는 키에 포함되며, 사용할 수 없는 선언된 도구는 캐싱을 우회합니다. 런처나 컴파일러 래퍼의 지문은 해당 SDK, 하위 프로세스 또는 시스템 라이브러리를 커버하지 않습니다. 불변의 `platform`와 추가 `inputs`가 이를 커버해야 합니다. `MAKEFLAGS`는 사용자 정의 빌더가 읽을 수 있으므로 그대로 유지됩니다. 따라서 상속된 GNU make jobserver 식별자는 실행 간에 안전한 캐시 미스를 유발할 수 있습니다. 이러한 값이 키에서 제거되었다고 가정하지 말고, 격리된 캐시 작업에서 안정적인 빌드 플래그를 사용하세요.

일부 빌더는 `_build/`뿐만 아니라 `deps/` 아래에 파일을 생성합니다. `generated`에 해당 의존성의 소스 디렉터리에 상대적인 경로를 나열하세요. 예를 들어 `generated: ["priv/native"]`와 같습니다. 소스 입력에서 제외되는 것은 이러한 생성된 경로뿐입니다. 원래 리소스나 소스 파일을 제외하지 마세요. 이들은 입력으로 남아 있어야 합니다. 경로는 글롭이나 순회 없이 리터럴입니다. 계약, 플랫폼, 추가 입력, 환경 값 및 모든 사용자 정의 의존성 컴파일 명령은 모두 키에 참여합니다. `compile: false`는 컴파일에서 제외되는 옵션으로 남아 있습니다.

감사된 스냅샷은 소스 기반 `ebin`, `priv`, `include` 및 `src` 리소스를 복원된 애플리케이션으로 구체화합니다. 따라서 네이티브 라이브러리, 포트 실행 파일, 헤더 및 생성된 리소스는 의존성 소스를 수정하지 않고도 콜드 체크아웃에서 생존합니다. 실행 모드와 포함된 상대 리소스 심볼릭 링크는 보존되며, 탈출, 절대 및 순환 링크는 거부됩니다. 모든 상위 애플리케이션 리소스는 일반 `priv` 리소스 및 사용자 정의 출력 디렉터리를 포함하여 하위 키에 들어가며, 네이티브 라이브러리나 BEAM만이 아닙니다. 프로듀서 소스 경로를 직접 읽는 코드는 재배치되지 않습니다. 애플리케이션 아티팩트 외부에 필수 부수 효과가 있는 빌더는 여전히 해당 단계가 필요합니다.

입력과 출력이 감사될 때까지 사용자 정의 빌더를 제외 상태로 유지하세요. 계약은 콜드 SDK 부트스트랩 컴파일, 64 MiB 아티팩트 제한 또는 호환되는 빌드 환경의 필요성을 제거하지 않습니다.

## 체크아웃 경로 간 재사용

체크아웃 경로는 기본적으로 키에 참여합니다. 의존성이 프로듀서 경로에 의존하지 않는 경우, 다른 체크아웃 위치 간 재사용을 선택하세요:

```elixir
cache: [portable: true]
```

`config/config.exs`의 `__DIR__`에서 구축된 경로와 같이 체크아웃 경로를 포함하는 구성된 값은 휴대용 키를 변경하지 않습니다. Elixir 툴체인이 설치된 위치 역시 영향을 주지 않습니다. 아카이브와 rebar3는 내용으로 계산됩니다.

캐시된 BEAM은 프로듀서 디버그/소스 경로와 컴파일 타임 `__DIR__`, `__ENV__.file` 및 `File.cwd!()` 값을 유지합니다. 휴대용 재사용은 이를 재작성하지 않습니다. 리소스 링크는 현재 소스 체크아웃을 가리킵니다. 상위 BEAM 바이트도 키에 들어가며 경로를 포함할 수 있으므로, 재사용은 독립적으로 다시 컴파일하는 대신 동일한 캐시에서 상위 클로저를 복원해야 할 수 있습니다.

## 저장소 및 접근

| 옵션 | 기본값 | 목적 |
| --- | --- | --- |
| `remote` | `true` | 로컬 미스 후 공유 원격 캐시를 사용합니다. |
| `upload` | `true` | 새 번들을 원격으로 게시합니다. `false`라도 읽기 및 로컬 스냅샷은 허용됩니다. |
| `path` | Tuist의 캐시 디렉터리(`mix/dependencies/v1` 하위) | 다른 로컬 저장소를 선택합니다. |
| `endpoint` | 자동으로 발견됨 | 계정의 HTTPS REAPI 엔드포인트를 재정의합니다. |

`upload: false`는 클라이언트 동작을 제어하며, 권한 부여를 제어하지 않습니다. 프로젝트 캐시 권한은 서버에서 적용됩니다. 프로젝트 캐시 읽기만 가능한 자격 증명은 업로드를 자동으로 건너뜁니다. 프로젝트 `endpoint:` 옵션과 발견된 엔드포인트는 루프백(`localhost`, `127.0.0.1`, `::1`) 개발 엔드포인트를 제외하고 HTTPS가 필요합니다.

비어 있지 않은 `TUIST_CACHE_ENDPOINT`는 `endpoint:`와 발견 모두를 재정의합니다. 호스팅된 러너는 이를 사용하여 클러스터 내 개인 캐시에 접근합니다. 이 운영자가 제어하는 환경 재정의는 비루프백 호스트에서도 HTTP를 허용합니다. HTTP는 프로젝트 범위 캐시 토큰과 아티팩트를 암호화 없이 전송하므로, 신뢰할 수 있는 네트워크에서만 사용하세요. 유효하지 않은 재정의는 발견을 시도하지 않고 로컬 스냅샷으로 폴백합니다.

로컬 스냅샷과 원격 번들은 64 MiB로 제한됩니다. 더 큰 아티팩트는 캐시되지 않고 컴파일됩니다. 로컬 저장소는 자동 퇴출 기능이 없으므로 필요할 때 내용을 제거하세요. 원격 아티팩트는 Kura의 기존 보존, 퇴출 및 프로젝트 정리 규칙을 사용합니다.

> [!IMPORTANT]
> 컴파일러 매니페스트와 BEAM은 비밀을 포함한 프로듀서 경로와 컴파일 타임 값을 포함할 수 있습니다. 프로젝트 캐시 리더는 이러한 아티팩트에 접근할 수 있습니다. 캐시 라이터는 신뢰할 수 있는 코드 프로듀서입니다. 다이제스트 검사는 손상된 데이터를 감지하지만, 악의적인 실행 가능 BEAM은 감지하지 않습니다. 신뢰할 수 없는 PR 작업에 캐시 쓰기 자격 증명을 노출하거나, 해당 자격 증명이 사용 가능한 상태에서 신뢰할 수 없는 의존성을 컴파일하지 마세요.

## 누락된 히트 문제 해결

- 패키지를 설치한 후 `mix tuist.setup`를 실행하고 생성된 Mix 구성을 커밋하세요. 설정은 다른 별칭과 Tuist 옵션을 보존하며, 이를 묵시적으로 제거하는 대신 사용자 정의 컴파일 작업을 거부합니다.
- 생성된 컴파일 별칭을 유지하세요. 직접적인 `mix tuist.compile` 작업 검색은 캐시가 검사하기 전에 의존성을 컴파일할 수 있습니다.
- 선택된 지원되는 의존성에 대해 이미 최신 상태인 유효한 출력물은 `up_to_date` 사유의 로컬 히트로 간주됩니다. 이러한 항목은 사후적으로 게시되지 않으며, 아티팩트 키, 전송 바이트, 복원 대기 시간 또는 절약된 예상 시간을 포함하지 않습니다. 스냅샷 복원을 테스트하려면, 캐시가 채워진 후 `mix deps.clean NAME --build`를 사용하여 지원되는 의존성의 빌드만 정리한 다음 다시 컴파일하세요.
- `MIX_ENV`, `MIX_TARGET`, 컴파일러 설정 및 선언된 입력을 일치시키세요. 포터블 재사용이 활성화되지 않은 경우 경로 변경도 키를 변경합니다.
- 지원되지 않는 의존성은 누락이 아닌 **캐시되지 않음**으로 표시됩니다. 이들은 히트율에서 제외됩니다. 조회도 없고 최신 로컬 히트도 없는 빌드는 0%가 아닌 사용 불가 비율을 가집니다.
- 누락된 자격 증명, 사용 불가능한 엔드포인트 및 손상된 스냅샷은 컴파일로 폴백합니다. 컴파일러 실패는 여전히 빌드를 실패시킵니다.
- CAS 기록은 빌드 보고서 후에 도착할 수 있습니다. 새로 인제스트된 전송을 보려면 새로 고침하세요. 로컬 히트와 레거시 빌드에는 원격 CAS 출력이 없습니다.

서버는 `up_to_date` 로컬 히트를 기록하기 위해 컴파일 보고서 계약 `0.2`에 대한 지원이 필요합니다. 이전 서버가 캐시 데이터나 스키마 열거값을 명시적으로 거부하는 경우, 패키지는 이러한 새로운 재사용 관찰 없이 보고서를 한 번 다시 시도합니다. 컴파일 세부 정보와 다른 캐시 결과는 보존되며, 서버가 업그레이드될 때까지 새로운 로컬 재사용은 사용할 수 없습니다. 서버를 먼저 배포하면 이 추가 요청을 피할 수 있습니다. 계약 버전은 지원을 협상하지 않으며, 인증 실패, 전송 실패 및 기타 검증 메시지는 재시도되지 않습니다. 열거 오류는 이전 서버에서 해당 필드를 식별하지 않습니다. 유지된 잘못된 필드는 단일 재시도에서도 여전히 실패합니다.

## 수동 컴파일 통합

설정이 프로젝트 구성을 안전하게 편집할 수 없는 경우, 사용자 정의 컴파일 작업을 보존하면서 이 별칭과 함수를 Mix 프로젝트 모듈에 수동으로 추가하세요:

```elixir
# In aliases/0:
compile: &compile/1

# In the same Mix project module:
defp compile(args) do
  if "--no-compile" not in args do
    compile_tuist_ex()
  end

  Mix.Task.run("deps.loadpaths", ["--no-compile", "--no-deps-check"])
  Mix.Task.run("tuist.compile", args)
end

defp compile_tuist_ex do
  deps =
    ["tuist_ex"]
    |> Mix.Dep.filter_by_name(Mix.Dep.load_and_cache(), include_children: true)
    |> Enum.reject(&(Mix.Dep.ok?(&1) and &1.scm.fetchable?()))
    |> Enum.map(&Atom.to_string(&1.app))

  if deps != [], do: Mix.Task.run("deps.compile", deps)
end
```

이 함수들은 Tuist와 그 의존성이 이미 컴파일되었거나 명령이 `--no-compile`로 실행될 때 해당 작업을 건너뛰며, 콜드 병렬 빌드를 포함하여 다른 의존성보다 먼저 Tuist를 컴파일하고 로드합니다. 동일한 함수는 Hex, Git 및 경로 설치에서도 작동하며 스크립트 경로가 필요하지 않습니다.

별칭이 `deps.compile tuist_ex --include-children`로 시작하는 경우, 모든 `mix compile`는 Tuist의 의존성을 다시 빌드하고 전체 프로젝트를 다시 컴파일할 수 있습니다. 이를 대체하려면 `mix tuist.setup`를 다시 실행하세요.

## 작동 방식

Elixir 캐싱은 별도의 Mix 저장소 서비스가 아닌 Bazel에서 사용하는 공유 REAPI ActionCache/CAS 파이프라인, 인증 및 Kura 서명 분석을 사용합니다. 모델링된 입력 키는 전체 컴파일 번들의 원시 바이트 SHA-256 다이제스트를 포함하는 ActionResult를 참조합니다. Tuist는 단계별 설치 전에 파일, 애플리케이션 메타데이터, 선언된 BEAM 및 SCM 매니페스트를 검증합니다. 손상된 항목은 성공적인 컴파일 후 복구됩니다.

OTP 28 이상에서는 원격 세션이 최소 1 KiB 이상의 ByteStream 전송에 대해 zstd 압축을 협상합니다. 압축 불가능한 업로드, 이전 OTP 런타임 및 압축을 지원하지 않는 서버는 identity 전송을 사용합니다. 다이제스트, 아티팩트 제한 및 보고된 바이트는 압축되지 않은 콘텐츠를 참조합니다. 디코딩된 바이트는 설치 전에 경계가 지정되고 검증됩니다. 각 의존성은 단일 CAS 번들로 유지되어 작은 아티팩트에 대한 파일별 또는 청크 요청을 피합니다.

원격 자격 증명/연결은 지연되어 해결됩니다. 유휴 빌드와 로컬 히트(이미 최신 상태인 출력 포함)는 원격 엔드포인트에 연결하지 않습니다. 컴파일러 실패를 포함하여 모든 종료 시 하나의 세션이 닫힙니다. 클라이언트 RPC에는 30초의 데드라인이 있습니다. Mix는 잠금 확인, 로컬 의존성 컴파일 및 지원되지 않는 작업에 대한 책임을 계속 유지합니다.

대시보드 지연 시간/바이트는 로컬 대 원격 출처를 보존하고 측정된 0과 사용 불가 값을 구분합니다. 원격 타이밍은 클라이언트 CAS 전송을 측정하는 반면, 로컬 타이밍은 검증 및 설치를 포함하며 둘 다 컴파일은 포함하지 않습니다. CAS Outputs는 로컬 복사본이나 액션 입력 키가 아닌 성공적인 Kura 서명 전송을 사용합니다. 처리량은 측정된 시간으로 나눈 바이트이며 압축된 크기는 사용할 수 없습니다. 추정된 컴파일 시간 절감은 측정된 종단 간 빌드 절감이 아닌 프로듀서의 원래 컴파일 지속 시간입니다.

독립적이고 준비된 의존성은 동일한 HTTP/2 연결을 통해 최대 4개의 동시 요청 윈도우에서 가져옵니다. 이는 디코딩된 번들 버퍼링을 64 MiB 제한을 받는 4개의 아티팩트로 제한합니다. 키 계획, Mix 상태 및 설치는 직렬화된 상태로 유지됩니다. 하류 키는 상류 아티팩트를 기다리며 프리페치된 바이트는 정확한 입력 키에서만 소비되고 원격 설치 전에 입력이 다시 확인됩니다. 이미 최신 상태인 출력과 로컬 스냅샷은 추측적 원격 요청을 유발하지 않습니다. 선택된 캐시 누락에 대한 컴파일과 업로드는 직렬로 유지되며, 동시성이 모든 빌드가 더 빠르다는 것을 보장하지는 않습니다.

## 모든 의존성이 컴파일을 건너뛸 수 있나요?

호환되는 히트는 지원되는 의존성의 컴파일을 건너뛸 수 있지만, `cache: true`는 제로 컴파일 보장이 아닌 fail-open입니다. 누락/퇴출된 항목, 지원되지 않는 빌더 및 콜드 SDK 부트스트랩은 여전히 컴파일될 수 있습니다. 높은 히트율 자체로는 실제 속도 향상을 보장하지 않습니다.

한 번 빌드/여러 번 테스트 CI의 경우,
<.localized_link href="/guides/features/test-sharding/elixir">Elixir test sharding</.localized_link>
를 사용하여 모든 작업자가 의존성별 캐시 히트로부터 이를 재구성하기를 기대하는 대신 정확히 준비된 빌드를 배포하세요. 완전한 빌드, 특히 네이티브 라이브러리를 포함하는 빌드를 재사용하려면 여전히 호환되는 플랫폼, 툴체인 및 구성이 필요합니다. 임의의 사용자 정의 빌드는 외부 입력, 출력 및 필요한 부작용을 모델링하지 않고서는 빌드 단계를 안전하게 건너뛸 수 없습니다.
