문제 상황
모듈식 모놀리스로 전환 후 Swagger API를 사용하여 API 명세를 손쉽게 하려고 세팅했었다. 하지만 Parameters 를 인식하지 못 하는 상황이 발생하게 되었다


코드 뜯어보기
우선 코드를 살펴보자면 저자는 Controller와 인터페이스를 사용한 Swagger API를 명확히 나눴다
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/posts")
public class PostController implements PostAPI {
private final PostService postService;
@PostMapping
public Long createPost(
@Valid @RequestBody PostCreateRequest request
){
return postService.createPost(request);
}
@GetMapping
public List<PostResponse> findPosts(){
return postService.getAllPosts();
}
@GetMapping("/{postId}")
public PostResponse findPostById(
@PathVariable Long postId
){
return postService.findPostById(postId);
}
@PatchMapping("/{postId}")
public PostResponse updatePost(
@Valid @RequestBody PostUpdateRequest request,
@PathVariable Long postId
){
Long post = postService.updatePost(postId, request);
return postService.findPostById(post);
}
@DeleteMapping("/{postId}")
public void deletePost(
@PathVariable Long postId
){
postService.deletePost(postId);
}
}
@Tag(name = "Post", description = "게시글 API")
public interface PostAPI {
@Operation(summary = "게시글 생성", description = "게시글을 생성합니다.")
Long createPost(
@RequestBody PostCreateRequest request
);
@Operation(summary = "게시글 리스트 조회", description = "게시글 리스트를 조회합니다.")
List<PostResponse> findPosts(
);
@Operation(summary = "게시글 상세 조회", description = "게시글 상세 조회합니다.")
PostResponse findPostById(
@PathVariable Long postId
);
@Operation(summary = "게시글 삭제", description = "게시글을 삭제합니다.")
void deletePost(
@PathVariable Long postId
);
}
문제 원인
PostAPI 구조 때문이 아니라, board 모듈 컴파일 결과에 파라미터 이름 메타데이터가 없어서
원인을 Codex로 해결 할 수 있었다
RuntimeVisibleParameterAnnotations:
parameter 0:
org.springframework.web.bind.annotation.PathVariable
javap 결과에 LocalVariableTable에는 postId가 보이지만, Java reflection이 읽는 MethodParameters가 없던 문제였다
쉽게 말하자면
소스코드에는 Long postId가 있음
컴파일된 클래스에는 @PathVariable은 있음
하지만 런타임 reflection 기준으로 "이 파라미터 이름이 postId다" 정보가 없음
때문이였다. 이런 일이 왜 발생했냐면
plugins {
id 'java-library'
}
모듈식 모놀리스로 나누는 과정에서 board/build.gradle 에서 java-library만 사용했기 때문이다.
또한 Spring Boot Gradle 플러그인도 app에만 있던 상황인지라 board 컴파일에 -parameters 옵션이 안 붙어있던 상태였던 것. 루트 build.gradle를 살펴보면 현재 인코딩만 설정하고 있었다
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
}
그래서 SpringDoc이 @PathVariable Long postId를 봐도 이름을 못 얻었던 것. 결과적으로 /api/posts/{postId} 의 {postId}와 메서드 파라미터를 연결하지 못해서 parameters: [] 가 된다.
요약
board 모듈이 -parameters 없이 컴파일됨
+ @PathVariable에 명시 이름이 없음
= springdoc이 postId 이름을 못 알아냄
= Swagger Parameters가 비어 있음
해결 방법
1. 루트 gradle 설정하기
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
options.compilerArgs += ['-parameters']
}
options.compilerArgs += ['-parameters'] 을 추가해주면 된다
이걸 루트 build.gradle의 subprojects 안에 넣으면 board, auth, app 전부 파라미터 이름이 보존된다
2. 각 @PathVariable에 이름을 명시 해주기
@PathVariable("postId") Long postId
“왜 안 되냐”의 진짜 이유는 board 모듈 class 파일에 postId라는 파라미터 이름이 reflection metadata로 안 남아있기 때문
