VO를 통한 GET query params의 처리와 명세(feat. Swagger)

Minjae An·2024년 2월 28일
0

Spring Web

목록 보기
9/9
post-custom-banner

@GetMapping시 파라미터 처리

@GetMapping("/users")
public ResponseEntity<UserPageRes> users(
	@RequestParam("page") @NotNull @PositiveOrZero int page,
	@RequestParam("size") @NotNull @Positive int size){
	// ...
}

스프링에서 @GetMapping 이용하여 API 로직을 구성할 때 쿼리 스트링에 포함되는 파라미터들의 경우 위와 같이 이름을 기반으로 매칭하여 처리할 수 있다. 사실 기본적으로 @GetMapping 을 사용하면 파라미터들을 쿼리 스트링에서 탐색하기 때문에 위 예시 코드에서 @RequestParam 은 생략 가능하다.

하지만 만약에 받아야 할 파라미터들이 많아 위와 같이 작성하였을 때 코드가 너저분해지는 문제는 어떻게 해결할 수 있을까?

VO를 활용

VO란?

불변한 객체로, 단순히 값의 집합을 캡슐화하여 나타낼 때 주로 사용한다. 값의 불변성을 보장하는 데 초점이 맞춰져 있는 객체이다.

Controller - API

@GetMapping("/users")
public ResponseEntity<UserPageRes> users(UserPageReq request){ ... }

UserPageReq

@Getter
@AllArgsConstructor
public class UserPageReq {

  @NotNull
  @PositiveOrZero
  private int page;

  @NotNull
  @Positive
  private int size;
}

요청 파라미터들을 저장할 VO를 정의하고 위와 같이 코드를 작성하면 자동으로 필드 이름을 기반으로 파라미터들을 매핑하여 처리해준다.

@ParameterObject와 @Parameter 활용 명세

앞서 VO를 활용하여 쿼리 파라미터를 처리한 API를 swagger를 활용하여 명세하기 위해 다음과 같이 UserPageReq 필드들에 @Parameter 를 활용하여 코드를 작성하였다.

package com.example.springallinoneproject.team;

import io.swagger.v3.oas.annotations.Parameter;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.PositiveOrZero;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class UserPageReq {

  @Parameter(
      name = "page",
      description = "페이지 번호",
      example = "1"
  )
  @NotNull
  @PositiveOrZero
  private int page;

  @Parameter(
      name = "size",
      description = "페이지 사이즈(한 페이지당 데이터 수)",
      example = "10"
  )
  @NotNull
  @Positive
  private int size;
}

이어서 API 로직에도 명세를 해주었다.

@Operation(
    summary = "사용자 목록 조회",
    description = "사용자 목록을 조회할 수 있습니다."
)
@ApiResponse(
    responseCode = "200",
    description = "사용자 목록 조회 성공"
)
@GetMapping("/users")
public ResponseEntity<UserPageRes> users(UserPageReq request){
    // ...
}

하지만 위와 같이 코드를 구성하면 swagger-ui 상에서 UserPageReq 의 필드들을 파라미터 형태로 요청할 수 있게 표시되지 않는다. 이는 @ParameterObject 어노테이션을 활용하면 아주 간단하게 해결할 수 있다.

@Operation(
    summary = "사용자 목록 조회",
    description = "사용자 목록을 조회할 수 있습니다."
)
@ApiResponse(
    responseCode = "200",
    description = "사용자 목록 조회 성공"
)
@GetMapping("/users")
public ResponseEntity<UserPageRes> users(
    @ParameterObject UserPageReq request){
    // ...
}

참고 사항으로 쿼리 파라미터중 /users?age=10,12 형태로 요청되는 파라미터를 명세하고 싶다면 @Parameterexplode 속성을 Explode.FALSE 로 설정해주면 된다. 다만, swagger-ui 상에서 테스트 요청을 수행할 때는 기본적으로 Explode.TRUE 옵션으로 파라미터를 처리하기에 이 부분에 골머리를 앓을 필요는 없다.

예시 코드

@Getter
@AllArgsConstructor
public class UserQueryRequest {
	// ...
	@Parameter(
      name = "age",
      description = "나이 범위(하한,상한), 사용자 검색시 사용",
      example = "20,25",
      in = ParameterIn.QUERY,
      explode = Explode.FALSE
  )
  private List<Integer> ages;
	// ...
}

swagger-ui 상에서 표기(명세)

profile
먹고 살려고 개발 시작했지만, 이왕 하는 거 잘하고 싶다.
post-custom-banner

0개의 댓글