환경 변수 사용하기

환경 변수 입력은 Turborepo 구성에서 고려해야 할 애플리케이션의 중요한 부분입니다.

Turborepo에서 환경 변수를 작업할 때 세 가지 중요한 질문이 있습니다:

구성에서 환경 변수를 고려하지 않으면 잘못된 구성으로 애플리케이션을 배포하게 될 수 있습니다. 이는 프리뷰 배포를 프로덕션으로 배포하는 것과 같은 심각한 문제를 일으킬 수 있습니다.

Good to know: 

Turborepo는 자체 동작을 구성하기 위해 시스템 환경 변수도 사용합니다. 아래에서는 작업의 런타임을 위한 환경 변수와 작업 해싱에 미치는 영향에 대한 정보를 찾을 수 있습니다.

작업 해시에 환경 변수 추가하기

Turborepo는 애플리케이션 동작의 변경 사항을 고려하기 위해 환경 변수를 인식해야 합니다. 이를 위해 turbo.json 파일의 envglobalEnv 키를 사용합니다.

Turborepo logo
./turbo.json
{
  "globalEnv": ["IMPORTANT_GLOBAL_VARIABLE"],
  "tasks": {
    "build": {
      "env": ["MY_API_URL", "MY_API_KEY"]
    }
  }
}
  • globalEnv: 이 목록에 있는 환경 변수 값의 변경 사항은 모든 작업의 해시를 변경합니다.
  • env: 작업에 영향을 미치는 환경 변수 값의 변경 사항을 포함하여 더 나은 세분성을 허용합니다. 예를 들어, lint 작업은 API_KEY 값이 변경될 때 캐시를 놓칠 필요가 없지만, build 작업은 그래야 할 가능성이 높습니다.

Good to know: 

Turborepo는 환경 변수에 대한 와일드카드를 지원하므로 특정 접두사를 가진 모든 환경 변수를 쉽게 고려할 수 있습니다. 자세한 내용은 env에 대한 API 참조를 참조하세요.

Framework Inference

Turborepo는 일반적인 프레임워크에 대해 env 키에 접두사 와일드카드를 자동으로 추가합니다. 패키지에서 아래 프레임워크 중 하나를 사용하는 경우, 이러한 접두사를 가진 환경 변수를 지정할 필요가 없습니다:

Framework

env wildcards

AstroPUBLIC_*
BlitzNEXT_PUBLIC_*
Create React AppREACT_APP_*
ExpoEXPO_PUBLIC_*
GatsbyGATSBY_*
Next.jsNEXT_PUBLIC_*
NitroNITRO_*, SERVER_*, AWS_APP_ID, INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN, CLEAVR, CF_PAGES, FIREBASE_APP_HOSTING, NETLIFY, STORMKIT, NOW_BUILDER, ZEABUR, RENDER
Nuxt.jsNUXT_*, NITRO_*, SERVER_*, AWS_APP_ID, INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN, CLEAVR, CF_PAGES, FIREBASE_APP_HOSTING, NETLIFY, STORMKIT, NOW_BUILDER, ZEABUR, RENDER, LAUNCH_EDITOR
RedwoodJSREDWOOD_ENV_*
Sanity StudioSANITY_STUDIO_*
SolidVITE_*
SvelteKitVITE_*, PUBLIC_*
ViteVITE_*
VueVUE_APP_*, LAUNCH_EDITOR

Good to know: 

Framework Inference는 패키지별로 적용됩니다.

Framework Inference를 사용하지 않으려면 다음과 같이 할 수 있습니다:

  • --framework-inference=false로 작업 실행하기
  • env 키에 부정 와일드카드 추가하기 (예: "env": ["!NEXT_PUBLIC_*"])

Environment Modes

Turborepo의 Environment Mode를 사용하면 런타임에 작업에서 사용할 수 있는 환경 변수를 제어할 수 있습니다:

  • Strict Mode (기본값): turbo.jsonenvglobalEnv 키에 지정된 환경 변수 필터링합니다.
  • Loose Mode: 프로세스의 모든 환경 변수를 사용할 수 있도록 허용합니다.

Strict Mode

Strict Mode는 작업의 런타임에서 사용할 수 있는 환경 변수를 turbo.jsonglobalEnvenv 키에 지정된 환경 변수으로 필터링합니다.

즉, 필요한 모든 환경 변수를 고려하지 않은 작업은 실패할 가능성이 높습니다. 다른 환경에서 잠재적으로 다른 동작을 가질 수 있는 작업을 캐시하고 싶지 않기 때문에 이것은 좋은 일입니다.

Strict Mode를 사용한 캐시 안전성

Strict Mode는 모든 환경 변수를 고려하지 않았을 때 작업이 실패할 가능성을 훨씬 높이지만, 작업 실패를 보장하지는 않습니다. 애플리케이션이 누락된 환경 변수를 우아하게 처리할 수 있다면 여전히 작업을 성공적으로 완료하고 의도하지 않은 캐시 히트를 얻을 수 있습니다.

Passthrough 변수

고급 사용 사례에서는 일부 환경 변수를 해시에 포함하지 않고 작업에서 사용할 수 있도록 하고 싶을 수 있습니다. 이러한 변수의 변경 사항은 작업 출력에 영향을 미치지 않지만 작업이 성공적으로 실행되기 위해 여전히 사용할 수 있어야 합니다.

이러한 경우 해당 환경 변수를 globalPassThroughEnvpassThroughEnv에 추가합니다.

CI 벤더 호환성

Strict Mode는 env, globalEnv, passThroughEnv 또는 globalPassThroughEnv를 사용하여 고려할 때까지 CI 벤더에서 제공하는 환경 변수를 필터링합니다.

이러한 변수 중 작업에 중요하고 Framework Inference에 포함되지 않은 경우 turbo.json 구성에 포함되어 있는지 확인하세요.

Loose Mode

Loose Mode는 globalEnvenv 키에 따라 환경 변수를 필터링하지 않습니다. 이를 통해 Strict Mode로 점진적으로 마이그레이션하는 것을 더 쉽게 시작할 수 있습니다.

스크립트에서 환경 변수를 찾을 수 없는 경우 모든 호출에서 Loose Mode를 활성화하려면 --env-mode 플래그를 사용합니다:

Terminal
turbo run build --env-mode=loose

turbo가 실행될 때 환경 변수를 사용할 수 있는 한 스크립트에서 사용할 수 있습니다. 그러나 이는 구성에서 환경 변수를 고려하는 것을 훨씬 더 쉽게 우연히 잊어버릴 수 있게 하여 작업이 캐시에 히트해서는 안 될 때 캐시에 히트할 수 있도록 합니다.

예를 들어, API에서 데이터를 가져오는 애플리케이션에 일부 코드가 있고, 기본 URL에 대한 환경 변수를 사용할 수 있습니다:

./apps/web/data-fetcher.ts
const data = fetch(`${process.env.MY_API_URL}/resource/1`);

그런 다음 프리뷰 환경을 대상으로 하는 MY_API_URL 값을 사용하여 애플리케이션을 빌드합니다. 애플리케이션을 배포할 준비가 되면 프로덕션용으로 빌드하고 캐시 히트를 확인합니다 - MY_API_URL 변수 값이 변경되었음에도 불구하고! MY_API_URL이 변경되었지만 Turborepo는 프로덕션의 MY_API_URL이 아닌 프리뷰 환경의 MY_API_URL을 사용하는 애플리케이션 버전을 캐시에서 복원했습니다.

Loose Mode를 사용하는 경우 MY_API_URL작업 해시에 고려되지 않았음에도 불구하고 작업 런타임에서 사용할 수 있습니다. 이 작업이 실패할 가능성을 높이고 이러한 잘못된 구성으로부터 보호하기 위해 Strict Mode를 선택하는 것이 좋습니다.

Platform 환경 변수

Vercel에 애플리케이션을 배포할 때 프로젝트에 이미 환경 변수가 구성되어 있을 가능성이 높습니다. Turborepo는 이러한 변수를 turbo.json 구성과 자동으로 확인하여 고려했는지 확인하고 누락된 변수에 대해 경고합니다.

