一键导入
add-api-endpoint
REST API 엔드포인트 스캐폴딩 (Controller → UseCase → Service → JPA, DDD 패턴). 새 API 추가, 엔드포인트 생성, CRUD 구현 요청 시 사용. 백엔드에 새 기능을 추가할 때 DDD 레이어 구조를 자동 생성.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
REST API 엔드포인트 스캐폴딩 (Controller → UseCase → Service → JPA, DDD 패턴). 새 API 추가, 엔드포인트 생성, CRUD 구현 요청 시 사용. 백엔드에 새 기능을 추가할 때 DDD 레이어 구조를 자동 생성.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
세션 변경사항을 분석하여 검증 스킬 누락을 탐지합니다. 기존 스킬을 동적으로 탐색하고, 새 스킬을 생성하거나 기존 스킬을 업데이트한 뒤 CLAUDE.md를 관리합니다.
REST API 응답 DTO 일관성 및 에러 코드 표준 검증. API 엔드포인트 추가/수정, DTO 변경, 에러 처리 수정 후 사용. API 계약 변경이 프론트엔드에 영향을 줄 수 있을 때 사용.
Flyway DB 마이그레이션 일관성 검증. 마이그레이션 추가/수정 후 사용.
프론트엔드 UI 컴포넌트 품질 검증 (shadcn/ui + Tailwind 기준). UI 컴포넌트 수정 후 사용.
KB 비동기 인덱싱 파이프라인 검증. 인덱싱 관련 코드 수정 후 사용.
RAG 파이프라인 (답변 작성 + 분석 + 다운로드) 검증. 답변 작성/분석/다운로드 관련 코드 수정 후 사용.
| name | add-api-endpoint |
| description | REST API 엔드포인트 스캐폴딩 (Controller → UseCase → Service → JPA, DDD 패턴). 새 API 추가, 엔드포인트 생성, CRUD 구현 요청 시 사용. 백엔드에 새 기능을 추가할 때 DDD 레이어 구조를 자동 생성. |
DDD 레이어 구조에 맞춰 REST API 엔드포인트를 스캐폴딩합니다. Controller → UseCase → Service → Repository 각 레이어의 코드를 생성합니다.
interfaces/rest/ ← Controller (Request/Response DTO)
↓ calls
application/usecase/ ← UseCase Interface + Command/Result DTOs
↓ implements
application/service/ ← Service (@Transactional, 비즈니스 로직)
↓ uses
domain/repository/ ← Repository Interface (순수 도메인)
↓ implements
infrastructure/persistence/ ← JPA Entity + Repository Adapter
경로: backend/app-api/src/main/java/com/biorad/csrag/interfaces/rest/{domain}/
@RestController
@RequestMapping("/api/v1/{domain}")
@RequiredArgsConstructor
public class XxxController {
private final XxxUseCase xxxUseCase;
@PostMapping
public ResponseEntity<XxxResponse> create(@Valid @RequestBody CreateXxxRequest request) {
XxxCommand cmd = new XxxCommand(request.field1(), request.field2());
XxxResult result = xxxUseCase.execute(cmd);
return ResponseEntity.status(HttpStatus.CREATED).body(XxxResponse.from(result));
}
@GetMapping("/{id}")
public ResponseEntity<XxxResponse> getById(@PathVariable UUID id) {
return ResponseEntity.ok(XxxResponse.from(xxxUseCase.getById(id)));
}
}
Request/Response는 record로 정의:
public record CreateXxxRequest(
@NotBlank String field1,
@Size(max = 500) String field2
) {}
public record XxxResponse(UUID id, String field1, String status, OffsetDateTime createdAt) {
public static XxxResponse from(XxxResult result) { ... }
}
// UseCase 인터페이스
public interface XxxUseCase {
XxxResult execute(XxxCommand command);
XxxResult getById(UUID id);
}
// Command (입력 DTO)
public record XxxCommand(String field1, String field2) {}
// Result (출력 DTO)
public record XxxResult(UUID id, String field1, String status, OffsetDateTime createdAt) {}
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class XxxService implements XxxUseCase {
private final XxxRepository xxxRepository;
@Override
@Transactional
public XxxResult execute(XxxCommand command) {
Xxx entity = Xxx.create(command.field1(), command.field2());
Xxx saved = xxxRepository.save(entity);
return toResult(saved);
}
@Override
public XxxResult getById(UUID id) {
Xxx entity = xxxRepository.findById(id)
.orElseThrow(() -> new NotFoundException("Xxx", id));
return toResult(entity);
}
}
팩토리 메서드 패턴 (퍼블릭 생성자 없음):
public class Xxx {
private UUID id;
private String field1;
private String status;
private OffsetDateTime createdAt;
private Xxx() {} // JPA용
// 신규 생성
public static Xxx create(String field1, String field2) {
Xxx xxx = new Xxx();
xxx.id = UUID.randomUUID();
xxx.field1 = field1;
xxx.status = "ACTIVE";
xxx.createdAt = OffsetDateTime.now();
return xxx;
}
// DB에서 복원
public static Xxx reconstitute(UUID id, String field1, String status, OffsetDateTime createdAt) {
Xxx xxx = new Xxx();
xxx.id = id;
xxx.field1 = field1;
xxx.status = status;
xxx.createdAt = createdAt;
return xxx;
}
}
@Entity
@Table(name = "xxx")
public class XxxJpaEntity {
@Id
@Column(columnDefinition = "UUID")
private UUID id;
// fromDomain / toDomain 변환 메서드 필수
public static XxxJpaEntity fromDomain(Xxx domain) { ... }
public Xxx toDomain() { ... }
}
@Repository
public class XxxRepositoryAdapter implements XxxRepository {
private final SpringDataXxxJpaRepository jpaRepository;
// 도메인 ↔ JPA 변환 처리
}
/add-flyway-migration 스킬을 사용하여 테이블을 생성합니다.
GlobalExceptionHandler가 공통 예외를 처리합니다:
// 이미 정의된 예외 클래스 사용
throw new NotFoundException("Xxx", id); // 404
throw new ConflictException("Xxx already exists"); // 409
throw new BadRequestException("Invalid input"); // 400
에러 응답 형식:
{
"error": {
"code": "NOT_FOUND",
"message": "Xxx not found: {id}",
"status": 404,
"requestId": "...",
"timestamp": "..."
}
}
@RestController, @Valid, ResponseEntity 사용from() 변환 메서드@Transactional(readOnly = true) 기본, 쓰기는 @Transactional| File | Purpose |
|---|---|
backend/contexts/inquiry-context/ | 가장 완성된 DDD 컨텍스트 참고 |
backend/app-api/src/main/java/.../interfaces/rest/ | 기존 Controller 참고 |
backend/app-api/src/main/java/.../common/exception/ | 공통 예외 클래스 |