ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Yarn berry] Yarn Berry 환경에 대한 이해도 높이기
    개발 블로깅/기타 개념 2022. 10. 9. 18:51

     

    이번에 Yarn berry에서 이것저것 작업하게 되면서 Yarn Berry라는 환경에 대해 알게 된 내용들을 한번 정리해 보려고 한다.

     

    Yarn Berry 환경은 단순 자바스크립트 파일일 뿐이다.

    이것을 설명하기 위해 우선 Yarn Classic 환경에 대해 먼저 다루어볼 필요가 있다.
    Yarn Classic을 먼저 알아보자.

     

    Yarn Classic

    우리가 일반적으로 Yarn을 설치할 때는 Homebrew를 통해서 설치한다.
    Homebrew를 통해 설치하게되면, Yarn 패키지 자체는 우리 로컬 PC 내에서 Global Package 공간 어딘가에 저장이 되고 이후에 커맨드를 통해 실행시킬 수 있다.

    $ yarn add ...
    $ yarn remove ...

     

    터미널에서 yarn으로 시작하는 명령어를 수행할 수 있다는 뜻은 무엇일까?

    이는 OS 내 Shell 스크립트 형식으로 사용할 수 있는 명령어로, OS 인터페이스를 통해 수행할 수 있는 명령어라는 뜻이다.

    따라서 우리는 Homebrew를 통해 Yarn을 설치하기만 하면, 이후에는 어느 디렉토리에서는 Yarn 명령어를 수행할 수 있다.

     

    Yarn Berry

    그러나 우리가 Yarn Berry 환경을 세팅할 때 어떻게 하는가?

    처음부터 로컬 자체에 Yarn Berry라는 환경을 세팅하지 않고, 특정 프로젝트 환경에서 아래 명령어를 통해 Berry 환경을 세팅한다.

    $ yarn init -2
    
    // or
    
    $ yarn init -berry

     

    그러면 해당 프로젝트 루트 경로에 .yarn/release/yarn-3.2.3.cjs 라는 파일이 생기는 것을 알 수 있다.

    이 yarn-3.2.3.cjs 파일의 정체가 무엇일까?
    이것이 바로 yarn Berry환경을 구축하는 자바스크립트 파일이다. 그리고 Yarn Berry 환경에서 수행되는 모든 Yarn 동작은 이 yarn-3.2.3.cjs 스크립트 위에서 수행된다.

     

    정리해보면, Yarn Classic은 OS 인터페이스에서 수행되는 Shell 명령어라면, Yarn Berry는 단순히 해당 프로젝트에서만 동작하는 자바스크립트라는 것이다.
    한마디로 Yarn Berry에서 사용되는 Yarn은 OS 인터페이스 명령어가 아니다.

     

    이에 대한 증거로, yarn berry에서 package.json 내 명시한 script로 환경변수를 주입하기 위해 'export' 라는 명령어를 시도하면, 아래처럼 커맨드가 먹히지 않는 경험을 해보았을 것이다. 

    // package.json
    
    {
      "scripts": {
        "dev": "export NODE_ENV=development && node server/index.mjs",  
       }
    }
    
    ------------
    
    $ yarn dev
    command not found: export

     

    yarn classic에서는 정상적으로 동작하던 export 명령어가, yarn berry에서 동작하지 않는 이유가 무엇일까?

    export 명령어는 온전히 OS 인터페이스 명령어이기 때문에, yarn classic 환경에서 package.json 내 선언된 script로 export 명령어를 수행한다면 그냥 일반적인 CLI로 동작하는 것이므로 수행이 가능하다.

    그러나 yarn berry에서는 package.json 내 script가 yarn-3.2.3.cjs이라는 자바스크립트 파일로 동작하는 것이다.

    자바스크립트 파일 자체가 로컬 환경의 인터페이스를 통해 환경변수를 주입하는 행동은 할 수 없다. 그래서 애초에 인터페이스 명령어 자체가 없는 것이고 export라는 커맨드가 없는 것이다.

     

    Yarn berry 환경인 디렉토리에서 그냥 터미널에서 export 명령어로 환경변수를 주입해보라. 이는 yarn-3.2.3.cjs파일 위에서 돌아간 명령어가 아니라 그냥 터미널에서 CLI로 돌린 명령어 이기 때문에 정상적으로 동작할 것이다.

    그러나 package.json 내에 정의한 script에서 export 명령어를 수행하려고 하면 command not found가 뜬다. 

    이게 바로 Yarn berry 환경에서 수행되는 Yarn 명령어는 모두 yarn-3.2.3.cjs 이라는 자바스크립트 파일에서 동작한다는 증거이다.

     

    그러면 여기서 우리는 의문이 하나 생길 수 있다.

    일반적으로 브라우저가 아닌 로컬 환경에서 JS 파일을 실행시키려면 Node 명령어로 수행을 해야하는데, 이 yarn-3.2.3.cjs라는 자바스크립트 파일을 실행시키는 주최자가 있어야 하지 않을까?

    그냥 Yarn 명령어를 수행하면 yarn-3.2.3.cjs가 동작한다? 어딘가에 유저가 커맨드로 Yarn 명령어를 치면 yarn.3.2.3.cjs를 동작시키라고 명시가 되어 있는 것일까?


    그러면 yarn-3.2.3.cjs를 동작시키는 이 Yarn 명령어는 또 누구일까?

     

    Yarn Berry는 Yarn Classic 환경 위에서 동작한다.

    바로 이 자바스크립트 파일을 수행하는 친구가 우리 로컬 환경 자체에 CLI로 동작하는 Yarn Classic인 것이다.

    Yarn Berry 환경에서 우리가 터미널에서 수행한 yarn 커맨드는 사실은 yarn  berry가 아니라 무조건 yarn classic인 것이고, Yarn  Classic이 yarn Berry 환경인지 파악 후 yarn.3.2.3.cjs 파일을 실행시키는 것이다.

    따라서, 어딘가에 yarn Berry 환경을 세팅했다고 해서 기존의 yarn Classic 시스템 자체가 Yarn Berry로 변경되는 것이 아니라, Yarn Classic 위에 Yarn Berry라는 구조가 하나 더 생기면서 동작하는 것이라 할 수 있겠다.

     

    이를 확인해보기 위해, Yarn Berry로 세팅된 환경과 이외에 다른 디렉토리에서 각각 Yarn version을 확인해보자.

    처음 yarn --version 은 Berry로 세팅된 환경이기 때문에 3.2.3으로 나오지만, 다른 디렉터리로 벗어나자마자 바로 1.xx 버전대로 나오는 것을 확인할 수 있다.

     

    그러나 이러한 동작 방식으로 인해, Yarn Berry에서 다른 패키지들을 동작시킬 때 의도치 않게 Berry를 통해 수행되지 않아 정상적으로 동작하지 않는 이슈가 발생할 수도 있다.

    이를 위해서 Yarn에서는 yarn dlx라는 커맨드를 통해 임시 환경 위에서 패키지를 수행할 수 있는 기능을 제공한다.

    $ yarn dlx <command>

     

     

    `yarn dlx`

    Run a package in a temporary environment.

    yarnpkg.com

     

    나 역시 이러한 문제로 인해 어려움을 겪었던 문제가 있었어서, 이를 공유해 보려고 한다.

    yarn classic에서 yarn berry로 마이그레이션을 하면서, docker Linux 환경에서 cypress를 아래처럼 실행시키려고 했었다.

    FROM cypress/included:10.2.0 as runner
    
    ...
    
    RUN cypress run ...

    그리고 현재 프로젝트 내 모든 패키지들은 pnp을 통해 프로젝트 내 .yarn/ 디렉토리 내 zip 파일로 관리되는 중이었다.

    docker cypress Linux 환경에서 그냥 Cypress를 수행하려고 하니 Cypress와 Cypress 내 사용되는 모든 모듈들이 Can not found modules 에러가 발생하는 것이었다.

     

    원인은, 모든 모듈들이 yarn berry 환경의 pnp를 통해 zip으로 관리되고 있으므로 yarn berry를 통해 모듈을 접근해야 하는데, 현재 우리가 실행한 cypress는 그냥 yarn classic으로 수행되었기 때문이다. yarn classic에는 zip 파일을 접근하는 pnp 기능이 없고 무조건 node_modules를 통해서만 가져올 수 있으므로 모듈을 찾을 수 없는 것이다.

    따라서 아래처럼 yarn berry의 임시 환경을 통해 실행해줌으로써 정상적으로 동작하도록 해결할 수 있었다.

    FROM cypress/included:10.2.0 as runner
    
    ...
    
    RUN yarn dlx cypress run ...

     

    정리하며

    위 내용들을 정리하면 아래와 같다.

    - Yarn Berry는 단순 자바스크립트 파일로 이루어진 환경이다.
    - Yarn Berry는 Yarn Classic 환경 위에서 동작한다.

    이를 통해 Yarn Berry라는 환경에 대해 조금 더 이해도가 높아진 것 같다.

    반응형

    댓글

Designed by Tistory.