Skip to content

[Feat] 프롬프트 생성 API 구현 (4차) #33

Description

@Hanharam

이 이슈는 이미지 업로드·워터마크 파이프라인의 4차 작업입니다.

선행 작업: #40 이미지 자산 DB·도메인 구조 → 업로드 API → 워터마크 처리·조회 API

어떤 기능인가요?

기존 API 계약 이슈 #23을 기반으로 POST /api/v1/prompts의 실제 비즈니스 로직과 영속성을 구현합니다.

인증된 사용자가 프롬프트 본문, 공개 범위, 태그, 업로드 및 워터마크 처리가 완료된 이미지를 제출하면 서버가 가격과 게시 상태를 결정하고 프롬프트·태그·이미지·초기 통계를 하나의 트랜잭션으로 저장합니다. 현재 NotImplementedException으로 반환되는 501 응답을 실제 201 Created 응답으로 교체합니다.

관련 도메인

  • prompt
  • user (작성자 식별만 사용)

선행 조건

  • [Feat] 프롬프트 이미지 DB 및 도메인 구조 구현 #40 이미지 자산 DB 및 도메인 구조가 병합되어야 한다.
  • 이미지 업로드 준비·완료 API가 구현되어야 한다.
  • 워터마크 처리 및 이미지 상태 조회 API가 구현되어야 한다.
  • 프롬프트 생성 시 사용할 이미지는 READY 상태여야 한다.

요구사항

생성 및 권한

  • 작성자 식별자는 요청 DTO가 아니라 AuthenticatedUserPrincipal에서 추출한다.
  • 존재하며 정상 상태인 사용자만 프롬프트를 생성할 수 있다.
  • 생성 완료된 프롬프트 상태는 ACTIVE로 저장한다.
  • visibility 미입력 시 PUBLIC을 적용하고 PUBLIC | PRIVATE만 허용한다.
  • 성공 시 201 CreatedPromptCommandResponse를 반환한다.

콘텐츠 및 가격 정책

  • title, promptBody, outputType, contentType 필수값과 기존 Bean Validation 계약을 검증한다.
  • contentTypeFREE | PREMIUM만 허용한다.
  • 요청에서 가격을 입력받거나 클라이언트 값으로 가격을 결정하지 않는다.
  • FREE 가격은 서버에서 0으로 결정한다.
  • PREMIUM 가격은 서버 설정값에서 조회한다.
  • 응답의 pricePoint에는 서버에서 결정한 값을 반환한다.
  • 유료 프롬프트 원문은 생성 응답에 포함하지 않는다.

태그

  • jobTagIds, taskTagIds, aiModelTagIds에 전달된 태그의 존재 여부와 타입 일치를 검증한다.
  • 중복 태그 ID를 정규화하거나 명확한 오류로 거절한다.
  • customAiModel은 소문자 변환 및 모든 공백 제거 후 정규화된 이름을 기준으로 조회·생성한다.
  • 프롬프트와 태그 연결 정보를 저장한다.

이미지

  • 이미지가 최대 10개인지 검증한다.
  • imageIdREADY 상태이며 현재 요청자가 사용할 수 있는 이미지인지 서버에서 확인한다.
  • 이미지 정렬 순서와 썸네일 최대 1개 정책을 검증한다.
  • 검증된 이미지만 프롬프트에 연결하고 원본 Object Key나 임의 URL을 신뢰하지 않는다.
  • 이미지가 있으면 지정된 썸네일을 대표 이미지로 사용한다.

영속성 및 트랜잭션

  • CreatePromptCommand, CreatePromptUseCase, Command Service를 정의한다.
  • application 계층이 Spring Data Repository에 직접 의존하지 않도록 outbound port와 persistence adapter를 구현한다.
  • 프롬프트, 태그 연결, 이미지 연결, 초기 통계 저장을 하나의 @Transactional 경계에서 처리한다.
  • 초기 조회수·좋아요수·복사수 등 통계값을 0으로 생성한다.
  • PromptVisibility 등 현재 API 계약과 DB 모델 간 누락 필드를 반영하고 필요한 DB 마이그레이션을 추가한다.
  • 저장 실패 시 일부 데이터만 남지 않도록 전체 작업을 롤백한다.

오류 응답

  • 인증 정보가 없으면 401 Unauthorized를 반환한다.
  • 요청 값 또는 태그 타입이 잘못되면 400 Bad Request를 반환한다.
  • 사용자, 태그 또는 이미지가 존재하지 않으면 도메인 정책에 맞는 404 Not Found를 반환한다.
  • 이미 사용되었거나 사용할 수 없는 이미지 등 충돌 상태는 명확한 도메인 오류로 반환한다.

TODO

  • 생성 Command/Info/UseCase 및 Command Service 구현
  • 프롬프트·태그·이미지·통계 outbound port 정의
  • JPA Repository 및 Persistence Adapter 구현
  • 도메인 모델과 JPA 모델의 생성 상태·공개 범위 정합성 보완
  • 프리미엄 가격 설정값 추가
  • PromptController#createPrompt를 UseCase에 연결
  • Controller 테스트의 501 기대값을 실제 생성 계약으로 변경
  • 도메인·UseCase·Persistence·Controller 테스트 추가
  • 전체 테스트 및 API 문서 계약 검증

완료 조건

  • 정상 요청이 201 Created와 생성된 promptId, ACTIVE, visibility, pricePoint, updatedAt을 반환한다.
  • 프롬프트와 연관 데이터가 하나의 트랜잭션으로 저장된다.
  • 서버가 가격과 이미지 사용 권한을 결정하며 클라이언트가 이를 우회할 수 없다.
  • 주요 성공·실패 경로에 대한 테스트가 통과한다.

참고 자료

제출 전 확인사항

  • 동일하거나 유사한 구현 이슈가 없는지 확인했습니다.
  • 유료 콘텐츠 원문 노출 정책에 영향을 확인했습니다.
  • API 계약 작업과 실제 구현 범위를 분리했습니다.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions