태그
목차

내부 패키지

생성일: 2024-07-11

수정일: 2024-07-11

내부 패키지는 프로젝트 내부에서 직접 만들어 사용하는 라이브러리 패키지다.

모노레포 내에서 코드를 공유하기 위해 빠르게 내부 패키지를 만들 수 있으며, 필요한 경우 나중에 npm 레지스트리에 배포할 수 있다.

내부 패키지는 npm 레지스트리에서 설치하는 외부 패키지와 유사하게 package.json 에 설치하여 사용한다.

그러나 특정 버전을 설치하는 대신 패키지 관리자가 제공하는 워크스페이스 기능을 사용해서 설치한다.

예를 들어:

// ./apps/web/package.json
{
  "dependencies": {
    "@repo/ui": "*"
  }
}
// ./apps/web/package.json
{
  "dependencies": {
    "@repo/ui": "*"
  }
}
// ./apps/web/package.json
{
  "dependencies": {
    "@repo/ui": "workspace:*"
  }
}

그런 다음 외부 패키지와 마찬가지로 코드에서 패키지를 가져와 사용할 수 있다:

import { Button } from '@repo/ui';

export default function Page() {
  return <Button>Submit</Button>;
}

내부 패키지를 만드는 여러 전략과 트레이드오프가 있으며, 필요한 경우 npm 레지스트리에 배포하여 외부 패키지로 만들 수도 있다.

컴파일 전략

라이브러리의 용도와 목적에 땨라 다음 세 가지 컴파일 전략 중 하나를 선택할 수 있다:

Just-in-Time 컴파일 패키지

JIT 컴파일 패키지는 해당 패키지를 사용하는 애플리케이션에 의해 컴파일된다.

TypeScript(또는 JavaScript) 파일을 그대로 사용할 수 있어, 다른 전략들보다 설정이 간편하다.

이 전략은 다음과 같은 경우에 가장 유용하다:

JIT 컴파일 패키지의 package.json 은 다음과 같은 형태다:

// ./packages/ui/package.json
{
  "name": "@repo/ui",
  "exports": {
    "./button": "./src/button.tsx",
    "./card": "./src/card.tsx"
  },
  "scripts": {
    "lint": "eslint . --max-warnings 0",
    "check-types": "tsc --noEmit"
  }
}

여기서 중요한 점은 다음과 같다:

제한사항 및 트레이드오프

컴파일된 패키지

컴파일된 패키지는 tsc 와 같은 빌드 도구를 사용하여 자체적으로 컴파일을 처리하는 패키지다.

// ./packages/ui/package.json
{
  "name": "@repo/ui",
  "exports": {
    "./button": {
      "types": "./src/button.tsx",
      "default": "./dist/button.js"
    },
    "./card": {
      "types": "./src/card.tsx",
      "default": "./dist/card.js"
    }
  },
  "scripts": {
    "build": "tsc"
  }
}

라이브러리를 컴파일하면 컴파일된 JavaScript 출력물이 디렉토리(dist, build 등)에 생성되며, 이를 패키지의 진입점으로 사용한다.

빌드 출력물은 Turborepo에 의해 캐시되어 빌드 시간을 단축할 수 있다.

제한사항 및 트레이드오프

TypeScript 컴파일러를 사용해야 하는 이유

대부분의 경우 tsc 를 사용하여 TypeScript 코드를 JavaScript로 변환한다. 이는 간단하고 직접적인 방법이다.

  • 보통 라이브러리를 만들 때는 번들러(예: webpack)를 사용하지 않는다.
    • 라이브러리를 사용하는 애플리케이션에서 이미 번들러를 사용하고 있기 때문이다.
    • 애플리케이션의 번들러는 다음과 같은 작업을 수행 한다:
      • 라이브러리 코드를 애플리케이션에 통합
      • 필요한 폴리필 추가 (오래된 브라우저 지원)
      • 코드를 더 낮은 JavaScript 버전으로 변환 (다운레벨링)
      • 기타 최적화 작업
  • 번들러를 사용하는 경우
    • 특별한 경우에만 라이브러리에서 번들러를 사용한다.
    • 예: 이미지나 CSS 같은 정적 파일을 라이브러리에 포함시켜야 할 때

정리해 보면, 라이브러리를 만들 때는 보통 간단한 TypeScript 컴파일러만 사용하고, 복잡한 처리는 라이브러리를 사용하는 애플리케이션의 번들러에게 맡긴다. 이렇게 하면 라이브러리를 더 쉽게 만들고 유지보수할 수 있다.

배포 가능한 패키지

npm 레지스트리에 패키지를 배포하는 것은 이 페이지에서 소개한 패키징 전략들 중 가장 엄격한 요구사항을 갖는다.

소비자들이 어떻게 패키지를 사용할지 알 수 없기 때문에, 수많은 설정이 필요하다.

또한, npm 레지스트리에 패키지를 배포하는 과정은 전문적인 지식과 도구를 필요로 한다.

버전 관리, 변경 로그 작성, 그리고 배포 과정을 관리하기 위해 changesets 를 사용하는 것을 추천한다.

Note

자세한 내용은 패키지 배포하기 가이드를 참조한다.