[번역] Turborepo Caching

young_pallete·2022년 8월 3일
0

turborepo

목록 보기
1/2

🌈 시작하며

최근에 터보레포 캐싱에 대해서 공부를 하고 있는데요.
아무래도 모노레포를 위한 시스템으로는 최근에 Vercel의 인수로 각광받기 시작한 터라, 번역 글이 부족하더군요.
특히 캐싱은 제가 보기엔 터보레포의 lazy한 최적화 동작을 이해하기에 필수라고 생각했어요.

따라서, 한 번씩 이해가 필요한 것들에 대해서 공식문서 번역 글을 써보려 했어요.
그럼, 시작해볼까요?!


📄 원문

당신이 사용해온 것들과는 달리, turbo는 이전 커맨드 실행에서 나온 파일과 로그들을 캐싱할 수 있습니다. 이를 통해 이미 완료된 작업을 생략하고, 엄청난 시간을 절약할 수 있습니다.

기본적으로, turbo run은 (package.jsonscript에서 정의된) 패키지 태스크의 distbuild에서 나온 파일들을 캐싱할 수 있는 것으로 여깁니다. 또한, turbo runstderrstdout과 같은 로그들을 다루는데, 그것들은 자동적으로 캐싱할 수 있는 아티팩트로써 .turbo/run-<commmand>.log로 쓰여집니다.

이러한 아티팩트로써 로그를 사용함으로써 당신은 당신의 터보레포에 어떠한 커맨드에 관해서든 거의 대부분을 캐싱할 수 있습니다.


캐시할 outputs 설정

pipeline을 사용함으로써 당신은 당신의 터보레포에 걸쳐 캐시 컨벤션을 설정할 수 있습니다.

기본적인 캐시들을 내보내는 행동들을 오버라이드하기 위해, pipeline.<task>.outputs 배열에 일련의 여러 파일 이름의 집합(glob)들을 넘겨주세요. 태스크를 위한 파일 이름 패턴들을 만족하는 파일들은 아티팩트로써 다루어질 겁니다. 🤗

{
  "$schema": "https://turborepo.org/schema.json",
  "pipeline": {
    "build": {
      "outputs": ["dist/**", ".next/**"],
      "dependsOn": ["^build"]
    },
    "test": {
      "outputs": [], // leave empty to only cache logs
      "dependsOn": ["build"]
    }
  }
}

만약 당신의 일이 어떠한 파일을 내뱉지 않는다면, 그저 outputs에 빈 배열을 넣어주시면 됩니다. 터보레포가 간편하고 빠르게 당신을 위한 로그들을 캐싱해 줄 거에요.

ESLint 캐싱을 위한 팁 - 당신은 eslint 이전에 TIMING=1이라는 변수를 설정함으로써 캐싱할 수 있는 예쁜 터미널 output을 얻을 수 있습니다. (그것이 만약 에러가 아닐지라고 해도 말이지요.)
자세한 것은 ESLint 공식 문서를 참조해주세요.

만약 당신이 실행하려 한다면 위의 pipeline 설정과 적절한 아웃풋 폴더들을 입력한 상태로 다음을 입력하세요.

turbo run build test

그리고 node_modules/.cache/turbo를 열어보세요. 당신은 캐시된 아티팩트를 볼 수 있을 겁니다. 🥰

캐싱 끄기

가끔 당신은 정말로 캐시 행동들을 원지 않을 수 있습니다. (예를 들자면, next dev를 한다거나, react-scripts start를 한다던가 할 때가 있습니다.)

전체적으로 캐싱을 하지 않게 해주려면, 어떠한 커맨드든지 --no-cache를 써주면 됩니다!

# Run `dev` npm script in all packages and apps in parallel,
# but don't cache the output

turbo run dev --pararrel --no-cache

또한, pipelinecache 옵션을 false로 설정해줌으로써 특정한 태스크 캐싱을 항상 중단시킬 수 있어요.

{
  "$schema": "https://turborepo.org/schema.json",
  "pipeline": {
    "dev": {
      "cache": false
    }
  }
}

