Frontend

Turborepo 도입하면서 겪었던 이슈들

mechaniccoder 2022. 11. 14. 00:05

안녕하세요. 이번 시간에는 최근 Turborepo를 회사에 도입하며 겪었던 이슈들 그리고 앞으로 이를 더 잘 사용하기 위해 어떻게 해야할 지에 대한 내용을 공유해보겠습니다.

왜 Turborepo일까?

모노레포를 구성하기 위한 여러 도구들이 있는데 왜 Turborepo를 선택했을까요? 그건 현재 Frontend의 인프라 대부분이 Vercel에 있기 때문입니다. 최근 Vercel이 Turborepo를 인수하기도 했고 실제로 배포할때 Turborepo에 대한 지원이 잘 되어있기 때문이죠.

React Framework인 Next.js 발전과 함께 Vercel을 Frontend의 인프라로 사용하는 분위기가 강해졌다는 생각이 드네요. 실제로 lerna와 비교했을때 turborepo의 인기가 점점 더 치고 올라가는 것을 확인할 수 있습니다.

Turborepo를 사용하며 겪었던 이슈들

transpiling을 위한 webpack configuration

여러 app에서 사용되고 있는 코드들을 npm에 배포는 하지 않고 internal package로서 사용했습니다. 하지만 이를 사용하고 있는 app에서 이 package를 사용하지 못하더군요. 디버깅 결과 사용하는 app에서 typescript를 트랜스파일링하지 못하기 때문에 발생하는 이슈였습니다. 참고로 Next.js app에서는 이 문제가 발생하지 않습니다. next.config.ts를 확인해보면 이유를 알 수 있습니다.

next-transpile-modules이 package를 트랜스파일링해주기 때문에 문제없이 사용할 수 있었습니다.

const withTM = require('next-transpile-modules')['package1', 'package2']

module.exports = withTM({
  // next.js configuration
})

하지만 문제가 발생했던 것은 nest.js app과 storybook 환경이었습니다. 따라서 이를 위한 webpack 설정이 따로 필요했죠. 처음에는 package를 빌드하고 entry point를 빌드된 파일로 설정했는데 이는 좋은 방법은 아닌 것 같았습니다. 공식문서에도 나와 있는 내용이지만 이렇게 사용하는 경우는 package가 npm에 배포된 경우입니다. 저희는 internal package이기 때문에 typescript 파일을 entry point로 사용했었죠.

결론은 package를 사용하는 app에서 typescript를 트랜스파일링하기 위한 webpack 설정이 필요하다입니다.

Dependency Version Conflict

말 그래도 여러 workspace에서 같은 패키지이지만 다른 버전을 사용했을때 발생했던 이슈입니다. 조금 더 구체적으로 공유해드리자면 web3@^1.8.0 web3@1.7.1 사이에 발생했던 이슈였습니다.

아래 코드와 같이 contract 변수 타이핑을 web3-eth-contract에서 가져온 Contract로 했고 web3로 생성한 contract 인스턴스를 할당했습니다. 문제는 여기서 사용한 web3의 버전은 ^1.8.0이고 다른 workspace에서 web3@1.7.1을 설치하면서 같이 딸려온 web3-eth-contract의 버전이 1.7.1이여서 타이핑 이슈가 발생해 빌드가 계속 깨졌습니다.

import { Contract } from 'web3-eth-contract'
import Web3 from 'web3';

const web3 = new Web3(//...)
const contract: Contract = new web3.eth.Contract(//...) // typing error ㅠㅠ

왜 이런 문제가 발생하는 걸까요? 그건 node_modules에 중복된 패키지들을 없애기 위해 hoist되기 때문입니다. 자세한 내용은 nohoist in Workspaces를 참고해주세요.

web3@^1.8.0를 설치했지만 web3-eth-contract@^1.8.0이 아닌 web3@1.7.1의 dependency인 web3-eth-contract@1.7.1이 root로 hoist됐기 때문이죠.

이를 효율적으로 해결하기 위한 방법으로 pnpm의 도입을 생각하고 있습니다. npm, yarn과 다르게 hoist되지 않고 내가 설치한 패키지에만 접근할 수 있다는 점과 symlink를 활용해 정확한 버전의 dependency를 사용할 수 있는 점이 이 문제를 해결할 수 있다고 생각했고 PoC 결과 실제로도 그러했습니다. pnpm의 motivation에 대한 내용은 공식문서를 참고해주세요.

마치며

이번 포스팅에서는 Turborepo를 도입하며 겪었던 이슈들에 대해 간략히 공유해봤습니다. 아직 package와 app이 많지 않아서 운영에서 겪는 이슈들은 공유하지 못했는데요. 앞으로 monorepo를 프런트엔드 팀에 안정적으로 정착시키기 위한 과정에서 발생하는 이슈와 best practice에 대한 내용을 꾸준히 공유해보겠습니다.