1. 코드 생성 자동화의 필요성
리액트 컴포넌트를 개발한다고 합시다. 컴포넌트의 이름을 정하고, index.tsx, index.module.scss, stories.tsx를 만듭니다.
그리고 항상 똑같은 코드를 작성합니다.
컴포넌트의 이름만 바뀌고, 같은 코드가 반복됩니다.
// index.tsx
import classNames from 'classnames/bind';
import styles from './styles.module.scss';
const cx = classNames.bind(styles);
interface Props {}
export const Component = ({}: Props) => {
return <></>
};
// index.stories.tsx
import type { Meta, StoryObj } from '@storybook/nextjs-vite';
import { Component } from '.';
export default {
title: '',
component: Component,
} as Meta<typeof Component>;
export const 기본: StoryObj<typeof Component> = {
name: 'Component',
args: {},
};
// styles.module.scss
...
뭐 이런 거까지 자동화를 해? 별다자(별걸 다 자동화 하네)라고 생각하실 수 있지만, 생각보다 절약되는 시간이 많습니다.
또한, 많은 작업자들이 관여하는 모노레포의 경우 일관된 코드 스타일을 구축하는 데에 도움을 줄 수 있습니다.
무엇보다 규모가 거대한 모노레포의 특징을 고려했을 때, 내가 생성할 컴포넌트의 적절한 위치를 찾는 것 또한 피곤한 과정이 됩니다.
plopjs가 이런 작업을 위해 존재합니다.
2. plopjs를 활용한 코드 생성 자동화
Plop: Consistency Made Simple
A little tool that saves you time and helps your team build new files with consistency. Generate code when you want, how you want.
plopjs.com
Plop is what I like to call a "micro-generator framework."
plop은 일관된 형식으로 코드를 생성할 수 있게 하는 프레임워크입니다.
위의 리액트 컴포넌트 생성 과정을 plop으로 자동화 해볼까요?
자동화를 위해 필요한 정보는 2가지 입니다.
- 컴포넌트의 이름
- 컴포넌트가 생성될 폴더
이 두 가지 정보로 컴포넌트를 자동 생성해보겠습니다.
2.1 plop 셋업
$ pnpm install --save-dev plop
plop을 설치하고, 프로젝트의 루트 디렉토리에 propfile.mjs 파일을 생성합니다.
import { execSync } from 'child_process';
export default function (plop) {
plop.setGenerator('component', {
description: '컴포넌트를 생성합니다.',
prompts: [
{
type: 'input',
name: 'name',
message: '컴포넌트 이름을 입력하세요:',
},
{
type: 'input',
nane: 'path',
message: '컴포넌트 폴더가 생성될 경로를 입력하세요:',
},
],
actions: () => {
const actions = [
{
type: 'addMany',
destination: '{{path}}/{{name}}',
base: 'plop-templates',
templateFiles: 'plop-templates/*.hbs',
abortOnFail: true,
},
function formatGeneratedFiles(answers) {
try {
const generatedDir = `${answers.path}/${answers.name}`;
console.log(`코드 스타일을 정리합니다: ${generatedDir}`);
execSync(`eslint --fix '${generatedDir}' | prettier --write '${generatedDir}'`);
return '코드 스타일 정리가 완료되었습니다.';
} catch (error) {
return '코드 포맷팅을 건너뛰었습니다.';
}
},
];
return actions;
},
});
}
이제 생성할 파일들의 포맷을 정의할 plop-templates 폴더를 루트에 만들고, 아래 파일들을 만듭니다.
// index.tsx.hbs
import classNames from 'classnames/bind';
import styles from './styles.module.scss';
const cx = classNames.bind(styles);
interface Props {}
export const {{pascalCase name}} = ({}: Props) => {
return <>This is {{pascalCase name}}</>
};
// index.stories.tsx.hbs
import type { Meta, StoryObj } from '@storybook/nextjs-vite';
import { {{pascalCase name}} } from '.';
export default {
title: '',
component: {{pascalCase name}},
} as Meta<typeof {{pascalCase name}}>;
export const 기본: StoryObj<typeof {{pascalCase name}}> = {
name: '{{pascalCase name}}',
args: {},
};
// styles.module.scss.hbs
...
마지막으로 package.json에 plop용 스크립트를 추가합니다.
"scripts": {
"plop": "plop"
},
이제 CLI에 pnpm plop을 입력해서 컴포넌트를 생성하면 됩니다.
$ pnpm plop
> 컴포넌트 이름을 입력하세요: installment-chip
> 컴포넌트 폴더가 생성될 경로를 입력하세요: src/app/main/_component
'Infra' 카테고리의 다른 글
[AWS] S3 + CloudFront + Route53로 NextJS 정적 배포하기 (0) | 2024.08.25 |
---|---|
[AWS] github action + S3로 NextJS 정적배포 자동화 시도 (0) | 2024.08.14 |