스웨거(Swagger)는 개발자가 REST 웹 서비스를 설계, 빌드, 문서화, 소비하는 일을 도와주는 대형 도구 생태계의 지원을 받는 오픈 소스 소프트웨어 프레임워크이다. 대부분의 사용자들은 스웨거 UI 도구를 통해 스웨거를 식별하며 스웨거 툴셋에는 자동화된 문서화, 코드 생성, 테스트 케이스 생성 지원이 포함된다.
build.gradle 파일에 springdoc-openapi-starter-webmvc-ui 의존성을 추가한다.implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.3'springdoc-openapi 라이브러리는 swagger-annotations과 swagger-ui 공식 라이브러리에 의존한다.http://localhost:8080/swagger-ui/index.html
위의 API 문서에서는 각 API의 이름, 설명 등이 모두 스프링 기본 어노테이션을 기반으로 출력됩니다. Swagger 애너테이션을 추가하여 좀 더 상세 정보를 표시할 수 있습니다.
@Tag, @Operation, @ApiResponse, @Parameter 네 가지 애너테이션을 통해 API와 각 API의 파라미터에 상세 정보를 추가한다.
Controller
@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class PostController {
private final PostService postService;
@Operation(summary = "게시글 작성", description = "파라미터로 넘어온 값으로 게시글을 작성한다.")
@ApiResponse(responseCode = "201", description = "성공")
@ApiResponse(responseCode = "400", description = "파라미터 오류")
@PostMapping("/post")
public ResponseEntity<PostResponse> savePost(@Parameter(description = "게시글의 제목과 내용 Dto") @RequestBody @Valid SavePostRequest savePostRequest) {
PostResponse postResponse = postService.save(savePostRequest);
return ResponseEntity.status(HttpStatus.CREATED).body(postResponse);
}
@Operation(summary = "게시글 리스트 조회", description = "모든 게시글을 조회한다.")
@ApiResponse(responseCode = "201", description = "성공")
@GetMapping("/posts")
public ResponseEntity<List<PostResponse>> findAllPosts() {
List<PostResponse> posts = postService.findAll();
return ResponseEntity.status(HttpStatus.OK).body(posts);
}
@Operation(summary = "게시글 조회", description = "파라미터의 id값으로 하나의 게시글을 조회한다.")
@ApiResponse(responseCode = "201", description = "성공")
@ApiResponse(responseCode = "400", description = "파라미터 오류")
@GetMapping("/post/{id}")
public ResponseEntity<PostResponse> findPost(@PathVariable("id") Long id) {
PostResponse postResponse = postService.findById(id);
return ResponseEntity.status(HttpStatus.OK).body(postResponse);
}
@Operation(summary = "게시글 삭제", description = "파라미터의 id값으로 하나의 게시글을 삭제한다.")
@ApiResponse(responseCode = "201", description = "성공")
@ApiResponse(responseCode = "400", description = "파라미터 오류")
@DeleteMapping("/post/{id}")
public ResponseEntity<Void> deletePost(@Parameter(description = "게시글 번호") @PathVariable("id") Long id) {
postService.deleteById(id);
return ResponseEntity.status(HttpStatus.OK).build();
}
@Operation(summary = "게시글 수정", description = "파리미터로 넘어온 id값과 정보로 게시글을 수정한다.")
@ApiResponse(responseCode = "201", description = "성공")
@ApiResponse(responseCode = "400", description = "파라미터 오류")
@PatchMapping("/post/{id}")
public ResponseEntity<PostResponse> updatePost(@Parameter(description = "게시글 번호") @PathVariable("id") Long id,
@Parameter(description = "게시글의 제목과 내용 Dto") @RequestBody @Valid SavePostRequest savePostRequest) {
PostResponse postResponse = postService.updatePost(id, savePostRequest);
return ResponseEntity.status(HttpStatus.OK).body(postResponse);
}
// 페이징과 검색
@Operation(summary = "게시글 페이징 리스트", description = "페이징 처리와 검색이 가능한 게시글 목록을 반환한다.")
@ApiResponse(responseCode = "201", description = "성공")
@ApiResponse(responseCode = "400", description = "파라미터 오류")
@GetMapping("/paging/post")
public ResponseEntity<Page<PostResponse>> list(@Parameter(description = "게시글의 제목")@RequestParam(required = false) String title,
@Parameter(description = "게시글의 내용")@RequestParam(required = false) String content,
Pageable pageable) {
SearchPostRequest searchPostRequest = new SearchPostRequest(title, content);
Page<PostResponse> page = postService.searchAndPagePost(searchPostRequest, pageable);
return ResponseEntity.status(HttpStatus.OK).body(page);
}
}
