회사에서 새 프로젝트를 시작할 때마다 같은 작업을 반복하고 있었다. Express 프로젝트 초기 설정, TypeScript 설정, 린터 설정, Swagger 연동, 그리고 CRUD API 작성…
“이거 자동화하면 되지 않을까?”
그렇게 시작된 프로젝트가 cucu-generator다.
문제 정의
당시 겪고 있던 문제들:
- 매번 반복되는 초기 설정: tsconfig, eslint, prettier, swagger… 새 프로젝트마다 30분~1시간 소요
- 일관성 없는 프로젝트 구조: 프로젝트마다 폴더 구조가 제각각
- CRUD 보일러플레이트: User, Post, Comment… 엔티티만 다르고 코드는 거의 동일
해결책 설계
두 가지 기능을 만들기로 했다.
1. 프로젝트 스타터
$ npx cucu-generator
? Select a template
❯ cucu-project-starter
crud-generator
선택하면 바로 실행 가능한 TypeScript Express 프로젝트가 생성된다.
포함된 것들:
- TypeScript 설정
- ESLint + Prettier
- Swagger UI (
/docs엔드포인트) - Sequelize ORM 연동
- JWT 인증 미들웨어
- 환경변수 관리
2. CRUD 제너레이터
$ npx cucu-generator
? Select a template
cucu-project-starter
❯ crud-generator
? Entity name: Person
실행하면 아래 파일들이 자동 생성된다:
src/
├── controllers/
│ └── PersonController.ts
├── services/
│ └── PersonService.ts
├── models/
│ └── Person.ts
├── routes/
│ └── person.routes.ts
└── dto/
├── CreatePersonDto.ts
└── UpdatePersonDto.ts
구현 과정
Inquirer.js로 CLI 인터페이스
import inquirer from 'inquirer';
const answers = await inquirer.prompt([
{
type: 'list',
name: 'template',
message: 'Select a template',
choices: ['cucu-project-starter', 'crud-generator']
}
]);
템플릿 엔진으로 코드 생성
EJS를 사용해서 템플릿을 만들었다:
// templates/controller.ejs
import { Request, Response } from 'express';
import { <%= entityName %>Service } from '../services/<%= entityName %>Service';
export class <%= entityName %>Controller {
private service = new <%= entityName %>Service();
async findAll(req: Request, res: Response) {
const items = await this.service.findAll();
res.json(items);
}
async findOne(req: Request, res: Response) {
const item = await this.service.findOne(req.params.id);
res.json(item);
}
// ...
}
npm 배포
npm login
npm publish
처음 npm에 패키지를 배포했을 때의 그 짜릿함이란… 내가 만든 코드가 전 세계 누구나 npm install로 설치할 수 있다니.
반응
GitHub에 올리고 몇 달 후, 스타가 하나둘 붙기 시작했다. 지금은 14개. 많지 않지만, 누군가는 이 도구가 유용했다는 뜻이다.
특히 뿌듯했던 건 fork가 생겼을 때다. 누군가 내 코드를 가져다가 자기만의 버전을 만들고 있다는 것.
배운 점
1. CLI 도구 개발의 재미
웹 개발만 하다가 CLI 도구를 만드니 색다른 재미가 있었다. 화면 없이 텍스트만으로 인터랙션하는 게 오히려 집중이 잘 됐다.
2. npm 생태계 이해
패키지 배포, 버저닝, peer dependencies 등 npm 생태계를 깊이 이해하게 됐다. 나중에 회사에서 private npm 레지스트리 구축할 때 이 경험이 도움됐다.
3. 문서화의 중요성
README 하나 잘 쓰는 게 생각보다 중요했다. GIF로 사용법을 보여주니 스타가 더 붙었다.
한계와 아쉬움
지금 보면 아쉬운 점도 많다.
-
NestJS의 등장: 이 도구를 만들고 얼마 지나지 않아 NestJS로 전환했다. NestJS CLI가 이미 비슷한 기능을 잘 제공하고 있었다.
-
유지보수 부재: 회사 일이 바빠지면서 업데이트를 못 했다. 오픈소스 메인테이너의 어려움을 조금 느꼈다.
-
테스트 부족: 테스트 코드 없이 배포했다. 지금이라면 절대 안 그럴 텐데.
마무리
cucu-generator는 내 첫 npm 패키지이자 첫 오픈소스 프로젝트다. 비록 지금은 거의 사용하지 않지만, 이 경험이 개발자로서 한 단계 성장하는 계기가 됐다.
누군가 반복 작업에 지쳐있다면, 도구를 만들어보길 추천한다. 그 과정에서 배우는 것들이 예상외로 많다.
GitHub: cucu-generator npm: cucu-generator
관련 포스트가 4개 있어요.
10개 넘는 백엔드 프로젝트를 NestJS로 만들면서 깨달은 패턴들
NestJS 실전에서 배운 것들
Electron으로 데스크톱 앱을 만들어보려다 실패한 이야기
백엔드 개발자의 데스크톱 앱 도전기
Express로 1년 반 개발하다 NestJS로 전환한 이유
1년 반 후, 왜 NestJS로 갈아탔나
apidoc으로 Express API 문서를 자동 생성하고 팀 협업을 개선한 이야기