hygen을 이용하여 반복적인 코드 생성을 자동화 하기

woori kim·2023년 6월 19일
0

프로젝트에서는 각 컴포넌트마다 component.tsx, index.ts, component.test.tsx, button.stories.tsx, style.module.css` ****와 같이 5가지 파일을 생성하여 관리하고 있습니다. 이러한 파일들은 컴포넌트마다 반복적으로 만들어져야 하고, 기본 형식은 동일하기 때문에 Hygen을 사용하여 템플릿화하고 반복적인 파일 생성 작업을 자동화할 수 있습니다. 이를 통해 파일 생성 및 코드 작성 작업에서 반복되는 항목을 복사 및 붙여넣기하지 않고도 효율적으로 처리할 수 있습니다.

└── atoms
    └── Button
        ├── Button.stories.tsx
        ├── Button.test.tsx
        ├── Button.tsx
        ├── index.tsx
        └── style.module.css

hygen

여기서 코드 생성 자동화에 사용되는 hygen에 대해 간략하게 설명해보도록 하겟습니다.

Hygen은 코드 생성 도구로서, 프로젝트에서 반복적으로 수행되는 작업이나 템플릿 기반의 코드 생성을 자동화하는 데 사용됩니다. 특히, 반복적인 작업이나 코드 작성 작업의 생산성을 향상시킬 수 있습니다.

Hygen은 코드를 생성하기 위한 템플릿과 프롬프트로 구성된 작업을 통해, 사용자가 인터랙티브하게 대화 형식으로 입력을 제공할 수 있도록 합니다. 이를 통해 템플릿에서 정의된 코드의 구조와 내용을 기반으로, 프롬프트에서 입력받은 값들을 활용하여 동적으로 코드를 생성할 수 있습니다.

hygen 사용방법

  1. Hygen 설치: 프로젝트 디렉토리에서 npm install -g hygen 명령을 사용하여 전역으로 Hygen을 설치

  2. **npm hygen init self** 을 사용하여 자체적으로 초기화하는 작업을 수행

    1. 초기화 이후 디렉토리는 하기와 같이 생성이 됩니다.
    _templates/
    ├── generator
    │   ├── help
    │   │   └── index.ejs.t
    │   ├── new
    │   │   └── hello.ejs.t
    │   └── with-prompt
    │       ├── hello.ejs.t
    │       └── prompt.ejs.t
    └── init
        └── repo
            └── new-repo.ejs.t
  3. 새로운 코맨드 생성 ex) **npm hygen generator new component**

    1. 생성후 디렉토리구조
    _templates/
    ├── component
    │   └── new
    │       └── hello.ejs.t
    ├── generator
    │   ├── help
    │   │   └── index.ejs.t
    │   ├── new
    │   │   └── hello.ejs.t
    │   └── with-prompt
    │       ├── hello.ejs.t
    │       └── prompt.ejs.t
    └── init
        └── repo
            └── new-repo.ejs.t
  4. 템플릿 생성: 각 파일에 대한 템플릿을 생성

    1. . 템플릿은 생성할 파일의 구조와 내용을 정의하는 파일로 일반적으로 프로젝트 내의 _templates 디렉토리에 저장됩니다. 각 템플릿 파일에는 파일 생성 위치, 파일명, 코드 내용 등이 정의되어 있어야 합니다.
    2. index.html, component.tsx, component.storybook.tsx 의 파일을 생성한다고 가정
    _templates/
    ├── component
    │   └── new
    │       └── component.stories.tsx.ejs.t
    │				└── component.tsx.ejs.t
    │				└── index.html.ejs.t
    ├── generator
    │   ├── help
    │   │   └── index.ejs.t
    │   ├── new
    │   │   └── hello.ejs.t
    │   └── with-prompt
    │       ├── hello.ejs.t
    │       └── prompt.ejs.t
    └── init
        └── repo
            └── new-repo.ejs.t
  5. 프롬프트 정의: 파일 생성에 필요한 입력 값을 받을 프롬프트를 정의해야 합니다. 프롬프트는 사용자로부터 값을 입력받거나 선택할 수 있는 질문의 형태입니다. 입력된 값은 템플릿에서 사용되어 동적으로 코드를 생성합니다.

    _templates/
    ├── component
    │   └── new
    │       └── component.stories.tsx.ejs.t
    │				└── component.tsx.ejs.t
    │				└── index.html.ejs.t
    │				└── prompt.cjs
    ├── generator
    │   ├── help
    │   │   └── index.ejs.t
    │   ├── new
    │   │   └── hello.ejs.t
    │   └── with-prompt
    │       ├── hello.ejs.t
    │       └── prompt.ejs.t
    └── init
        └── repo
            └── new-repo.ejs.t
  6. 코드 생성: 프롬프트와 템플릿이 정의되었다면, Hygen을 사용하여 코드를 생성할 수 있습니다. 프로젝트 디렉토리에서 **hygen component new** 명령을 실행하고, 사용할 템플릿과 프롬프트를 선택합니다. 입력된 값에 따라 코드가 생성됩니다.

    npm run new
    
    > hygen-sample@1.2.2 new
    > hygen component new
    
    // 카테고리선택
    ? AWhich Atomic Design category?  … 
    ❯ atoms
      molecules
      organisms
      templates
    
    // 선택이후
    ✔ AWhich Atomic Design category?  · atoms
    ✔ What is the name of component?  · button
    ✔ Please select the directory within src/components/${category}. · 
    
    Loaded templates: _templates
           added: src/components/atoms/button/button.stories.tsx
           added: src/components/atoms/button/button.tsx
           added: src/components/atoms/button/index.tsx

프롬포트와 템플릿

프롬프토

hygen 템플릿에서 **prompt.cjs**를 사용하는 경우, 해당 템플릿은 사용자로부터 콘솔 입력을 받아 템플릿을 동적으로 생성하거나 조작할 수 있습니다. 예를 들어, 사용자가 입력한 정보에 따라 다양한 텍스트, 파일 또는 폴더를 생성할 수 있습니다. 또한, prompt.cjs 모듈을 사용하여 사용자 입력을 처리하는 방법을 변경하면, 템플릿이 생성하는 결과물도 다양하게 바뀔 수 있습니다. 이를 통해 템플릿이 생성하는 결과물의 다양성과 유연성을 높일 수 있습니다.

module.exports = {
  prompt: ({ inquirer, args }) => {
    const questions = [
      {
        type: 'select',
        name: 'category',
        message: 'AWhich Atomic Design category? ',
        choices: ['atoms', 'molecules', 'organisms', 'templates']
      },
      {
        type: 'input',
        name: 'component_name',
        message: 'What is the name of component? '
      },
      {
        type: 'input',
        name: 'dir',
        message: 'Please select the directory within src/components/${category}.',
      },
    ]
    return inquirer
      .prompt(questions)
      .then(answers => {
        const { category, component_name, dir } = answers
        const path = `${category}/${ dir ? `${dir}/` : `` }${component_name}`
        const abs_path = `src/components/${path}`
        const tag = args.tag ? args.tag : 'div'
        const upperSingleCategory = category.charAt(0).toUpperCase() + category.slice(1, -1)
        return { ...answers, path, abs_path, tag,
          upperTag: tag.charAt(0).toUpperCase() + tag.slice(1),
          upperSingleCategory
        }
      })
  }
}

상기 prompt 에서는 하기와 같은 작업을 수행합니다.

  1. inquirerargs 매개변수
    1. 매개변수들은 inquirer 모듈과 추가적인 인자들을 전달하기 위해 사용됩니다.
  2. questions라는 배열을 정의
    1. 배열은 사용자에게 보여질 질문들로 각 질문은 다양한 유형(type)과 이름(name), 메시지(message), 선택지(choices) 등의 속성을 가지고 있습니다.
  3. inquirer.prompt(questions)를 호출하여 사용자로부터 질문에 대한 답변을 받습니다. 이를 통해 사용자의 입력을 처리하고 결과를 얻을 수 있습니다.
  4. then() 메서드를 사용하여 사용자의 답변을 처리합니다. 답변 객체(answers)에서 category, component_name, dir 등의 속성을 추출하여 사용합니다. 이를 기반으로 템플릿을 구성하는데 필요한 다양한 변수들을 계산합니다.
  5. 계산된 변수들과 함께 결과 객체를 반환합니다. 이 객체는 path, abs_path, tag, upperSingleCategory 등의 속성을 가지고 있습니다. 이 속성들은 템플릿에서 사용될 수 있는 값들입니다.

template

---
to: <%= abs_path %>/index.tsx
---
export * from './<%= component_name %>'

위의 코드에서 to: <%= abs_path %>/index.tsx는 생성되는 파일의 경로를 나타내고있습니다. <%= abs_path %>는 템플릿에서 계산된 절대 경로를 나타내며, /index.tsx는 생성되는 파일의 이름과 확장자를 정의합니다.

예를 들어 src/components/atoms/Button/index.tsx 와 같은 형식으로 파일이 생성됩니다.

주의점은 상단에 공백이 존재해서는 안되고 공백이 있는 경우 파일이 생성되지않는 문제가 발생합니다.

hygen에 대한 자세한 설명은 공식 사이트에서 확인 가능합니다.

Hygen | Hygen

제가 만든 간략한 샘플코드는 하기 링크에서 확인 가능합니다.

https://github.com/woori3104/hygen-sample

0개의 댓글