이전 회사 프로젝트에서는 Swagger2(springfox)를 사용했는데, 개인 프로젝트에서 Swagger 최신 버전 (3.0)을 사용하려고 하니
이전과 많은 부분이 달라져서 해당 글에 v3 사용 방법, 예시를 정리하려합니다. :D
이전 글(설정 방법): https://vennycode.tistory.com/60
Springdoc-openapi 주요 속성
1. @OpenAPIDefinition VS new OpenAPI()
-> 주로 Spring Boot 애플리케이션에서 OpenAPI 3.0의 전체적인 정의를 설정하는 데 사용되며, 일반적으로 애플리케이션의 진입점 클래스나 별도의 설정 클래스에 지정합니다.
방법 1: @OpenAPIDefinition 애너테이션 사용
이 방식은 설정이 간단하고, 기본적인 API 정보 설정을 할 때 유용합니다.
- 애플리케이션의 진입점 클래스 예시:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.servers.Server;
@SpringBootApplication
@OpenAPIDefinition(
info = @Info(
title = "User Management API",
description = "APIs for managing users",
version = "1.0.0"
),
servers = {
@Server(url = "http://localhost:8080", description = "Local Server")
}
)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 별도의 설정 클래스 예시:
import org.springframework.context.annotation.Configuration;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.servers.Server;
@Configuration
@OpenAPIDefinition(
info = @Info(
title = "User Management API",
description = "APIs for managing users",
version = "1.0.0"
),
servers = {
@Server(url = "http://localhost:8080", description = "Local Server")
}
)
public class OpenApiConfig {
// This class can be used to add additional OpenAPI configurations if needed
}
( 클래스명은 SwaggerConfig로 해도 됩니다. )
방법 2: new OpenAPI().Info(new Info()) 방식 사용
이 방식은 설정 클래스에서 더 세밀하게 설정을 제어할 수 있고, 추가적인 설정이 필요한 경우 유용합니다. 이를 통해 설정 클래스를 모듈화하고 다양한 설정 옵션을 사용할 수 있습니다.
package com.vennygo.config;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.servers.Server;
import io.swagger.v3.oas.models.tags.Tag;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
// API 문서의 메타데이터를 설정
.info(new Info()
.title("Vennygo API") // API의 제목 설정
.description("APIs for vennygo") // API 설명 설정
.version("1.0.0") // API 버전 설정
.contact(new Contact() // API 담당자 정보 설정
.name("Venny") // 담당자 이름
.url("https://www.vennygo.com") // 담당자 웹사이트 URL
.email("vennygo00@gmail.com") // 담당자 이메일
)
.termsOfService("http://swagger.io/terms/")
.license(new License().name("Apache 2.0").url("http://springdoc.org"))
)
// 추가 설정 속성
// API가 배포된 서버들을 정의
.servers(List.of(
new Server().url("http://localhost:8080").description("Local Server"), // 로컬 서버 설정
new Server().url("https://www.vennygo.com").description("Production Server") // 프로덕션 서버 설정
))
// 외부 문서에 대한 링크를 설정
.externalDocs(new ExternalDocumentation()
.description("Full API Documentation") // 외부 문서 설명
.url("https://www.vennygo.com/api-docs") // 외부 문서 URL
)
// API 태그를 설정하여 엔드포인트를 그룹화
.tags(List.of(
new Tag().name("board").description("Operations related to boards"),
new Tag().name("sign-in").description("Operations related to sign-in")
))
// API의 보안 요구 사항 설정 (보안 스키마)
.addSecurityItem(new SecurityRequirement().addList("bearerAuth")) // Bearer 토큰을 사용한 인증 스키마
;
}
}
그래서 뭐를 사용하는게 좋지? 😯
• 프로젝트가 간단하고 기본적인 API 정보 설정만 필요한 경우 @OpenAPIDefinition 애너테이션을 사용하는 것이 더 편리합니다.
• 더 복잡한 설정이나 추가적인 설정이 필요한 경우 new OpenAPI().info(new Info()) 방식을 사용하는 것이 좋습니다.
실제로 많이 사용하는 방식은 프로젝트의 요구 사항과 팀의 선호도에 따라 달라질 수 있습니다. 대부분의 경우, 복잡한 설정이 필요한 경우가 많기 때문에 new OpenAPI().info(new Info()) 방식을 많이 사용하는 경향이 있습니다.
그래서 저는 방법 2로 적용!
Rest Controller - OpenApi 사용 예시
package com.vennygo.controller.api;
import com.vennygo.entity.Board;
import com.vennygo.service.BoardService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/api/board")
@RequiredArgsConstructor
@Tag(name = "board")
public class BoardController {
private final BoardService boardService;
@Operation(summary = "게시판 조회 by boardId", description = "특정 게시판을 조회합니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Board.class))),
@ApiResponse(responseCode = "404", description = "찾을 수 없음")
})
@GetMapping("/{boardId}")
public ResponseEntity<Board> getBoardByBoardId(
@Parameter(description = "게시판 ID", required = true) @PathVariable Long boardId) {
Optional<Board> board = boardService.getBoard(boardId);
return board.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
@Operation(summary = "게시판 목록 조회", description = "전체 게시판 목록을 조회합니다.")
@ApiResponse(responseCode = "200", description = "성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Board.class)))
@GetMapping
public ResponseEntity<List<Board>> getBoards() {
List<Board> boards = boardService.getBoards();
return ResponseEntity.ok(boards);
}
@Operation(summary = "게시판 생성", description = "새로운 게시판을 생성합니다.")
@ApiResponse(responseCode = "200", description = "성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Board.class)))
@PostMapping
public ResponseEntity<Board> createBoard(
@Parameter(description = "생성 할 게시판 정보", required = true) @RequestBody Board board) {
Board createBoard = boardService.createBoard(board);
return ResponseEntity.ok(createBoard);
}
@Operation(summary = "게시판 수정", description = "기존 게시판 정보를 수정합니다.")
@ApiResponse(responseCode = "200", description = "성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Board.class)))
@PutMapping("/{boardId}")
public ResponseEntity<Board> updateBoard(
@Parameter(description = "수정 할 게시판 ID", required = true) @PathVariable Long boardId,
@Parameter(description = "수정 할 게시판 정보", required = true) @RequestBody Board boardDetail) {
Board updateBoard = boardService.updateBoard(boardId, boardDetail);
return ResponseEntity.ok(updateBoard);
}
@Operation(summary = "게시판 삭제", description = "특정 게시판을 삭제합니다.")
@ApiResponse(responseCode = "204", description = "삭제 성공")
@ApiResponse
@DeleteMapping("/{boardId}")
public ResponseEntity<Board> deleteBoard(
@Parameter(description = "삭제 할 게시판 ID", required = true) @PathVariable Long boardId) {
boardService.deleteBoard(boardId);
return ResponseEntity.noContent().build();
}
}
• @Tag(name = "board"): Swagger에서 사용할 태그를 정의합니다. (OpenApiConfig 파일에서 설정한 tag name과 동일)
• 각 메서드에 @Operation, @ApiResponse, @Parameter 등의 어노테이션을 사용하여 API 문서를 자세히 정의합니다.
• @Operation: 각각의 API 작업(Operation)에 대한 요약(summary)과 설명(description)을 제공합니다.
• @ApiResponse: 각 API의 응답(response)에 대한 설명을 제공합니다. content는 응답의 MediaType과 스키마를 정의합니다.
• @Parameter: 메서드의 매개변수에 대한 설명을 제공합니다.
결과 화면
- 'Try it out' 버튼 클릭
- 'Execute' 버튼 클릭
- 목록 조회 결과
* 현재는 request와 Response Parameter에 Entity를 통째로 조회하게 되어있는데,
RequestDTO와 ResponseDTO를 생성하여 필요한 파라미터 값만 request, response 하도록 변경 할 예정입니다. :D
'Framework > Swagger' 카테고리의 다른 글
[Swagger] Spring Boot (Gradle)에서 Swagger 3.0 (Springdoc-openapi) 설정 방법 (0) | 2024.06.30 |
---|