콘텐츠로 이동

Nx 생성기 생성기

TypeScript 프로젝트에 Nx Generator를 추가하여 컴포넌트 스캐폴딩이나 특정 프로젝트 구조 강제화와 같은 반복 작업을 자동화할 수 있도록 도와줍니다.

다음 두 가지 방법으로 제너레이터를 생성할 수 있습니다:

  1. 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
  2. VSCode에서 Nx 콘솔 열기
  3. 클릭 Generate (UI) "Common Nx Commands" 섹션에서
  4. 검색 @aws/nx-plugin - ts#nx-generator
  5. 필수 매개변수 입력
    • 클릭 Generate
    매개변수 타입 기본값 설명
    project 필수 string - TypeScript project to add the generator to. We recommend using the ts#nx-plugin generator to create this.
    name 필수 string - Generator name
    description string - A description of your generator
    directory string - The directory within the plugin project's source folder to add the generator to (default: <name>)

    지정한 project 내에 다음 프로젝트 파일들이 생성됩니다:

    • 디렉터리src/<name>/
      • schema.json 제너레이터 입력을 위한 스키마
      • schema.d.ts 스키마의 TypeScript 타입
      • generator.ts 제너레이터 구현 스텁
      • generator.spec.ts 제너레이터 테스트
      • README.md 제너레이터 문서
    • generators.json 제너레이터 정의를 위한 Nx 설정
    • package.json “generators” 항목이 추가되거나 업데이트됨
    • tsconfig.json CommonJS 사용으로 업데이트됨

    현재 Nx 제너레이터는 CommonJS만 지원하므로(ESM 지원 관련 GitHub 이슈 참조), 이 제너레이터는 선택한 project를 CommonJS 사용으로 업데이트합니다.

    ts#nx-generator 제너레이터 실행 시 로컬 nx-plugin 프로젝트를 선택하고 이름, 선택적 디렉토리 및 설명을 지정하세요.

    schema.json 파일은 제너레이터가 수락하는 옵션들을 정의합니다. 이 파일은 Nx 확장 기능이 추가된 JSON Schema 형식을 따릅니다.

    schema.json 파일의 기본 구조는 다음과 같습니다:

    {
    "$schema": "https://json-schema.org/schema",
    "$id": "YourGeneratorName",
    "title": "Your Generator Title",
    "description": "Description of what your generator does",
    "type": "object",
    "properties": {
    // 제너레이터 옵션들이 위치합니다
    },
    "required": ["requiredOption1", "requiredOption2"]
    }

    기본 옵션들을 포함한 간단한 예제:

    {
    "$schema": "https://json-schema.org/schema",
    "$id": "ComponentGenerator",
    "title": "Create a Component",
    "description": "Creates a new React component",
    "type": "object",
    "properties": {
    "name": {
    "type": "string",
    "description": "Component name",
    "x-priority": "important"
    },
    "directory": {
    "type": "string",
    "description": "Directory where the component will be created",
    "default": "src/components"
    },
    "withTests": {
    "type": "boolean",
    "description": "Whether to generate test files",
    "default": true
    }
    },
    "required": ["name"]
    }

    CLI에서 제너레이터 실행 시 표시되는 프롬프트를 커스터마이즈하려면 x-prompt 속성을 추가하세요:

    "name": {
    "type": "string",
    "description": "Component name",
    "x-prompt": "What is the name of your component?"
    }

    불리언 옵션의 경우 yes/no 프롬프트 사용 가능:

    "withTests": {
    "type": "boolean",
    "description": "Whether to generate test files",
    "x-prompt": "Would you like to generate test files?"
    }

    고정된 선택지 세트가 있는 옵션의 경우 enum을 사용하여 사용자가 옵션 중 하나를 선택할 수 있도록 합니다:

    "style": {
    "type": "string",
    "description": "The styling approach to use",
    "enum": ["css", "scss", "styled-components", "none"],
    "default": "css"
    }

    워크스페이스의 기존 프로젝트 목록에서 선택할 수 있도록 하는 일반적인 패턴:

    "project": {
    "type": "string",
    "description": "The project to add the component to",
    "x-prompt": "Which project would you like to add the component to?",
    "x-dropdown": "projects"
    }

    x-dropdown: "projects" 속성은 Nx에게 드롭다운을 워크스페이스의 모든 프로젝트로 채우도록 지시합니다.

    명령줄에서 제너레이터 실행 시 위치 인수로 옵션을 전달하도록 구성할 수 있습니다:

    "name": {
    "type": "string",
    "description": "Component name",
    "x-priority": "important",
    "$default": {
    "$source": "argv",
    "index": 0
    }
    }

    이를 통해 사용자는 nx g your-generator --name=my-component 대신 nx g your-generator my-component처럼 실행할 수 있습니다.

    x-priority 속성을 사용하여 중요한 옵션을 표시합니다:

    "name": {
    "type": "string",
    "description": "Component name",
    "x-priority": "important"
    }

    옵션은 "important" 또는 "internal" 우선순위를 가질 수 있습니다. 이는 Nx VSCode 확장과 Nx CLI에서 속성 순서를 조정하는 데 도움이 됩니다.

    옵션에 기본값을 제공할 수 있습니다:

    "directory": {
    "type": "string",
    "description": "Directory where the component will be created",
    "default": "src/components"
    }

    스키마에 대한 자세한 내용은 Nx Generator Options 문서를 참조하세요.

    schema.json과 함께 생성되는 schema.d.ts 파일은 제너레이터 옵션에 대한 TypeScript 타입을 제공합니다:

    export interface YourGeneratorSchema {
    name: string;
    directory?: string;
    withTests?: boolean;
    }

    이 인터페이스는 타입 안전성과 코드 완성을 위해 제너레이터 구현에서 사용됩니다:

    import { YourGeneratorSchema } from './schema';
    export default async function (tree: Tree, options: YourGeneratorSchema) {
    // TypeScript가 모든 옵션의 타입을 인지합니다
    const { name, directory = 'src/components', withTests = true } = options;
    // ...
    }

    위 단계로 새 제너레이터를 생성한 후 generator.ts에 구현 코드를 작성할 수 있습니다.

    제너레이터는 가상 파일 시스템(Tree)을 변형하는 함수로, 원하는 변경 사항을 적용하기 위해 파일을 읽고 씁니다. Tree의 변경 사항은 “dry-run” 모드가 아닌 경우 제너레이터 실행 완료 시 디스크에 기록됩니다. 빈 제너레이터는 다음과 같습니다:

    export const myGenerator = async (tree: Tree, options: MyGeneratorSchema) => {
    // 트리를 사용하여 변경 사항 적용
    };
    export default myGenerator;

    제너레이터에서 수행할 수 있는 일반적인 작업 예시:

    // 파일 읽기
    const content = tree.read('path/to/file.ts', 'utf-8');
    // 파일 쓰기
    tree.write('path/to/new-file.ts', 'export const hello = "world";');
    // 파일 존재 여부 확인
    if (tree.exists('path/to/file.ts')) {
    // 작업 수행
    }

    @nx/devkitgenerateFiles 유틸리티를 사용하여 EJS 템플릿으로 파일을 생성할 수 있습니다.

    import { generateFiles, joinPathFragments } from '@nx/devkit';
    // 템플릿에서 파일 생성
    generateFiles(
    tree,
    joinPathFragments(__dirname, 'files'), // 템플릿 디렉토리
    'path/to/output', // 출력 디렉토리
    {
    // 템플릿에서 치환할 변수들
    name: options.name,
    nameCamelCase: camelCase(options.name),
    nameKebabCase: kebabCase(options.name),
    // 필요에 따라 추가 변수 정의
    },
    );

    AWS용 Nx 플러그인이 제공하는 tsAstReplace 메서드를 사용하여 TypeScript 추상 구문 트리의 일부를 교체할 수 있습니다.

    import { tsAstReplace } from '@aws/nx-plugin/sdk/utils/ast';
    import * as ts from 'typescript';
    // 예시: 파일 내 버전 번호 증가
    tsAstReplace(
    tree,
    'path/to/version.ts',
    'VariableDeclaration:has(Identifier[name="VERSION"]) NumericLiteral',
    (node: ts.NumericLiteral) =>
    ts.factory.createNumericLiteral(Number(node.text) + 1));
    import { addDependenciesToPackageJson } from '@nx/devkit';
    // package.json에 의존성 추가
    addDependenciesToPackageJson(
    tree,
    {
    'new-dependency': '^1.0.0',
    },
    {
    'new-dev-dependency': '^2.0.0',
    },
    );
    import { formatFilesInSubtree } from '@aws/nx-plugin/sdk/utils/format';
    // 수정된 모든 파일 포맷팅
    await formatFilesInSubtree(tree, 'optional/path/to/format');
    import { readJson, updateJson } from '@nx/devkit';
    // JSON 파일 읽기
    const packageJson = readJson(tree, 'package.json');
    // JSON 파일 업데이트
    updateJson(tree, 'tsconfig.json', (json) => {
    json.compilerOptions = {
    ...json.compilerOptions,
    strict: true,
    };
    return json;
    });

    AWS용 Nx 플러그인의 제너레이터 확장

    섹션 제목: “AWS용 Nx 플러그인의 제너레이터 확장”

    AWS용 Nx 플러그인의 제너레이터를 임포트하여 확장하거나 조합할 수 있습니다. 예를 들어 TypeScript 프로젝트를 기반으로 제너레이터를 생성할 수 있습니다:

    import { tsProjectGenerator } from '@aws/nx-plugin/sdk/ts';
    export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => {
    const callback = await tsProjectGenerator(tree, { ... });
    // TypeScript 프로젝트 제너레이터 확장
    // 의존성 설치를 보장하기 위해 콜백 반환
    // 추가 작업을 수행하려면 콜백을 래핑할 수 있음
    return callback;
    };

    TypeScript 클라이언트 및 훅에 사용하는 제너레이터를 비슷한 방식으로 사용하고 확장할 수 있습니다:

    import { openApiTsClientGenerator } from '@aws/nx-plugin/sdk/open-api';
    export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => {
    await openApiTsClientGenerator(tree, { ... });
    // 추가 파일 생성
    };

    OpenAPI 명세의 작업을 반복 처리할 수 있는 데이터 구조를 구축하는 메서드도 제공합니다:

    import { buildOpenApiCodeGenerationData } from '@aws/nx-plugin/sdk/open-api.js';
    export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => {
    const data = await buildOpenApiCodeGenerationData(tree, 'path/to/spec.json');
    generateFiles(
    tree,
    joinPathFragments(__dirname, 'files'), // 템플릿 디렉토리
    'path/to/output', // 출력 디렉토리
    data,
    );
    };

    이를 통해 다음과 같은 템플릿 작성이 가능합니다:

    files/my-operations.ts.template
    export const myOperationNames = [
    <%_ allOperations.forEach((op) => { _%>
    '<%- op.name %>',
    <%_ }); _%>
    ];

    더 복잡한 예제 템플릿은 GitHub의 코드베이스를 참조하세요.

    두 가지 방법으로 제너레이터를 실행할 수 있습니다:

    1. 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
    2. VSCode에서 Nx 콘솔 열기
    3. 클릭 Generate (UI) "Common Nx Commands" 섹션에서
    4. 검색 @my-project/nx-plugin - my-generator
    5. 필수 매개변수 입력
      • 클릭 Generate

      제너레이터 단위 테스트는 간단하게 구현할 수 있습니다. 일반적인 패턴 예시:

      import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
      import { yourGenerator } from './generator';
      describe('your generator', () => {
      let tree;
      beforeEach(() => {
      // 빈 워크스페이스 트리 생성
      tree = createTreeWithEmptyWorkspace();
      // 트리에 사전 존재해야 하는 파일 추가
      tree.write(
      'project.json',
      JSON.stringify({
      name: 'test-project',
      sourceRoot: 'src',
      }),
      );
      tree.write('src/existing-file.ts', 'export const existing = true;');
      });
      it('should generate expected files', async () => {
      // 제너레이터 실행
      await yourGenerator(tree, {
      name: 'test',
      // 기타 필수 옵션 추가
      });
      // 파일 생성 확인
      expect(tree.exists('src/test/file.ts')).toBeTruthy();
      // 파일 내용 확인
      const content = tree.read('src/test/file.ts', 'utf-8');
      expect(content).toContain('export const test');
      // 스냅샷 사용 가능
      expect(tree.read('src/test/file.ts', 'utf-8')).toMatchSnapshot();
      });
      it('should update existing files', async () => {
      // 제너레이터 실행
      await yourGenerator(tree, {
      name: 'test',
      // 기타 필수 옵션 추가
      });
      // 기존 파일 업데이트 확인
      const content = tree.read('src/existing-file.ts', 'utf-8');
      expect(content).toContain('import { test } from');
      });
      it('should handle errors', async () => {
      // 특정 조건에서 제너레이터가 오류를 발생시키는지 확인
      await expect(
      yourGenerator(tree, {
      name: 'invalid',
      // 오류를 유발하는 옵션 추가
      }),
      ).rejects.toThrow('Expected error message');
      });
      });

      제너레이터 테스트 핵심 포인트:

      • createTreeWithEmptyWorkspace()로 가상 파일 시스템 생성
      • 제너레이터 실행 전 필수 파일 설정
      • 새 파일 생성과 기존 파일 업데이트 모두 테스트
      • 복잡한 파일 내용에 스냅샷 사용
      • 오류 조건 테스트로 제너레이터의 정상 실패 확인

      @aws/nx-plugin에 제너레이터 기여하기

      섹션 제목: “@aws/nx-plugin에 제너레이터 기여하기”

      ts#nx-generator를 사용하여 @aws/nx-plugin 내부에 제너레이터 스캐폴딩도 가능합니다.

      이 제너레이터를 저장소에서 실행하면 다음 파일들이 생성됩니다:

      • 디렉터리packages/nx-plugin/src/<name>/
        • schema.json 입력 스키마
        • schema.d.ts TypeScript 타입
        • generator.ts 제너레이터 구현
        • generator.spec.ts 테스트
      • 디렉터리docs/src/content/docs/guides/
        • <name>.mdx 제너레이터 문서 페이지
      • packages/nx-plugin/generators.json 제너레이터 포함되도록 업데이트

      이후 제너레이터 구현을 시작할 수 있습니다.