-
[appling] Controller 추가하기 (Api Annotation 추가, Swagger 적용)appling 프로젝트 2024. 9. 8. 13:10728x90반응형
🔴 Controller 만들기
지금까지 Service만 작성하고 실제로 Controller는 작성하지 않았다. 이제 Controller를 적용해보자.
🟠 Controller 적용하기
🟢 기존 Controller 쓰기
@RestController @RequestMapping("/api/v1") public class ProductController { }
RestController를 적용하고 기본 값으로
/api/v1
을 붙여주려고 한다. 근데 만드는 Controller마다 붙이는게 너무 귀찮을거 같아 Annotation으로 설정하려고 하다.🟢 @ApiController 만들기
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @RestController @RequestMapping("/api/v1") public @interface ApiController { }
@ApiController
를 Annotation으로 정의하고@ApiController public class ProductController { }
기존에 Controller 적용 대신 다음과 같이 적용해준다.
🟠 Swagger 적용하기
🟢 Controller 처리
@ApiController @RequiredArgsConstructor @Tag(name = "Product API", description = "Product API Documentation") public class ProductController { private final ProductService productService; @PostMapping("/product") @Operation(summary = "상품 등록", description = "상품 등록 api") @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "정상", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)), }) public ResponseEntity<ResponseData<PostProductResponse>> product(@RequestBody @Validated PostProductRequest productRequest, BindingResult bindingResult) { if (bindingResult.hasErrors()) { Map<String, String> errors = new HashMap<>(); bindingResult.getFieldErrors().forEach(error -> errors.put(error.getField(), error.getDefaultMessage())); return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body(ResponseData.from(ResponseDataCode.SUCCESS, errors)); } return ResponseEntity.status(HttpStatus.CREATED) .body(ResponseData.from(ResponseDataCode.SUCCESS, productService.createProduct(productRequest))); } }
상품 Controller에
@Tag()
를 추가해주고 각 Url에 대한 설명을 위해@Operation()
@ApiResponse()
를 추가해준다.그리고 Controller에 추가적으로
@Validated
와BindingResult
를 추가로 적용하여 유효성 검사를 추가해준다.@Getter @Builder @AllArgsConstructor @NoArgsConstructor public class PostProductRequest { @NotNull(message = "상품명을 입력해 주세요.") @JsonProperty("product_name") @Schema(description = "상품명", example = "아리수") private String productName; @NotNull(message = "상품 무게를 입력해 주세요.") @JsonProperty("product_weight") @Schema(description = "상품 무게", example = "5") private int productWeight; @NotNull(message = "상품 타입을 입력해 주세요. ex) 사과는 11과") @JsonProperty("product_type") @Schema(description = "상품 타입", example = "11과") private String productType; @NotNull(message = "상품 가격을 입력해 주세요.") @JsonProperty("product_price") @Schema(description = "상품 가격", example = "100000") private int productPrice; @NotNull(message = "상품 수량을 입력해 주세요.") @JsonProperty("product_stock") @Schema(description = "상품 수량", example = "100") private int productStock; ... }
Request에 Swagger에 대한 추가 설정을 한다.
Swagger 추가 설정을 통해 테스트 시 기본 값과 API의 요청 Schema에 대한 설명을 추가해두었다.
@Entity @Table(name = "product") @AllArgsConstructor(access = AccessLevel.PROTECTED) @NoArgsConstructor(access = AccessLevel.PROTECTED) @Builder @Getter public class ProductEntity extends CommonEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long productId; private String productName; private int productWeight; private String productType; @Enumerated(EnumType.STRING) private ProductStatus productStatus; private int productPrice; private int productStock; ... }
추가로 Entity에
@Enumerated(EnumType.STRING)
를 추가해두었다.🟢 반환 데이터 정의하기
@ApiController @RequiredArgsConstructor @Tag(name = "Product", description = "Product API Documentation") public class ProductController { private final ProductService productService; @PostMapping("/product") @Operation(summary = "상품 등록", description = "상품 등록 api") @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "정상", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = PostProductResponse.class))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)), }) public ResponseEntity<ResponseData<PostProductResponse>> product(@RequestBody @Validated PostProductRequest productRequest) { return ResponseEntity.status(HttpStatus.CREATED) .body(ResponseData.from(ResponseDataCode.CREATE, productService.createProduct(productRequest))); } ... }
기존 Controller에서 반환할때 데이터도 추가하려고 한다.
@ApiResponse(responseCode = "201", description = "정상", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = PostProductResponse.class))),
해당 부분의
schema
데이터를 추가하여 주면 반환하는 데이터의 형식도 예시로 보여줄 수 있다.@JsonInclude(JsonInclude.Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) @Builder @Schema(description = "상품 등록 반환 데이터") public record PostProductResponse( @Schema(description = "상품번호", example = "1") Long productId ) { public static PostProductResponse createFrom(ProductEntity saveProduct) { return PostProductResponse.builder() .productId(saveProduct.getProductId()) .build(); } }
반환되는 class도 다음과 같이 정의해주면 된다.
그러면 반환 시 데이터 예시를 정의해 둘수 있고
schema를 클릭하면 반환 데이터의 설명도 확인해 볼 수 있다.
나머지 get, put도 수정해두었는데 해당 부분은 깃 소스를 통해 확인해주시면 된다!
728x90반응형'appling 프로젝트' 카테고리의 다른 글
[appling] 나머지 Controller 작업 및 Test Code 추가 작성 (1) 2024.09.08 [appling] Controller 예외처리 (Advice, Validation) (0) 2024.09.08 [appling] Querydsl 적용하기 (with. SpringBoot 3.3, build.gradle.kts) (0) 2024.09.05 [appling] Domain 테스트코드 작성 (2) 2024.09.04 [appling] Product 수정 (0) 2024.09.04