섭섭한 개발일지

[Swagger] Java DTO를 Record로 사용 시 Swagger 오류 본문

프로그래밍/Spring

[Swagger] Java DTO를 Record로 사용 시 Swagger 오류

Seop 2024. 7. 19. 04:01

프로젝트 본격적인 개발에 앞서 Swagger 작성을 하던 중 Java record에서 발생한 문제점에 대한 게시글이다.

git repo

 

개발 환경
Java version : 21 (Amazon Corretto)
Springboot version :  3.2.5
Swagger dependencies : org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0

 


 

상황

이번 프로젝트에서는 DTO를 record를 이용하여 작성하기로 했다.

협업을 위해 Controller에서 request와 response를 먼저 작성하여 Swagger 문서를 만들어두기로 하여 작업을 진행하였다.

get, post 와 관련된 Controller를 작성하여 Swagger 문서를 확인해 봤는데 request와 response의 data가 모두 동일하게 작성되는 문제가 발생했다.

(편의상 request와 response가 동일한 문제를 발생함으로 내용에서는 response만 다루도록 한다.)

[GET]
[POST]

 


 

문제 파악 과정

BoardController

@Slf4j
@Tag(name = "Board-API", description = "게시판 API")
@RequiredArgsConstructor
@RestController
@RequestMapping("/board")
public class BoardController {
    private final BoardService service;

    @Operation(summary = "ID 게시글 조회")
    @GetMapping("/{id}")
    public ResponseEntity<FindBoardDto.Response> findBoard(@PathVariable Long id) {
        FindBoardDto.Response response = service.findOne(id);
        return ResponseEntity.ok().body(response);
    }

    @Operation(summary = "전체 게시글 조회")
    @GetMapping
    public ResponseEntity<List<FindBoardDto.Response>> findAllBoard() {
        List<FindBoardDto.Response> response = service.findAll();
        return ResponseEntity.ok().body(response);
    }
    
    @Operation(summary = "게시글 작성")
    @PostMapping
    public ResponseEntity<AddBoardDto.Response> addBoard(AddBoardDto.Request request) {
        AddBoardDto.Response response = service.addBoard(request);
        return ResponseEntity.created(null).body(response);
    }
}

 

여기서 각 메서드의 반환 객체를 보면 FindBoardDto.ResponseAddBoardDto.Response로 되어 있다.

 

FindBoardDto

public record FindBoardDto() {
    @Builder
    public record Response(
            Long id,
            String title,
            String content
    ) {}

    public static FindBoardDto.Response of(Board board) {
        return Response.builder()
                .id(board.getId())
                .title(board.getTitle())
                .content(board.getContent())
                .build();
    }
}

 

AddBoardDto

public record AddBoardDto() {
    public record Request(
            String title,
            String content) {}

    @Builder
    public record Response(Long id) {}

    public static Board toEntity(AddBoardDto.Request request) {
        return Board.builder()
                .title(request.title)
                .content(request.content)
                .build();
    }

    public static AddBoardDto.Response of(Long id) {
        return Response.builder().id(id).build();
    }
}

 

DTO를 record로 생성하였고

각 DTO 별로 Request와 Response를 작성하여 관리하였다.

 

이렇게 구현을 해두고 Swagger 문서를 확인해보니

Swagger

 

각 API의 Responses 데이터가 동일하게 id만 나오는 문제가 발생했다.

뭐가 문제일까.. 여러 테스트를 진행했다.

 

 

 

1.

id 라는 responses가 어디서 나온건지 확인을 위해

id만을 반환하는 게시글 작성 부분 중 Response에서 사용하는 id의 이름을 변경했다.

AddBoardDto class

 

swagger

 

AddBoardDto의 Response 값의 id를 boardId로 변경을 하니 모든 스웨거의 반환 값이 boardId 로 변경이 됐다.

FindBoardDto의 Response가 적용이 되지 않는 문제인 것이다.

 

project clean, rebuild project 등을 하고 실행을 해도 문제는 같았다.

 

 

 

2.

Controller @Operation 상세 설정도 진행했다.

BoardController

 

그래도 결과는 동일했다.

GET 메서드의 반환 값에 id만 존재한다....

 

 

 

3.

Google에 검색을 해봐도 이와 같은 경우는 찾기가 어려웠다.

그나마 record를 사용하여 Swagger를 사용하는 프로젝트의 질문을 찾았다. 질문

 

질문에서 나온 답변을 프로젝트에 동일하게 구현을 해봤다.

AddBoardDto.Response
FindBoardDto.Response

 

swagger

 

이번엔 id가 아닌 FindBoardDto.Response의 값이 responses에  도배가 되었다..

 

 

 

4.

GPT에게 물어봤다..

chatGPT

 

딱히 도움이 되지는 않았다..

 

 

 

5.

계속해서 코드를 수정하던 중 record 특징인 불변 객체의 문제가 아닐까.. 해서

FindBoardDto.ResponseFindBoardDto.Response2로 변경해봤다.

 

정상으로 나왔다.

이때는 record의 문제라고 생각을 했다.

이를 토대로 gpt에 한번 더 질문을 해봤다.

chatGPT

 

내부 클래스 이름 충돌과 런타임 시점에 문제가 있을 것이라고 힌트를 줬다.

record 문제로 결론을 내리려는 중

 

과연 build가 어떻게 되길래 이럴까 Response 이름을 원복하고 build된 파일들을 봤다.

 

[build] AddBoardDto.Response
[build] FindBoardDto.Response

 

빌드된 파일을 봤을땐 서로 충돌이 발생하지 않고 정상적으로 각자의 Response가 생성이 된 것이 보인다.

 

혹여나 record의 문제가 아니지 않을까 라는 생각으로 postman을 통해 값을 확인해봤다.

[PostMan] 게시글 작성

 

[PostMan] 게시글 조회

 

API에서는 정상 동작하는게 확인된다..

record의 문제가 아닌 것이다..

 

Swagger의 문제인 것....

기능은 정상 작동을 잘 한다...

 

이걸 어떻게 해결을 해야할까

 


 

현재까지의 결론

이 문제에 대해서 아직 해결 방안을 찾지 못했다.

시간이 늦어졌으니.. 오늘은 여기까지하고 단잠을 청해야겠다...

내일 아침에는 해결 방안이 떠오르기를...

Comments