콘텐츠로 이동

TypeScript 프로젝트

TypeScript 프로젝트 생성기는 ECMAScript Modules (ESM), TypeScript 프로젝트 참조, 테스트 실행을 위한 Vitest, 린팅 및 포매팅을 위한 Biome과 같은 모범 사례로 구성된 현대적인 TypeScript 라이브러리 또는 애플리케이션을 생성하는 데 사용할 수 있습니다.

두 가지 방법으로 새 TypeScript 프로젝트를 생성할 수 있습니다:

Terminal window
pnpm nx g @aws/nx-plugin:ts#project
어떤 파일이 변경될지 확인하기 위해 드라이 런을 수행할 수도 있습니다
Terminal window
pnpm nx g @aws/nx-plugin:ts#project --dry-run
매개변수타입기본값설명
name 필수string-TypeScript 프로젝트 이름
directory stringpackages라이브러리가 배치될 상위 디렉토리입니다.
subDirectory string-라이브러리가 배치될 하위 디렉토리입니다. 기본값은 라이브러리 이름입니다.
preferInstallDependencies booleantrue생성기 실행 후 의존성 설치를 선호할지 여부입니다. 여러 생성기를 일괄 처리할 때 설치를 연기하려면 false로 설정하세요 (후속 생성기가 Nx 프로젝트 그래프를 계산할 수 있도록 필요한 경우 설치는 여전히 실행됩니다); 마지막에 한 번만 설치합니다.

생성기는 <directory>/<name> 디렉토리에 다음과 같은 프로젝트 구조를 생성합니다:

  • 디렉터리src TypeScript 소스 코드
    • index.ts
  • package.json 프로젝트의 패키지 이름과 의존성을 정의하는 프로젝트 매니페스트
  • project.json 프로젝트 구성 및 빌드 타겟
  • tsconfig.json 이 프로젝트의 기본 TypeScript 구성 (워크스페이스 루트 tsconfig.base.json을 확장)
  • tsconfig.lib.json 라이브러리를 위한 TypeScript 구성 (런타임 또는 패키징된 소스)
  • tsconfig.spec.json 테스트를 위한 TypeScript 구성
  • vitest.config.mts Vitest 구성

워크스페이스 루트의 다음 파일에서도 일부 변경 사항을 확인할 수 있습니다:

  • nx.json Nx 구성이 업데이트되어 프로젝트에 대한 @nx/js/typescript 플러그인을 구성합니다
  • tsconfig.base.json 워크스페이스의 다른 프로젝트에서 가져올 수 있도록 프로젝트에 대한 TypeScript 별칭이 설정됩니다
  • tsconfig.json 프로젝트에 대한 TypeScript 프로젝트 참조가 추가됩니다

src 디렉토리에 TypeScript 코드를 추가하세요.

TypeScript 프로젝트가 ES Module이므로 파일 확장자를 명시적으로 참조하는 올바른 ESM 구문으로 import 문을 작성해야 합니다:

index.ts
import { sayHello } from './hello.js';

다른 TypeScript 프로젝트를 위한 내보내기

섹션 제목: “다른 TypeScript 프로젝트를 위한 내보내기”

TypeScript 프로젝트의 진입점은 src/index.ts입니다. 다른 프로젝트에서 가져올 수 있도록 하려는 모든 것을 여기에 내보낼 수 있습니다:

src/index.ts
export { sayHello } from './hello.js';
export * from './algorithms/index.js';

다른 프로젝트에서 라이브러리 코드 가져오기

섹션 제목: “다른 프로젝트에서 라이브러리 코드 가져오기”

프로젝트에 대한 TypeScript 별칭은 워크스페이스 tsconfig.base.json에 구성되어 있으며, 이를 통해 다른 TypeScript 프로젝트에서 TypeScript 프로젝트를 참조할 수 있습니다:

packages/my-other-project/src/index.ts
import { sayHello } from '@my-scope/my-library';

워크스페이스에서 새 프로젝트에 대한 import 문을 처음 추가하면 IDE에서 다음과 유사한 오류가 표시될 수 있습니다:

Import 오류
Terminal window
File '/path/to/my/workspace/packages/my-library/src/index.ts' is not under 'rootDir' '/path/to/my/workspace/packages/my-consumer'. 'rootDir' is expected to contain all source files.
File is ECMAScript module because '/path/to/my/workspace/package.json' has field "type" with value "module" ts(6059)
File '/path/to/my/workspace/packages/my-library/src/index.ts' is not listed within the file list of project '/path/to/my/workspace/packages/my-consumer/tsconfig.lib.json'. Projects must list all files or use an 'include' pattern.
File is ECMAScript module because '/path/to/my/workspace/package.json' has field "type" with value "module" ts(6307)

