Swagger
스프링 생태계에서 API 문서 자동화를 도와주는 스웨거에 대해 알아봅시다.
이번 글에서는 Swagger의 개념, 그리고 실제 사용 방법과 예시를 살펴보겠습니다.
1. Swagger의 개념
API 문서 작성을 자동화 시키는데 사용하는 도구!
-
OpenAPI Specification (OAS): Swagger의 핵심이자 표준화된 API 설계 스펙입니다. JSON 또는 YAML 형식으로 작성되며, API의 엔드포인트, 매개변수, 응답 포맷 등을 정의합니다.
-
Swagger UI: API의 OpenAPI Specification을 시각적으로 표현하고, 인터랙티브하게 사용할 수 있는 웹 인터페이스입니다. 개발자는 Swagger UI를 통해 API 엔드포인트를 쉽게 탐색하고, 요청을 테스트하며, 자동으로 생성된 문서를 읽을 수 있습니다.
-
Swagger Editor: OpenAPI Specification을 편집하고 검증할 수 있는 온라인 편집기입니다. JSON 또는 YAML로 스펙을 작성하고 실시간으로 변경 사항을 볼 수 있습니다.
(이번 글에서는 Editor는 사용하지 않고 Swagger UI만 사용할 예정입니다.) 이 Swagger UI 만으로도 api 문서를 만들 수 있습니다.
- 자동 생성된 API 문서: 프로젝트의 엔드포인트, 매개변수, 응답 등을 자동으로 문서화합니다.
- 인터랙티브한 웹 인터페이스: Swagger UI를 통해 API 엔드포인트를 시각적으로 탐색하고, 요청을 테스트할 수 있습니다. 이를 통해 사용자들은 API의 작동 방식을 쉽게 이해할 수 있습니다.
2. Swagger 사용 방법
Swagger를 사용하여 API를 문서화하고 제공하는 방법은 다음과 같습니다.
2-1 의존성 추가
SpringDoc 과 SpringFox 자료는 SpringFox가 많지만 2020년 이후 업데이트를 멈춰서, 스프링부트3.x 이상에서는 SpringDoc만 사용이 가능합니다.
Spring Boot 프로젝트에서는 Maven이나 Gradle에 springdoc-openapi-ui
의존성을 추가합니다.
<!-- Maven -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>
//gradle
dependencies {
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
}
2-2 Springdoc 설정 파일 작성
Springdoc 설정 파일 (application.yml 또는 application.properties)을 작성해야합니다.
springdoc:
default-consumes-media-type: application/json;charset=UTF-8
default-produces-media-type: application/json;charset=UTF-8
swagger-ui:
path: /swagger-ui.html
접기/펼치기
<media-type> 이란? 이 설정은 API가 기본적으로 소비하고 생산하는 미디어 타입을 명시적으로 설정하기 위한 것입니다. (없어도 특별히 에러가 나지는 않습니다) 하지만 이 미디어 타입을 강제해야하는 경우가 있을 때는 반드시 사용해야 합니다.
1. 클라이언트와 서버 간의 일관성 유지 API의 클라이언트와 서버가 특정 미디어 타입을 사용하여 데이터를 주고받기로 약속한 경우, 일관성을 유지하기 위해 미디어 타입을 강제할 필요가 있습니다.
예: JSON 데이터를 주고받기로 한 경우, 모든 요청과 응답에서 application/json 미디어 타입을 사용해야 합니다.
2. 특정 인코딩 요구사항 특정 인코딩(예: UTF-8)을 사용해야 하는 경우, 모든 요청과 응답에서 해당 인코딩을 강제해야 합니다. 이는 특히 다국어 지원이 필요한 경우 중요합니다.
예: application/json;charset=UTF-8를 사용하여 모든 데이터를 UTF-8 인코딩으로 처리해야 할 때.
3. 보안 및 데이터 무결성 특정 미디어 타입이 더 안전하거나 데이터 무결성을 보장하는 경우, 이를 강제할 수 있습니다. 예를 들어, XML 기반의 SOAP 서비스와 같은 경우입니다.
예: application/xml을 사용하여 XML 형식의 데이터를 주고받아야 할 때.
4. 성능 최적화 특정 미디어 타입이 더 빠르거나 효율적인 경우, 성능 최적화를 위해 이를 강제할 수 있습니다. 예를 들어, 대용량 데이터 전송 시 압축된 형식을 사용할 수 있습니다.
예: application/json 대신 application/json+gzip와 같은 압축된 형식을 사용할 때.
2-1.의존성 추가와 2-2.설정 파일 작성을 끝냈다면 서버를 실행시켜 http://localhost:8080/swagger-ui/index.html 에서 api 문서를 확인해 볼 수 있습니다.
이렇게 @Restcontroller 나 @ResponseBody가 달려있는 컨트롤러들이 보이게 됩니다.(아무런 설정을 하지 않았기 때문에 default 옵션으로 진행되었고, view 를 반환하는 api는 보이지 않았습니다)
또한 위 사진처럼 간단하게 api 통신도 테스트 해볼 수 있습니다.
http://localhost:8080/v3/api-docs 으로 들어가보면 다음과 같이 json 형태의 api 문서도 볼 수 있습니다.
이제 연결하는 방법은 알았으니 처음 이 api 문서를 보는 사람들도 쉽게 이해하고 사용할 수 있도록 문서를 다듬을 필요가 있습니다.
3. OpenAPI Specification 작성 (추가설정)
3-1 API의 기본 정보를 설정합니다.
Configuration 과 관련된 설정파일 ( 저는 SpringConfig.java 로 만들어 사용했습니다)에 아래 내용을 추가합니다.
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Hello Spring API")
.version("1.0")
.description("Hello Spring API documentation"));
}
3-2 Controller 클래스에 Swagger 어노테이션 추가 ( ### 예시 )
각 컨트롤러와 API 엔드포인트에 대해 @Operation, @ApiResponse, @RequestBody, @RequestParam 등의 Swagger 어노테이션을 사용하여 설명을 추가합니다.
package hello.hellospring.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
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 org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@Operation(summary = "Render hello view", description = "Returns a view with a hello message")
@GetMapping("hello")
public String hello(Model model) {
model.addAttribute("data", "hello!!");
return "hello";
}
@Operation(summary = "Render hello-mvc view", description = "Returns a view with a personalized hello message")
@GetMapping("hello-mvc")
public String helloMvc(@Parameter(description = "Name of the person to greet") @RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-templates";
}
@Operation(summary = "Return hello string", description = "Returns a personalized hello string")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successful operation"),
@ApiResponse(responseCode = "400", description = "Invalid parameter")
})
@GetMapping("hello-string")
@ResponseBody
public String helloString(@Parameter(description = "Name of the person to greet") @RequestParam("name") String name) {
return "hello " + name;
}
@Operation(summary = "Return hello object", description = "Returns a personalized hello object")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successful operation"),
@ApiResponse(responseCode = "400", description = "Invalid parameter")
})
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@Parameter(description = "Name of the person to greet") @RequestParam("name") String name) {
Hello hello = new Hello();
hello.setName(name);
return hello;
}
@Schema(description = "Hello object")
static class Hello {
@Schema(description = "Name of the person to greet")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
(참고로 위 코드는 api에 맞게 문서가 작성된 것이 아닙니다. “단순히 각 어노테이션을 이용해 summary 나 description 자리에 이러한 텍스트를 쓰면 ui로 이렇게 보이더라~” 정도로 받아들여 주시기 바랍니다)
이후 다시 Swagger UI를 확인 해보면
이렇게 바뀐 부분들이 보입니다.
4. 참고!
4-1 설정파일
.yml 이나 .properties 에 작성하는 기본적인 Swagger UI 추가 설정 (선택사항)
# swaggerdoc
springdoc.version=v1.0.0
springdoc.packages-to-scan=com.example.swagger3test
springdoc.swagger-ui.path=/api-docs
springdoc.swagger-ui.tags-sorter=alpha
springdoc.swagger-ui.operations-sorter=alpha
springdoc.api-docs.path=/api-docs/json
springdoc.api-docs.groups.enabled=true
springdoc.cache.disabled=true
springdoc.default-consumes-media-type=application/json;charset=UTF-8
springdoc.default-produces-media-type=application/json;charset=UTF-8
-
springdoc.version=v1.0.0
SpringDoc의 버전을 지정합니다.
-
springdoc.packages-to-scan=com.example.swagger3test
OpenAPI 문서를 생성하기 위해 스캔할 패키지를 지정합니다. 이 경우 com.example.swagger3test 패키지가 스캔 대상입니다.
-
springdoc.swagger-ui.path=/api-docs
Swagger UI에 접근할 수 있는 경로를 지정합니다. /api-docs 경로를 통해 Swagger UI에 접근할 수 있습니다.
-
springdoc.swagger-ui.tags-sorter=alpha
Swagger UI에서 태그를 알파벳 순으로 정렬하도록 설정합니다.
-
springdoc.swagger-ui.operations-sorter=alpha
Swagger UI에서 API operation들을 알파벳 순으로 정렬하도록 설정합니다.
-
springdoc.api-docs.path=/api-docs/json
JSON 형식의 OpenAPI 문서에 접근할 수 있는 경로를 지정합니다. /api-docs/json 경로를 통해 JSON 형식의 문서에 접근할 수 있습니다.
-
springdoc.api-docs.groups.enabled=true
OpenAPI 문서의 그룹화를 활성화합니다. 이는 서로 다른 그룹의 API 문서를 관리하고 표시하는 데 사용될 수 있습니다.
-
springdoc.cache.disabled=true
캐싱을 비활성화합니다. 캐싱이 비활성화되면, 매번 최신의 API 문서가 생성됩니다.
-
springdoc.default-consumes-media-type=application/json;charset=UTF-8
API에서 기본적으로 소비하는 미디어 타입을 application/json;charset=UTF-8로 설정합니다.
-
springdoc.default-produces-media-type=application/json;charset=UTF-8
API에서 기본적으로 생산하는 미디어 타입을 application/json;charset=UTF-8로 설정합니다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
4-2. 각 종 annotations
-
@Tag
컨트롤러 파일의 클래스위에 작성합니다. (미 작성시 클래스 이름으로 설정됩니다) api들을 그룹 지을 수 있습니다.
-
@Operation
특정 api에 대한 정보를 입력할 수 있습니다.
-
@ApiResponses
바로 아래에서 설명하는 여러 개의 @ApiResponse를 묶기 위한 어노테이션입니다.
-
@ApiResponse
api의 response 설정을 위한 어노테이션입니다.
-
@Parameters
바로 아래에서 설명하는 api 별로 필요한 파라미터들을 묶기 위한 어노테이션입니다.
-
@Parameter
api별로 필요한 개별 파라미터들에 대한 설정을 위한 어노테이션입니다.
-
@RequestParam
필요한 파라미터이름과 타입에 대해 설정할 수 있습니다.
-
@Schema
모델 클래스의 속성을 설명하기 위해 사용하는 어노테이션입니다. 즉 request, response 객체에 대한 설정을 위해 사용됩니다.