diff --git a/src/main/java/com/grabpt/controller/SuggestionController.java b/src/main/java/com/grabpt/controller/SuggestionController.java index 1e61d8f..5159d21 100644 --- a/src/main/java/com/grabpt/controller/SuggestionController.java +++ b/src/main/java/com/grabpt/controller/SuggestionController.java @@ -26,6 +26,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Encoding; import io.swagger.v3.oas.annotations.media.ExampleObject; @@ -46,38 +47,67 @@ public class SuggestionController { @Operation( summary = "제안서 저장 API (Multipart)", - description = "트레이너가 보낸 제안서를 저장합니다. JSON(`data`) + 이미지 리스트(`photos`)로 업로드하세요." + description = "트레이너가 보낸 제안서를 저장합니다. `data`(JSON)와 `photos`(이미지 리스트)를 함께 업로드하세요." ) @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse( responseCode = "200", description = "저장 성공", - content = @Content(schema = @Schema(implementation = SuggestionResponseDto.SuggestionSaveResponseDto.class)) + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = SuggestionResponseDto.SuggestionSaveResponseDto.class), + examples = @ExampleObject(name = "성공 예시", value = """ + { + "isSuccess": true, + "code": "OK", + "message": "요청에 성공했습니다.", + "result": { "suggestionId": 123 } + } + """) + ) ) }) - // 1. Swagger가 multipart 내부의 각 파트 타입을 알 수 있도록 RequestBody 설정을 추가합니다. + // 핵심: Swagger UI가 multipart 각 필드를 인식하도록 메서드 레벨에서 정의 @io.swagger.v3.oas.annotations.parameters.RequestBody( content = @Content( mediaType = MediaType.MULTIPART_FORM_DATA_VALUE, - schema = @Schema(type = "object"), // 전체를 오브젝트로 정의 - encoding = { - @Encoding(name = "data", contentType = MediaType.APPLICATION_JSON_VALUE), // data 파트는 JSON임을 명시 - @Encoding(name = "photos", contentType = MediaType.IMAGE_JPEG_VALUE) // 사진 파트 설정 (생략 가능) - } + schema = @Schema(type = "object"), + encoding = @Encoding(name = "data", contentType = MediaType.APPLICATION_JSON_VALUE), + examples = @ExampleObject( + name = "data 예시", + summary = "제안서 본문 예시", + value = """ + { + "requestionId": 77, + "price": 50000, + "sessionCount": 10, + "message": "안녕하세요, 반갑습니다.", + "location": "성북동", + "sentAt": "2025-10-01", + "isMatched": false + } + """ + ) ) ) @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ApiResponse setSuggestion( - // 2. @RequestPart를 사용하되, 복잡한 @Parameter 설정은 위 RequestBody로 옮겼으므로 간단하게 유지합니다. + // Swagger UI에서 이 파트를 JSON 입력창으로 인식하게 함 @RequestPart("data") SuggestionRequestDto dto, - @RequestPart(value = "photos", required = false) List photos, + + // Swagger UI에서 이 파트를 '파일 선택' 버튼으로 인식하게 함 (format = binary 필수) + @RequestPart(value = "photos", required = false) + @Parameter( + description = "첨부 이미지 배열", + content = @Content(array = @ArraySchema(schema = @Schema(type = "string", format = "binary"))) + ) + List photos, + HttpServletRequest request ) throws IllegalAccessException { - // 사용자 정보 추출 UserResponseDto.UserInfoDTO userInfo = userQueryService.getUserInfo(request); String email = userInfo.getEmail(); - // 서비스 호출 Suggestions saved = suggestionService.save(dto, email, photos); return ApiResponse.onSuccess(