이 기능은 TURBO_PLATFORM_ENV_DISABLED=false를 설정하여 비활성화할 수 있습니다.

.env 파일 처리하기

.env 파일은 로컬에서 애플리케이션 작업을 할 때 유용합니다. Turborepo는 .env 파일을 작업의 런타임에 로드하지 않으며, 프레임워크 또는 dotenv와 같은 도구에서 처리하도록 남겨둡니다.

그러나 turbo.env 파일의 값 변경 사항을 알고 해싱에 사용할 수 있도록 하는 것이 중요합니다. 빌드 간에 .env 파일의 변수를 변경하면 build 작업은 캐시를 놓쳐야 합니다.

이를 위해 파일을 inputs 키에 추가합니다:

Turborepo logo
./turbo.json
{
  "globalDependencies": [".env"], // 모든 작업 해시
  "tasks": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", ".env"] // `build` 작업 해시만
    }
  }
}

여러 .env 파일

*를 사용하여 여러 .env 파일을 한 번에 캡처할 수 있습니다.

Turborepo logo
./turbo.json
{
  "globalDependencies": [".env"], // 모든 작업 해시
  "tasks": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", ".env*"] // `build` 작업 해시만
    }
  }
}

.env 파일은 환경 변수가 env에 추가되지 않은 경우에도 작업 런타임에 변수를 로드할 수 있습니다. CI 및 프로덕션 빌드의 경우 빌드를 위한 환경 변수를 env 키에 추가했는지 확인하세요.

모범 사례

패키지에서 .env 파일 사용하기

리포지토리의 루트에 .env 파일을 사용하는 것은 권장되지 않습니다. 대신 .env 파일을 사용하는 패키지에 배치하는 것이 좋습니다.

이 방법은 환경 변수가 각 애플리케이션의 런타임에 개별적으로 존재하므로 애플리케이션의 런타임 동작을 더 밀접하게 모델링합니다. 또한 monorepo가 확장됨에 따라 이 방법을 사용하면 각 애플리케이션의 환경을 더 쉽게 관리할 수 있어 애플리케이션 간 환경 변수 누출을 방지할 수 있습니다.

Good to know: 

monorepo로 점진적으로 마이그레이션할 때 루트 .env 파일을 사용하는 것이 더 쉬울 수 있습니다. dotenv와 같은 도구는 다른 위치에서 .env 파일을 로드할 수 있습니다.

eslint-config-turbo 사용하기

eslint-config-turbo 패키지turbo.json에 나열되지 않은 코드에서 사용되는 환경 변수를 찾는 데 도움이 됩니다. 이를 통해 모든 환경 변수가 구성에서 고려되도록 할 수 있습니다.

런타임에 환경 변수 생성 또는 변경 피하기

Turborepo는 작업 시작 시 작업의 환경 변수를 해싱합니다. 작업 중에 환경 변수를 생성하거나 변경하면 Turborepo는 이러한 변경 사항을 알지 못하고 작업 해시에 고려하지 않습니다.

예를 들어, Turborepo는 아래 예제의 인라인 변수를 감지할 수 없습니다:

./apps/web/package.json
{
  "scripts": {
    "dev": "export MY_VARIABLE=123 && next dev"
  }
}

MY_VARIABLEdev 작업이 시작된 후에 환경에 추가되므로 turbo는 해싱에 사용할 수 없습니다.

예제

다음은 몇 가지 인기 있는 프레임워크에 대한 적절한 환경 변수 구성의 예입니다:

문제 해결

--summarize 사용하기

--summarize 플래그turbo run 명령에 추가하여 작업에 대한 데이터를 요약하는 JSON 파일을 생성할 수 있습니다. globalEnvenv 키의 diff를 확인하면 구성에서 누락되었을 수 있는 환경 변수를 식별하는 데 도움이 됩니다.

다음 단계

환경 변수를 고려했으면 turbo의 속도로 애플리케이션을 빌드하고 확인하고 배포하는 CI 파이프라인을 구축할 준비가 되었습니다.