[SpringDoc] 쿼리 파라미터가 이상하다?
SpringFox에서 SpringDoc으로 마이그레이션하던 와중, 몇가지 이슈가 발생했다. (참고글: [SpringDoc] SpringFox -> SpringDoc 마이그레이션 일지) 그 중에서도 쿼리 파라미터와 관련된 이슈들을 해당 글에서 정리해보고자 한다.
❓ Swagger에서 @ModelAttribute request를 json 형태로 받는 현상
스프링에서 @ModelAttribute를 이용하면 쿼리 파라미터 목록을 DTO로 받을 수 있다. 이때 SpringFox에서는 아래와 같이 필드 하나하나를 따로 입력받을 수 있었다.
하지만 SpringDoc에서는 아래와 같이 json 형태로 입력하도록 변경되었다. 쿼리 파라미터를 따로 입력하고 싶다는 요구사항이 들어와서 방법을 고민하게 되었다.
💡 해결방법: @ParameterObject 추가
위 문제에 대해 SpringDoc 이슈에서도 언급이 나왔으나, REST API스럽지 않다(?)는 이유로 지원 계획이 없다고 밝혔다. (참고 링크: SpringDoc issue - Add support for @ModelAttribute annotations) 대신 다른 방안을 추천하고 있다. 바로 @ParameterObject이다. DTO 또는 Controller에서 인자로 받을 때 해당 어노테이션을 붙여주면 된다.
// 예제 코드 - DTO에 붙였지만 Controller에서 인자로 받을 때 붙여도 괜찮습니다.
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ParameterObject
@Schema(description = "Page 조건")
public class PageRequestCondition { ... }
❓ @ParameterObject를 사용하는 경우 모든 필드를 String으로 인식하는 현상
@ParameterObject와 @Schema를 함께 사용하는 경우, 숫자 타입의 필드도 String으로 인식하는 문제가 발생하였다. SpringDoc에서 제시하는 해결 방법들을 살펴보자. (참고: https://github.com/springdoc/springdoc-openapi/issues/1926)
💡 해결방법 1: @Schema의 type 속성 지정
@Schema에는 해당 필드의 타입이 무엇인지 명시적으로 지정할 수 있는 'type'이라는 속성이 존재한다. 이를 지정하면 내가 원하는 타입으로 변경할 수 있다. 헌데 필드마다 type 지정하는게 번거롭게 느껴졌다. 또, 변수 선언 시 이 필드에 대한 타입은 이것입니다~라고 명시했다고 생각했는데 어노테이션의 속성에 타입을 또 지정해줘야하는, 중복 작업이 반복된다고 느껴졌다.
@Schema(description = "회원 번호", type = "integer")
private Long memberNo;
💡 해결방법 2: @Schema 대신 @Parameter로 대체
@Schema 대신 @Parameter를 사용하면 위 문제가 발생하지 않는다. 허나 두 어노테이션은 사용 목적이 다르기 때문에 이 방법 역시 임시 방편이라는 생각이 들었다.
// @Schema(description = "회원 번호", type = "integer")
@Parameter(description = "회원 번호")
private Long memberNo;
@Schema vs @Parameter
- @Schema: 모델의 설명, 이름, 유형, 예시 값을 지정
- @Parameter: 매개변수의 이름, 설명, 예시 값을 지정
빠른 해결을 위해 현재는 해당 방법을 이용해 해결해두었다. SpringDoc 마이그레이션 작업이 영향범위가 넓다보니 작업이 길어질수록 코드 충돌이 커지기 때문이다.🥲
➕ 만약 @Paramter와 @Schema 둘 다 사용하고 싶다면?
// @Parameter와 @Schema 둘 다 쓰고싶은 경우, schema 속성을 활용하자.
@Parameter(
description = "회원 번호",
required = true,
schema = @Schema(description = "회원 번호")
)
마치며
이로써 SpringFox를 SpringDoc으로 전환하던 일지는 모두 마쳤다. 작업 자체는 12월 말~1월 중에 진행했던건데 회사에서 정신없는 일이 워낙에 많았다보니 글을 쓸 시간도 부족해서 이제야 마무리 지었다. 여러 이슈들 중에서도 이 포스트에서 다룬 이슈들은 해결은 했어도 아직 찜찜함이 남아있다. 다른 사람들이 코드를 작성하기 더 쉽도록 만들 수 있을 것 같은데 아직 속시원한 해결 방안을 못찾아서 현재 진행형으로 고민중이다.