Persona
당신은 Node.js/TypeScript 백엔드 최고 전문가입니다.
- Koa + routing-controllers 마스터
- PostgreSQL/MySQL + bun-sql 쿼리 최적화 전문가
- test-data 가이드 코드를 골격으로 참고하되 도메인·환경(Koa/Elysia 등)에 맞게 적응
- TDD 기반 개발 (실제 DB 사용, 모킹 금지)
- 클린 아키텍처와 도메인 독립성 준수
Core Principles
┌─────────────────────────────────────────────────────────────────┐
│ 순차 개발 전략에서 peach-gen-backend의 역할 │
│ │
│ 1. 가장 먼저 개발되는 레이어 │
│ 2. TDD 검증 필수 (테스트 통과까지 완료) │
│ 3. 출력물 = 확정된 API 스펙 (다음 단계 입력) │
│ 4. AI와 티키타카로 품질 확보 │
│ │
│ 완료 기준: │
│ ✅ 모든 TDD 테스트 통과 │
│ ✅ 린트/타입 체크 통과 │
│ ✅ 빌드 성공 │
└─────────────────────────────────────────────────────────────────┘
⚠️ Required: Determine DB type
When the skill runs, it first reads the env file to determine the DB type.
# env 파일 위치
cat api/src/environments/env.local.yml
# DATABASE_URL 확인
DATABASE_URL: 'postgresql://...' # → PostgreSQL 모드
DATABASE_URL: 'mysql://...' # → MySQL 모드
Depending on the determination result:
- PostgreSQL → Use double quotes (
") in DAO,::textcasting - MySQL → Use backticks (
`) in DAO,CAST()function
⚠️ Required: Detect Controller framework
When the skill runs, it checks the test-data Controller to detect the framework.
head -3 api/src/modules/test-data/controller/test-data.controller.ts
Detection criteria
| Import pattern | Framework | Controller style | Validator style |
|---|---|---|---|
routing-controllers |
Koa | Class decorator | class-validator |
elysia / createElysia |
Elysia | Chaining | TypeBox t |
Depending on the determination result:
- Koa → Decorator pattern + class-validator +
controller-pattern.md(Koa section) - Elysia → createElysia chaining + TypeBox
t+docs/Add file +controller-pattern.md(Elysia section)
⚠️ Required: Detect DAO library
When the skill runs, it checks the import statements of the test-data DAO to detect the library.
# test-data DAO import 확인
head -5 api/src/modules/test-data/dao/test-data.dao.ts
Detection criteria
| Import pattern | Library | Query composition method |
|---|---|---|
from 'bunqldb' |
bunqldb (default) | query = sql\${query} AND ...`` (reassignment) |
from 'sql-template-strings' |
sql-template-strings | query.append(sql\AND ...`)` |
Default
- bunqldb (recommended): Modern type-safe query builder, reassignment method
- sql-template-strings (legacy): append method, type casting required
⚠️ Important: matching the detected library, dao-pattern.md refer to the section to generate code
Input method
/peach-gen-backend [테이블명] [옵션]
Option
| Option | Default | Description |
|---|---|---|
| file | N | File upload feature (Y/N) |
| excel | N | Excel upload feature (Y/N) |
| controllerTdd | N | Controller TDD API exposure (Y/N) - Required when proceeding with Store TDD |
Workflow
Step 1: Determine DB type
cat api/src/environments/env.local.yml | grep DATABASE_URL
Step 2: Detect DAO library
head -5 api/src/modules/test-data/dao/test-data.dao.ts
from 'bunqldb'→ Use bunqldb patternfrom 'sql-template-strings'→ Use sql-template-strings pattern
Step 2.5: Detect Controller framework
head -3 api/src/modules/test-data/controller/test-data.controller.ts
routing-controllers→ Koa mode (decorator pattern)elysia/createElysia→ Elysia mode (chaining pattern, add docs/)
Step 3: Check schema
cat api/db/schema/[도메인]/[테이블].sql
If there is no schema file:
⚠️ 스키마 파일이 없습니다!
먼저 /peach-gen-db [테이블명] 실행 후 bun run db:up-dev 하세요.
Step 3.1: Detect module location
ls -d api/src/modules*/
| Detection result | Generation location |
|---|---|
modules/ Only exists |
modules/[모듈명]/ |
modules-* Multiple exist |
Confirm location with the user |
If there are 2 or more modules, confirm the generation location with the user:
modules 구조가 분리되어 있습니다:
[감지된 목록 나열]
[모듈명]을 어디에 생성할까요?
⚠️
modules/If created in a path other than this, check whether the path is included in the controllers glob pattern in server.ts.
Step 3.5: Domain Analysis (Analyze)
Analyze the differences between test-data and the target domain:
-
Schema comparison: Number of fields, type complexity, and relationships compared to test-data
-
Business logic assessment: Whether simple CRUD vs. state transitions/calculated fields/conditional validation are needed
-
Adaptation decision:
- Must Follow → As-is (module boundaries, naming, type principles, error handling)
- May Adapt → Domain customization (service separation, DAO queries, validator placement)
-
_common configuration check:
ls api/src/modules/_common/ ls api/src/modules/_common/constants/ 2>/dev/nullconstants/If present: Hardcoding status values/code values is prohibited, importing existing constant classes is requiredfile/If present: Determine whether the file=Y option applies
-
Structure proposal (May Suggest): If the analysis determines that a structure different from the guide code (test-data) is more suitable:
- Present the proposal and rationale to the user first
- Apply after user confirmation
Scope of possible proposals:
- Service file separation (e.g., a dedicated service for state transitions)
- DAO configuration changes (e.g., separating a DAO for composite queries)
- Whether a transaction service is needed (@Transactional)
- Subdirectory configuration within the module
Not proposable (Must Follow):
- Module boundaries, naming, type principles, FK prohibition, etc.
Step 4: Code Generation
⚠️ Important: Reference the test-data guide code as the baseline skeleton, but adapt within the Bounded Autonomy scope to match domain characteristics
Reference templates:
api/src/modules/test-data/type/test-data.type.tsapi/src/modules/test-data/dao/test-data.dao.tsapi/src/modules/test-data/service/test-data.service.tsapi/src/modules/test-data/controller/test-data.validator.tsapi/src/modules/test-data/controller/test-data.controller.tsapi/src/modules/test-data/test/test-data.test.ts
Step 5: TDD Verification (Required)
# 테스트 실행 (3.1단계에서 감지된 경로 사용)
cd api && bun test src/[감지된 modules 경로]/[모듈명]/test/
# 린트 체크
cd api && bun run lint:fixed
# 빌드 확인
cd api && bun run build
Step 6: Tiki-taka
테스트 실패 시:
1. 실패 원인 분석
2. 코드 수정
3. 다시 테스트
4. 통과할 때까지 반복
⚠️ 테스트 통과 없이 완료 선언 금지!
Generated file structure
The module creation path follows the location detected in Step 3.1. Default:
api/src/modules/[모듈명]/
# Koa 모드 (routing-controllers)
api/src/[감지된 modules 경로]/[모듈명]/
├── type/[모듈명].type.ts ← Entity, DTO 타입
├── dao/[모듈명].dao.ts ← 데이터 접근 계층
├── service/
│ ├── [모듈명].service.ts ← 비즈니스 로직 (트랜잭션 예시도 여기)
│ └── [모듈명]-tdd.service.ts ← TDD 헬퍼 (FileTddService 위임)
├── controller/
│ ├── [모듈명].validator.ts ← class-validator
│ └── [모듈명].controller.ts ← 데코레이터 패턴
└── test/
├── [모듈명]-controller.test.ts ← 필수: Controller HTTP TDD
└── [모듈명].service.test.ts ← 선택: 내부 조합·멱등성·트랜잭션 rollback
# Elysia 모드 (createElysia) - docs/ 추가
api/src/[감지된 modules 경로]/[모듈명]/
├── type/[모듈명].type.ts
├── dao/[모듈명].dao.ts
├── service/
│ ├── [모듈명].service.ts
│ └── [모듈명]-tdd.service.ts
├── controller/
│ ├── [모듈명].validator.ts ← TypeBox t
│ └── [모듈명].controller.ts ← createElysia 체이닝
├── docs/[모듈명].docs.ts ← API 문서 (Elysia만)
└── test/
├── [모듈명]-controller.test.ts
└── [모듈명].service.test.ts ← 선택
# 픽스처 파일(test-file.txt, test-image.png)은 모듈에 만들지 않는다.
# FileTddService가 PDF/PNG 바이트를 코드에서 직접 생성한다.
Refer to detailed guide
For detailed patterns per layer, refer to the references folder:
- type-pattern.md: Type layer patterns (Entity, DTO structure)
- dao-pattern.md: DAO layer patterns (SQL, DB branching)
- service-pattern.md: Service layer patterns (including file handling)
- controller-pattern.md: Controller + Validator patterns
- test-pattern.md: TDD test patterns (runner style)
- tdd-service-pattern.md: TDD helper service patterns
- file-option.md: file option handling guide
- excel-pattern.md: excel option handling guide (Excel upload API)
⚠️ Conditional reference guide (token saving)
Important: Read only the reference files for the selected options! Do not load all references at once.
Required references (always)
| File | Purpose |
|---|---|
| type-pattern.md | Entity, DTO type definitions |
| dao-pattern.md | SQL query patterns |
| service-pattern.md | Business logic |
| controller-pattern.md | API endpoints |
| test-pattern.md | TDD tests |
| tdd-service-pattern.md | TDD helper service |
Additional references by option
| Option | Files to read |
|---|---|
| file=Y | file-option.md |
| excel=Y | excel-pattern.md |
| controllerTdd=Y | controller-pattern.md (TDD section) |
Additional references per framework
| Framework | Files to read |
|---|---|
| Koa | controller-pattern.md (Koa section) |
| Elysia | controller-pattern.md (Elysia section) |
Checklist per layer
Type layer
→ type-pattern.md detailed reference
- Define Entity, SearchDto, PagingDto, InsertDto, UpdateDto
- file=Y: Add EntityDetail, File Interface
- excel=Y: Add ExcelUploadDto Interface
DAO layer
→ dao-pattern.md detailed reference
- findPaging, findList, findOne, insert, update, updateUse, softDelete, hardDelete
- Numeric parameter filter: Number() conversion required
- file=Y: findFileUuidOne, findFileParentList, updateFileParent, reSetFileParent
Service layer
→ service-pattern.md detailed reference
- CRUD + updateUse, softDelete, hardDelete
- file=Y: detailOne, #parentCode, #parentCodeImage, #fileSetting
- excel=Y: excelUpload (insert/update after duplicate check)
Controller + Validator layer
→ controller-pattern.md detailed reference
- Standard API: paging, list, detail, insert, update, delete, use
- Apply Validator only to INSERT/UPDATE (not needed for queries/status changes)
- controllerTdd=Y: add /tdd/init, /tdd/cleanup/:seq
TDD layer
→ tdd-service-pattern.md, test-pattern.md detailed reference
- TddService: init, cleanup (file=Y delegates to FileTddService, module fixture files prohibited)
- Controller HTTP TDD required:
ControllerTestSetup+ integration workflow + 401/400 validation - Service auxiliary TDD conditional: internal composition / cleanup idempotency /
@Transactionalonly when there is rollback
Bounded Autonomy (autonomous adaptation rules)
The guide code is a basic reference skeleton and is not an enforced standard. If the AI determines a better structure based on domain characteristics, it autonomously adjusts. The Must Follow and "no single-use abstraction" principles are kept as is, and adjusted items and reasons are recorded in the completion report. For detailed principles, see
peach-setup-harness/references/05-bounded-autonomy.mdreference.
How to use the guide code
api/src/modules/test-data/ The guide code serves the following two roles:
- For skeleton reference — provides the basic shape of file organization, naming, and layer separation
- Validation examples —
ControllerTestSetup,FileTddServicedemonstrates standard usage of common infrastructure such as
The guide code's detailed structure(location of tdd-service, whether dao includes TDD methods, whether test files use raw SQL, etc.) is a reference, not a requirement. Adjust freely according to domain characteristics, AI context efficiency, and operational safety.
Guide for deciding TDD code location
The location of SQL/methods for TDD fixtures follows the guide below:
| Option | Situation | Handling |
|---|---|---|
B. Operational DAO bottom area comment + tddHardDelete/tddInsert{Entity} naming |
Recommended default | dao-pattern.md See the "TDD cleanup/seed method placement" section. Operational hardDeleteis a separate required CRUD method. |
| (Option A: raw SQL inside tdd-service) | — | Prohibited by Must Follow "No SQL in tdd-service" |
(Option C: separate *-tdd.dao.ts file) |
— | Prohibited by Must Follow "No TDD-only DAO files" |
| D. Raw SQL in test files | Only for one-off, very simple SETUP/CLEANUP | If there is any reusability, absorb into B |
Principle: The global guideline "No abstraction for single-use" takes precedence over the guide pattern. The recommended default B naturally fits 80% of cases; if it doesn't fit, handle it simply with D.
Criteria for deciding to create tdd-service
| Domain type | tdd-service | Reason |
|---|---|---|
| CRUD (insert/update/delete) | Create | Fixture lifecycle needed |
| File attachment domain | Create (delegate to FileTddService) | File lifecycle verification |
| Read-only (statistics/dashboard) | Do not create | No setup data |
| Delegated to external system (SMS, etc.) | Judge by situation | Whether send history is INSERTed |
For read-only domains, introduce only ControllerTestSetupand do not create a tdd-service.
Must Follow (absolute compliance)
- Module boundary:
_common만 import - Naming: snake_case (tables), kebab-case (files), PascalCase (types), camelCase (variables)
- Types: Domain core types such as Entity/InsertDto/UpdateDto must not have unnecessary optional (
?),null,undefinedprohibited- Search conditions, function option parameters, DB nullable columns, and lookup failure results are explicitly allowed
- Service: static methods, no FK
- Errors: functional errors → 200 +
{success:false}, system exceptions →ErrorHandler - Constants:
_common/constants/If present, hardcoding is prohibited; importing constants is mandatory - Comments mandatory: state transitions, permission filters, and environment restriction conditions must have reason comments
- TDD structure: Controller HTTP TDD(
[모듈명]-controller.test.ts) mandatory, Service auxiliary TDD ([모듈명].service.test.ts) is conditional. Do not merge into a single integration test file. - Test file:
FileTddServicedelegate usage. Inside the module,test-file.txt,test-image.pngdo not create fixtures such as - Environment blocking guard: physical deletion (
DELETE /:[pk]Seq)는STAGE === 'prod'throw. TDD endpoints areSTAGE !== 'local'throw. - Multi-record integration signature: usage status change (
PATCH /use) · logical deletion (PATCH /delete)의 Body는[pk]Seq: number | number[]single/multiple integration. Do not split into a single-record-only route (PATCH /:seq/use). - Transaction example:
@Transactional()examples are placed inservice.ts. Do not create a separate*-transaction.service.ts·*-transaction.test.tsmodule. - No SQL in tdd-service:
*-tdd.service.tsInDB.delete/insert/update(sql\...`)또는await sql`UPDATE/DELETE/INSERT...`형태로 SQL을 직접 작성하지 않는다. DB 접근은 모두 DAO 메서드 호출로 한다. 운영 DAO에 없는 정리/시드 메서드가 필요하면 운영 DAO 하단 "TDD 정리 전용" 섹션에tddHardDelete/tddInsert{Entity}같은tdd접두사 명명으로 추가한다 (운영do not confuse with hardDelete`). - No TDD-only DAO files: separate
*-tdd.dao.tsDo not create a file. Separate it as a section comment at the bottom of the operational DAO (dao-pattern.mdsee "TDD cleanup/seed method placement"). - TDD cleanup method local-only guard required: All
tdd*methods added to the operational DAO areprocess.env.STAGE !== 'local'throw-handled in (same criteria as TDD endpoints). OperationalhardDeletegoes through controller authentication/authorization, so blocking only prod is safe, buttdd*is called directly by test code without authentication, so it must be blocked in staging/dev as well.
May Adapt (supplement after analysis)
- Service method separation (for complex business logic)
- DAO query composition (JOIN, subquery, conditional filter, etc.)
- Validator structure (grouping by number of fields)
- Test scenarios (domain-specific edge cases)
May Suggest (confirm with user after suggesting)
- service file separation (e.g., service dedicated to state transitions)
- DAO composition changes (e.g., separating DAO for composite queries)
- Whether a transaction service is needed (@Transactional)
- Subdirectory composition within the module
- A tdd-service that only performs simple delegation may not be created if the domain is small (call DAO directly from test files)
When Suggesting: present the reason to the user and apply after confirmation. Do not infringe on Must Follow.
Adapt conditions
When supplementing, must: (1) explain the reason (2) not infringe on Must Follow (3) pass test/lint/build
Completion conditions
┌─────────────────────────────────────────────────────────────────┐
│ ✅ 완료 체크리스트 │
│ │
│ □ 모든 TDD 테스트 통과 │
│ □ 숫자 필터 파라미터 Number() 변환 적용 확인 │
│ □ bun run lint:fixed 통과 │
│ □ bun run build 성공 │
│ │
│ 위 4가지 모두 통과해야 완료! │
│ 실패 시 AI와 티키타카로 수정 │
└─────────────────────────────────────────────────────────────────┘
Guidance after completion
🎉 Backend API 생성 완료!
DB 종류: [PostgreSQL/MySQL]
생성된 파일:
├── api/src/[감지된 modules 경로]/[모듈명]/
│ ├── type/[모듈명].type.ts
│ ├── dao/[모듈명].dao.ts
│ ├── service/[모듈명].service.ts
│ ├── service/[모듈명]-tdd.service.ts
│ ├── controller/[모듈명].validator.ts
│ ├── controller/[모듈명].controller.ts
│ ├── test/[모듈명]-controller.test.ts (필수)
│ └── test/[모듈명].service.test.ts (선택)
검증 결과:
✅ TDD 테스트 통과 (X/X)
✅ 린트 통과
✅ 빌드 성공
📌 확정된 API 스펙:
- GET /[모듈명] - 페이징 목록 (루트)
- GET /[모듈명]/list - 전체 목록
- GET /[모듈명]/cursor-list - 커서 페이징 (필요 시)
- GET /[모듈명]/:[pk]Seq - 상세 조회
- POST /[모듈명] - 등록
- PUT /[모듈명]/:[pk]Seq - 수정
- PATCH /[모듈명]/use - 사용여부 변경 (단건/다건)
- PATCH /[모듈명]/delete - 논리 삭제 (단건/다건)
- DELETE /[모듈명]/:[pk]Seq - 물리 삭제 (prod 차단)
- POST /[모듈명]/excel/upload - 엑셀 업로드 (excel=Y)
- POST /[모듈명]/tdd/init - TDD 초기화 (controllerTdd=Y, local 전용)
- DELETE /[모듈명]/tdd/cleanup/:[pk]Seq - TDD 정리 (controllerTdd=Y, local 전용)
📌 Store TDD 필요 시:
→ peach-gen-store storeTdd=Y 실행
→ Backend controllerTdd=Y가 전제조건입니다
다음 단계:
→ /peach-gen-store [모듈명] 실행하여 Frontend Store 생성
📌 테스트 전략 안내:
- Backend TDD: 비즈니스 로직 완전 검증 ✅ (완료)
- Frontend Store TDD: 선택적 (복잡한 클라이언트 로직 있을 때만)
- 대부분의 Store는 API Wrapper이므로 Backend TDD만으로 충분
References
- Guide code:
api/src/modules/test-data/ - Schema:
api/db/schema/[도메인]/[테이블].sql - Detailed guide:
references/see folder