환경변수와 파일 기반 캐싱 이후

몇몇 특정한 태스크에 대해, 당신은 관련 없는 파일이 변경되었을 때의 캐시가 되지 않는 것을 원치 않을 수 있습니다.
예를 들어볼까요? README.md를 업데이트한다는 것은 tesk 태스크에 대해 캐시가 되지 않는 것을 트리거할 필요가 없을지 모릅니다.

당신은 특정 태스크에 대해 고려해야 할 일련의 파일들을 한정하기 위해inputs를 사용할 수 있습니다.
여기서는 test 태스크에 관해 캐시 히트(CPU가 참조하는 메모리가 캐시에 존재하는 것)를 결정하는 것에 관해 오직 .ts.tsx에 대해서만 고려하도록 했네요.

{
  "$schema": "https://turborepo.org/schema.json",
  "pipeline": {
    // ...other tasks
    "test": {
      "outputs": [], // leave empty to only cache logs
      "dependsOn": ["build"],
      "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts"]
    }
  }
}

만약 당신이 turbo를 빌드 타임 시 환경 변수를 인라인하는 도구랑 같이 쓴다면, turbo에 꼭 알려주세요! 그렇지 않다면, 캐시된 아티팩트가 잘못된 환경 변수가 들어간 채로 보내질 지도 모릅니다.

다행이라면, 당신은 환경 변수와 파일의 내용물의 값들에 기반하여 turbo의 캐시를 핑거프린팅(해싱)하는 것을 컨트롤 할 수 있어요.

  • pipeline$가 앞에 붙여진 환경변수명이 dependsOn에 있는 것은 각 패키지 태스크나 각각의 태스크의 캐시 핑거프린트에 있어 영향을 미칩니다.
  • globalDependencies$가 앞에 붙여진 환경변수들은 모든 태스크에 있어 캐시 핑거프린트에 영향을 미칩니다.
  • globalDependencies에 파일이나 파일 이름 패턴이 적힌 경우도 모든 태스크의 캐시 핑거프린트에 영향을 미칩니다.
  • 이름에 THASH가 포함된 환경변수의 값은 모든 태스크의 캐시 핑거프린트에 영향을 미칩니다.
{
  "$schema": "https://turborepo.org/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": [
        "^build",
        // env vars will impact hashes of all "build" tasks
        "$SOME_ENV_VAR",
      ],
      "outputs": ["dist/**"]
    },
    "web#build": { // override settings for the "build" task for the "web" app
      "dependsOn": [
        "^build",
        // env vars that will impact the hash of "build" task for only "web" app
        "$STRIPE_SECRET_KEY",
        "$NEXT_PUBLIC_STRIPE_PUBLIC_KEY",
        "$NEXT_PUBLIC_ANALYTICS_ID",
      ],
      "outputs": [".next/**"],
    },
    "docs#build": { // override settings for the "build" task for the "docs" app
      "dependsOn": [
        "^build",
        // env vars that will impact the hash of "build" task for only "docs" app
        "$STRIPE_SECRET_KEY",
        "$NEXT_PUBLIC_STRIPE_PUBLIC_KEY",
        "$NEXT_PUBLIC_ANALYTICS_ID",
      ],
      "outputs": [".next/**"],
    }
  },
  "baseBranch": "origin/main",
  "globalDependencies": [
    "$GITHUB_TOKEN",// env var that will impact the hashes of all tasks,
    "tsconfig.json", // file contents will impact the hashes of all tasks,
    ".env.*", // glob file contents will impact the hashes of all tasks,
  ]
}

팁 - 대부분의 모노레포에서, 당신은 공유된 패키지의 환경 변수를 자주 사용하지 않고, 오직 애플리케이션에서만 사용할 것인데요. 따라서, 캐시 히트 비율을 높이기 위해서 당신은 그들이 사용된 앱의 특정 태스크에 있는 환경 변수를 포함해야 할 것입니다.

캐시 강제 덮어쓰기

