[Spring] - springdoc-openapi 구조 미노출 이슈

🛠️ 개발 환경

  • kotlin : 2.1.10
  • Spring Boot : 3.3.10

💬 상황 설명

우선 현재 사용 중인 springdoc의 버전은 다음과 같다.

implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0")

코틀린 + 스프링 부트를 기반으로 API를 개발하면서, 다음과 같은 형태로 API의 request/response 클래스를 설계했다.

object ApiPostProductBacklog {
    const val PATH = "/api/v1/product-backlog"

    data class Request(
        val title: String,
        val description: String,
        val priority: ProductBacklogPriority
    )

    data class Response(
        val productBacklogRowid: Long
    )
}

이렇게 설계하면, 경로 상수를 함께 관리할 수 있고, request/response 모델도 한 눈에 파악할 수 있어 도메인 단위로 API를 정리하기 좋을 것 같아 이런 형태로 설계했다.

 

하지만 문제는 Swagger 문서에서 발생했다. 위 코드를 기반으로 컨트롤러를 작성했을 때, 다음과 같은 이상한 현상이 발생했다.

실제로 많은 필드를 넣었는데도, title 필드만 보여지는 것이다.

✅ 해결 과정

검색을 하던 중, springdoc 리포지토리의 issue#32를 찾았는데, DTO의 구조가 나와 비슷하다는 것을 알게 되었다. 내용을 간략히 요약하면 다음과 같다.

Java에서 static inner class를 사용했을 때, Swagger 문서에 보여지지 않는 이슈가 있다.

 

Kotlin 코드를 컴파일할 때, 내부적으로 생성하는 클래스 구조와 관련이 있으며, springdoc-openapi가 리플렉션을 통해 필드 정보를 읽어오는 과정에서 일부 필드가 누락되는 것으로 파악되었다.

 

내부 클래스에 대한 사용이 제한되기 때문에, 결국 object의 내부 클래스가 아닌, 따로 분리를 하게 되었다.

data class ProductBacklogRequest(
    val title: String,
    val description: String,
    val priority: ProductBacklogPriority
)

data class ProductBacklogResponse(
    val productBacklogRowid: Long
)

그 결과 정상적으로 모든 데이터가 잘 보이도록 수정되었다.

🤔 회고

Kotlin의 object는 싱글턴으로 설계되는 특성이 있어, DTO를 같이 묶어두는 용도로 많이 쓰이기도 한다. 하지만 Swagger 문서를 자동 생성할 때 사용되는 springdoc-openapi에서는 내부 클래스를 완전하게 분석하지 못해, API 문서가 일부만 생성되는 문제가 발생할 수 있다.

 

현재로서는 해결되지 않은 이슈이기 때문에, Swagger 문서를 정상적으로 출력하려면, object 내부에 클래스를 두는 것이 아닌, 최상위에 클래스를 두는 것이 안전할 것 같다.