규칙 엔진
3.0 의 생성기는 두 부분으로 나뉩니다.
| 무엇을 정하나 | 어디에 있나 | |
|---|---|---|
| 규칙(rule) | 무엇을 낼지 - 이 필드에 @Column(length=200) 이 붙는가 | Java 클래스 (CodeRules) |
| 스켈레톤(template) | 그것이 어디에 놓이는지 - 파일의 뼈대 | .tmpl 파일 |
규칙은 모델을 읽고 판단만 합니다. 문자열을 어떻게 쓰는지(세미콜론, import 형태, 프로퍼티 선언)는 언어 이음새
(Syntax)가 답합니다. 이 분리 덕분에 같은 규칙으로 Java 와 Kotlin 을 모두 생성합니다.
모델(DSL) ──▶ Spec ──▶ 규칙들 ──▶ SourceCode ──▶ 스켈레톤 ──▶ 파일
│
Syntax(언어)
번들
번들은 규칙 집합의 이름 목록입니다. build.gradle 의 두 단어가 하나를 고릅니다:
architecture | language = 'java' | language = 'kotlin' |
|---|---|---|
layered | jpa-springboot (2.x 호환 출력), -Pv3 면 jpa-springboot-v3 | jpa-springboot-kt |
ddd | ddd-springboot | ddd-springboot-kt |
hexagonal | hexagonal-springboot | hexagonal-springboot-kt |
| 번들 | 무엇을 생성하나 |
|---|---|
jpa-springboot | 2.x 파이프라인과 같은 출력 (이력에 적은 2.x 버그 수정 제외) |
jpa-springboot-v3 | 정리된 출력 - 실제 쓰는 import 만, 규칙이 만드는 클래스 애노테이션 |
jpa-springboot-kt | Kotlin 출력 |
ddd-springboot | v3 + 애그리거트 경계 - 루트만 repository·service·controller, 불변 값 객체, 도메인 이벤트 |
hexagonal-springboot | ddd-springboot + 노출된 루트마다 인바운드 포트(<Entity>UseCase) |
ddd-springboot-kt, hexagonal-springboot-kt | 같은 읽기의 Kotlin 판 |
ts-model | TypeScript - DTO·enum·검색 DTO + 컨트롤러를 부르는 클라이언트 |
플러그인은 이 표를 갖고 있지 않습니다. 두 단어를 적힌 그대로 넘기고, 생성기가 한 쌍을 하나의 번들과 하나의 언어 스위치로 합성하므로 둘이 어긋날 수 없습니다.
옵트인, 그리고 지켜지는 2.x 출력
- 아무것도 선언하지 않으면 아무것도 달라지지 않습니다.
elasticore { }블록에architecture·language·rules가 없는 빌드는 2.x 생성기로 생성합니다. 기본값을layered로 "정해 두는" 것과 아예 전달하지 않는 것은 다릅니다 - 선언이 없으면 플러그인은 아무것도 보내지 않습니다. - 풀 리퀘스트마다 검사합니다: CI 가 2.x 생성기로 기준 프로젝트를 다시 생성하는데 커밋된 그대로여야 하고, 그다음
규칙 엔진의 출력을 2.x 출력과 비교합니다 - 산출물별로(
150 MATCH / 0 DIFF / 2 ACCEPTED), 그리고 기준 프로젝트에서 2.x 가 만드는 229개 파일 전부(0 differ / 0 missing / 0 extra: 2.x 버그 수정으로 달라지는 4개는 이름을 정해 허용, 1개는 import 순서만 다름). - 새 기능은 쓸 때만 켜집니다 - DSL 단어, 설정, 번들.
env.yml 에서 규칙 고르기
대부분의 프로젝트는 필요 없습니다 - build.gradle 의 두 단어가 번들을 고릅니다. 프로젝트의 나머지와 다른 도메인만
규칙을 적습니다:
elasticore:
config:
publisher:
rules: [hexagonal-springboot, ossie-export] # 이 도메인의 기본값을 대체
suppress: [jpa-comment] # 규칙 하나 끄기 - 누적됨
| 키 | 뜻 |
|---|---|
rules | 쓸 규칙 집합 - 기본값을 대체. 이름은 번들, 규칙 집합, 또는 CodeRules 의 완전한 클래스 이름 |
suppress | 끌 규칙 id - 누적 |
rules.kt | Kotlin 용 (있으면 rules 보다 우선) |
rules.ts | TypeScript 용 - TypeScript 는 서버의 규칙을 물려받지 않음 |
우선순위: 도메인의 env.yml, 그다음 프로젝트(생성 태스크의 시스템 속성 elasticore.publisher.rules), 그다음 내장 기본값.
publisher.rules 는 규칙 엔진만 읽습니다. 2.x 애노테이션 프로세서는 읽지 않습니다.
규칙 보기와 더하기
./gradlew elcore3 -PlistRules # 도메인마다 선택된 규칙을 파일 종류별로 실행 순서대로 (아무것도 쓰지 않음)
팀 규칙은 build.gradle 에서 선택된 번들 뒤에 더합니다:
elasticore {
architecture = 'hexagonal'
rules = ['com.acme.rules.AcmeRules'] // 번들 뒤에 더해짐
}
dependencies {
elasticore project(':acme-rules') // 생성기 클래스패스 (애플리케이션에는 안 들어감)
}
작 성하는 법: 우리 팀 규칙.
두 진입점은 섞지 않습니다
규칙 엔진(elcore3)과 2.x 애노테이션 프로세서(@ElastiCore)는 같은 파일을 서로 다른 규칙으로 생성합니다. 번들을
쓰는 프로젝트는 태스크만 씁니다 - 애플리케이션 클래스에 @ElastiCore 를 붙이지 마세요. 플러그인이 태스크를
등록하며, 플러그인 없이 손으로 구성하는 방법은 blueprint/elasticore-rule-guide.md 에 있습니다.