거꾸로, 만약 당신이 이전의 캐시된 태스크를 다시 강제 실행하기를 원하는 경우에는 --force flag를 추가하세요.

# Run `build` npm script in all packages and apps,
# ignoring cache hits.

turbo run build --force

로그들

turbo 가 당신의 태스크들의 output들을 캐시할 뿐만 아니라, 터미널에서의 output 역시 (다시 말하자면 stdout, stderr의 결합) <package>/.turbo/run-<command>.log에 기록합니다.

turbo가 캐시된 태스크에 들어가면, 그것은 마치 다시 일어난 것처럼 output을 다시 실행할 것입니다. 다만 패키지의 이름이 약간 흐리게 표시될 것입니다.

해싱

지금까지, 당신은 turbo가 주어진 태스크에 대해 어떻게 캐시 히트와 캐시 미스를 결정하는지에 대해 궁금하셨을텐데요! 좋은 질문입니다. 👏🏻

첫번째로, turbo는 모노레포의 현재 전역상태를 해시로 구성합니다.

  • 파일 이름 패턴에 맞는 파일들의 내용물과 globlDependencies에 리스트되어 있는 환경변수의 값들
  • THASH라는 문자가 포함된 key-value 쌍의 정렬된 환경 변수 (예를 들면 STRIPE_PUBLIC_KEY가 아닌 STRIPE_PUBLIC_THASH_SECRET_KEY)

그러면 이는 주어진 패키지의 태스크와 관련된 여러 요소를 추가합니다.

  • 만약 존재한다면 inputs 파일 이름 패턴과 일치하는 패키지 폴더나 파일들에 있는, gitignore에는 없는 모든 내용물들에 해시 값을 붙입니다.
  • 모든 내부 종속성들에 해시 값을 붙입니다.
  • pipeline에 있는 outputs에 명시된 옵션들에 해시 값을 붙입니다.
  • root lockfile로부터 package.json에 명시된, 설치된 모든 dependencies, devDependencies, optionalDependencies의 버전 집합
  • 패키지 태스크의 이름
  • 적용할 수 있는 pipeline.<task-or-package-task>.dependsOn에 리스트된, 환경 변수와 일치하는 key-value 쌍의 정렬된 환경 변수 리스트

일단 turbo가 실행된 주어진 패키지 태스크에 들어가면, (로컬과 원격 모두) 해시와 일치하는 캐시를 검사합니다.
만약 일치한다면, 태스크 실행을 스킵하고, 캐시된 output을 적절한 곳에 이동시키거나 다운로드합니다. 그리고 즉시, 이전에 기록된 로그들을 다시 실행합니다.

만약에 계산된 해쉬값과 일치하는 (원격 또는 로컬) 캐시가 없다면, 로컬로 작업을 실행한 후 turbo는 인덱스로써 해쉬를 사용하면서 outputs에 명시된 곳에 캐싱합니다.

주어진 태스크의 해시 값은 TURBO_HASH 환경변수로써 실행 시간에 주입됩니다.
이 값은 Dockerfile 등을 태깅하거나 outputs에 스탬핑을 하는 데 유용합니다.

turbo v0.6.10인 현재, turbo의 해싱 알고리즘은 npmpnpm을 쓸 땐 위와 살짝 다릅니다. 만약 이들 중 하나인 패키지 매니저를 사용할 때, turbo는 각각의 패키지 태스크에 대하여 해쉬 알고리즘에 lockfile의 해시된 내용들을 포함할 것입니다. 그것은 현재의 yarn 구현과 같이 모든 종속성의 resolved된 집합들을 파싱하거나, 구문 분석을 하지 않습니다.


✨ 마치며

와... 이 글을 하나하나 번역하는 데 꽤 적지 않은 시간이 드는군요..!
그렇지만, 하나하나 의미를 뜯어보면서 꽤나 새로운 정보들을 많이 얻어가서 기분이 좋아요 🥰

다들 터보레포 즐겁게 쓰시길 바라며, 이상! 👐🏻

profile
People are scared of falling to the bottom but born from there. What they've lost is nth. 😉

0개의 댓글