이는 프로젝트 참조가 아직 설정되지 않았고, 가져온 프로젝트가 프로젝트의 package.json에 워크스페이스 의존성으로 아직 선언되지 않았기 때문입니다.

워크스페이스는 두 가지를 모두 관리하는 동기화 생성기로 구성되어 있으므로 수동으로 구성할 필요가 없습니다. 다음 명령을 실행하기만 하면 Nx가 필요한 구성을 추가합니다:

Terminal window
pnpm nx sync
Terminal window
NX The workspace is out of sync
[@nx/js:typescript-sync]: Some TypeScript configuration files are missing project references to the projects they depend on, contain stale project references, or have duplicate project references.
[@aws/nx-plugin:ts#sync]: Local project dependencies are out of sync. The following workspace dependencies will be declared:
packages/my-other-project/package.json:
- @my-scope/my-library: workspace:*
Syncing the workspace...
The workspace was synced successfully!

Nx의 TypeScript 동기화 생성기는 프로젝트 참조를 추가하고, 플러그인의 ts#sync 생성기는 가져온 프로젝트를 프로젝트의 package.json에 선언하므로 (패키지 매니저가 워크스페이스 프로토콜을 지원하는 경우 workspace:*, npm 및 yarn classic에서는 *) 패키지 매니저가 설치 시 로컬 프로젝트를 연결합니다. 이후 IDE의 오류가 사라지고 라이브러리를 사용할 준비가 됩니다.

프로젝트의 tsconfig.json에 사용자 정의 compilerOptions.paths 항목을 추가하면 TypeScript는 tsconfig.base.json에 정의된 워크스페이스 별칭 상속을 중단합니다. 숨겨진 ts#sync 생성기는 compile 타겟 전에 실행되어 (nx.json에 구성됨) 이미 paths를 선언하는 tsconfig.json, tsconfig.lib.jsontsconfig.app.json 파일에 누락된 기본 별칭을 복사합니다. 옵트아웃하려면 nx.jsontargetDefaults.compile.syncGenerators에서 @aws/nx-plugin:ts#sync를 제거하세요.

각 TypeScript 프로젝트는 자체 package.json에 서드파티 런타임 의존성을 선언합니다. 프로젝트 간에 공유되는 빌드 및 테스트 도구는 루트 package.json에 정의됩니다.

프로젝트에 런타임 의존성을 추가하려면 해당 프로젝트에 설치하세요:

Terminal window
pnpm add some-npm-package --filter my-library

프로젝트 디렉토리 내에서 패키지 매니저의 일반 add/install 명령을 실행할 수도 있습니다.

공유 개발 도구를 추가하려면 워크스페이스 루트에 설치하세요:

Terminal window
pnpm add -Dw some-dev-tool

카탈로그를 지원하는 패키지 매니저(pnpm, yarnbun)의 경우, 생성기는 각 버전을 카탈로그에 기록하고 catalog: 프로토콜로 참조합니다 (예: "zod": "catalog:"). 따라서 어떤 프로젝트가 의존성을 선언하든 카탈로그가 버전의 단일 진실 공급원이 됩니다. 이는 단일 버전 정책을 따르는 데 도움이 되며, 타입 충돌과 배포 번들에서 패키지의 여러 복사본을 방지합니다.

새 의존성을 직접 추가할 때도 카탈로그에 유지하세요:

워크스페이스는 catalogMode: strict를 설정하므로 pnpm add는 버전을 카탈로그에 기록하고 자동으로 참조합니다 — 추가 단계가 필요 없습니다.

Terminal window
pnpm add some-npm-package --filter my-library

카탈로그는 기본적으로 활성화되어 있습니다. 비활성화하려면 --catalog false로 워크스페이스를 생성하세요:

Terminal window
pnpm create @aws/nx-workspace my-project --catalog false

또는 언제든지 aws-nx-plugin.config.mts에서 설정하세요:

aws-nx-plugin.config.mts
export default {
packageManager: {
catalogs: false,
},
} satisfies AwsNxPluginConfig;

카탈로그가 비활성화되면 생성기는 의존성 버전을 각 프로젝트의 package.json에 직접 작성하며, 프로젝트 간 버전 정렬을 유지하는 것은 사용자의 책임입니다.

모든 의존성을 루트 package.json에만 선언하는 것을 선호하는 경우 (프로젝트별 의존성 선언 없음), 워크스페이스 biome.json에서 린트 규칙을 비활성화하세요:

biome.json
{
"linter": {
"rules": {
"correctness": {
"noUndeclaredDependencies": "off"
}
}
}
}

프로젝트는 빌드 시 루트에 설치된 패키지를 해결하므로 모든 것이 여전히 빌드됩니다 — 각 프로젝트의 의존성에 대한 정확한 기록으로서 프로젝트별 매니페스트를 포기하게 됩니다 (나중에 프로젝트를 게시하거나 저장소를 분할하는 경우 중요함).

TypeScript 프로젝트를 런타임 코드로 사용하는 경우 (예: AWS Lambda 함수의 핸들러로), 프로젝트를 번들링하기 위해 Rolldown과 같은 도구를 사용하는 것이 좋습니다. 이는 트리 쉐이킹을 통해 프로젝트가 실제로 참조하는 의존성만 포함되도록 보장할 수 있기 때문입니다.

project.json 파일에 다음과 같은 타겟을 추가하여 이를 달성할 수 있습니다:

{
...
"targets": {
...
"bundle": {
"cache": true,
"executor": "nx:run-commands",
"outputs": ["{workspaceRoot}/dist/packages/my-library/bundle"],
"options": {
"command": "rolldown -c rolldown.config.ts"
}
},
},
}

그리고 다음과 같이 rolldown.config.ts 파일을 추가하세요:

rolldown.config.ts
import { defineConfig } from 'rolldown';
export default defineConfig([
{
input: 'src/index.ts',
output: {
file: '../../dist/packages/my-library/bundle/index.js',
format: 'cjs',
codeSplitting: false,
},
},
]);

TypeScript 프로젝트는 build 타겟으로 구성되어 있으며 (project.json에 정의됨), 다음을 통해 실행할 수 있습니다:

Terminal window
pnpm nx build <project-name>

여기서 <project-name>은 프로젝트의 정규화된 이름입니다.

build 타겟은 프로젝트를 컴파일, 린트 및 테스트합니다.

빌드 출력은 워크스페이스의 루트 dist 폴더에서 찾을 수 있으며, 패키지 및 타겟에 대한 디렉토리 내부에 있습니다. 예: dist/packages/<my-library>/tsc

워크스페이스의 모든 프로젝트를 빌드하려면 다음을 실행하세요:

Terminal window
pnpm nx run-many --target build

또는 단축 명령을 사용하세요:

Terminal window
pnpm build

Vitest가 프로젝트 테스트를 위해 구성되어 있습니다.

테스트는 프로젝트의 src 폴더에 함께 위치한 .spec.ts 또는 .test.ts 파일에 작성해야 합니다.

예를 들어:

  • 디렉터리src
    • hello.ts 라이브러리 소스 코드
    • hello.spec.ts hello.ts에 대한 테스트

Vitest는 describe, it, testexpect와 같은 유틸리티와 함께 Jest와 유사한 구문을 제공합니다.

hello.spec.ts
import { sayHello } from './hello.js';
describe('sayHello', () => {
it('should greet the caller', () => {
expect(sayHello('Darth Vader')).toBe('Hello, Darth Vader!');
});
});

테스트 작성 방법 및 의존성 모킹과 같은 기능에 대한 자세한 내용은 Vitest 문서를 참조하세요.

테스트는 프로젝트의 build 타겟의 일부로 실행되지만 test 타겟을 실행하여 별도로 실행할 수도 있습니다:

Terminal window
pnpm nx test <project-name>

Vitest의 -t 플래그를 사용하여 개별 테스트 또는 테스트 스위트를 실행할 수 있습니다. Nx가 자체 --target 옵션으로 사용하지 않고 Vitest로 전달하도록 -- 구분 기호 뒤에 전달하세요:

Terminal window
pnpm nx test <project-name> -- -t 'sayHello'

TypeScript 프로젝트는 린팅 및 포매팅을 위해 Biome를 사용합니다. Biome는 워크스페이스 루트 biome.json 파일에 구성되어 있으며 — 이에 대한 변경 사항은 워크스페이스의 모든 TypeScript 프로젝트에 적용되고 일관성을 보장합니다.

프로젝트를 확인하기 위해 린터를 호출하려면 lint 타겟을 실행할 수 있습니다.

Terminal window
pnpm nx lint <project-name>

대부분의 린팅 또는 포매팅 문제는 --configuration=fix 인수를 사용하여 실행하면 자동으로 수정할 수 있습니다.

Terminal window
pnpm nx lint <project-name> --configuration=fix

마찬가지로 워크스페이스의 모든 패키지에서 모든 린트 문제를 수정하려면 다음을 실행할 수 있습니다:

Terminal window
pnpm nx run-many --target lint --all --configuration=fix

개발 중에 린팅 문제로 인해 속도가 느려지는 것을 방지하려면 (특히 프로젝트에 자동 수정할 수 없는 문제가 있는 경우) skip-lint 구성으로 빌드를 실행할 수 있습니다:

Terminal window
pnpm nx run-many --target build --configuration=skip-lint

이렇게 하면 빌드 중에 린트 타겟을 완전히 건너뜁니다.