요약
1. 반복적으로 작성되는 코드들에 대한 패턴을 찾아서 코드 생성기를 만들어서 자동으로 코드를 생성한다.
2. 코드 생성기를 통해 생성된 코드는 일관적이기 때문에 유지보수가 용이하고 개발 속도가 빨라진다.
3. AI의 도움을 받아서 유지 보수를 하면 비교적 손쉽게 유지보수가 가능하다.
백엔드 코드를 구현하면서 반복적으로 작성되는 코드들을 칠때마다 매번 귀찮다고 생각을 했다.
비지니스 로직에 집중해서 빠르게 코드 구현과 테스트만 진행하면 개발 속도가 빠르지 않을까? 라는 생각을 하던 도중 gRPC에서 proto를 기반으로 기초 코드를 생성하는걸 보고 힌트를 얻었다.
특히 Node.js에서는 Nest.js, React.js, Next.js 모두 Code Generator를 제공하고 있어서 이를 아이디어 삼아 코드 생성기를 구현하기로 했다.
들어가기 앞서 먼저 코드 생성기로 구현을 하려면 기본적으로 열려있는 코드 패턴을 만들어야 했고, 비지니스 로직을 제외하면 최대한 패턴화를 시켜야 한다고 생각을 했다.
그래서 기본적으로 Controller-Service-Repository 패턴으로 코드를 구현을 했고, 이 위에 패턴화를 시작했다.
먼저 응답 데이터에 대해서 패턴화를 시켰다.
{
"statusCode": 200,
"message": "Success",
"data": {
"id": 1,
"name": "John Doe"
}
}
위와 같이 data 필드는 반드시 Object 형태로 구성하고, statusCode와 message는 반드시 존재하도록 했다.
또한 목록 조회와 같이 List 반환이 필요한 경우는 data 필드에 items라는 필드에 담도록 패턴화 했다.
응답 데이터뿐만 아니라 요청 데이터에 대해서도 어느정도 패턴화를 진행했다.
페이지네이션 목록 조회 요청, 특정 공통 요청 데이터에 대해서 Base를 만들고 해당하는 타입을 상속받아서 구현할 수 있도록 구성했다.
Typescript로 예를 들면 아래와 같이 구성했다.
export class DomainGetDto extends IntersectionType(BasePaginationRequestDto, AdminRequestDto) {}
class DomainResponseData {
@ApiProperty({ item: DomainResponseDataItem, isArray: true })
items: DomainResponseDataItem[];
/**
* 기타 필요한 데이터
*/
}
export class DomainResponse extends BaseResponse {
@ApiProperty({ type: DomainResponseData })
data: DomainResponseData;
}
위와 같이 API에 필요한 요청, 응답 데이터를 패턴화를 진행한 다음 Controller/Service에 대한 패턴화를 진행했다.
Controller와 Service에 대한 역할은 아래와 같이 정의했다.
이제 Code에 대한 기본적인 패턴을 구현했기 때문에 위 패턴을 기반으로 Generator를 구현했다.
구현한 패턴은 아래와 같다.
단순히 생성 과정은 위와 같은 과정으로 진행하고, 이후에 변경/삭제에 대한 부분도 코드 파일을 읽어서 진행할 수 있도록 구현했다.
구현하면서 핵심은 최대한 패턴화하고, 패턴화한 부분을 AI한테 전달해서 코드를 생성하도록 했다.
아직까지는 AI가 세부적인 구현은 잘못한다고 생각하지만, 정확하게 패턴화된 부분은 잘한다고 생각을 했고 실제로도 처음 구현부터 유지보수까지 편리하게 진행했다.
생성된 Generator는 CLI를 통해 실행할 수 있도록 했다.
Code Generator를 통해 개발을 진행하고 아래와 같은 이점을 얻게 됐다.
단점으로는 Generator를 또한 유지 보수를 해야할 수 있기 때문에 유지 보수 비용이 증가한다고 느껴질 수 있지만, 없을때 사용하던 시간에 비해서 대폭 감소했기 때문에 괜찮았다.
gRPC는 REST보다 더 간단하게 Generator를 생성했다.
REST는 DTO 파일을 정의하고 Method와 같은걸 판별해야했지만, gRPC는 proto 파일에 이미 Service가 전부 정의가 된 상태고, protoc를 통해 기초 코드를 생성해주기 때문에 편리했다.
이에 build-proto 명령어를 만들고 수행하면 아래와 같은 순서로 진행됐다.
1. protoc 빌드
2. protoc가 생성한 기초 코드들과 proto 파일을 기반으로 Controller/Service 코드 생성