
1. Swagger란?
- Swagger는 개발한 Rest API를 문서화 한다.
- 문서화된 내용을 통해 관리 & API 호출을 통한 테스트를 가능하게 해준다.
2. swagger 적용하기
- build.gradle
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
springfox 말고 현재 꾸준히 업데이트가 진행 중인 springdocs 버전을 사용하여 swagger를 구현하였다.
springDoc 공식 문서에 따르면, Spring Boot v3 (Java 17 & Jakarta EE 9)을 사용하기 위해선 위 dependency를 사용해야 한다. Spring Boot 3 지원을 위해 springdoc-openapi v2를 사용해야 하기 때문이다.
3. Swagger 설정 파일 추가
기본적인 SwaggerConfig 코드는 다음과 같다.
- JWT를 사용하는 경우
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
String jwt = "JWT";
SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwt);
Components components = new Components().addSecuritySchemes(jwt, new SecurityScheme()
.name(jwt)
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
);
return new OpenAPI()
.components(new Components())
.info(apiInfo())
.addSecurityItem(securityRequirement)
.components(components);
}
private Info apiInfo() {
return new Info()
.title("API Test") // API의 제목
.description("Let's practice Swagger UI") // API에 대한 설명
.version("1.0.0"); // API의 버전
}
}
- @OpenAPIDefinition 을 사용하는 경우 (위 코드 수정)
@OpenAPIDefinition(
info = @Info(
title = "title",
description = "description",
version = "v1"
),
servers = {
@Server(url = "${baseUrl.server}")
}
)
@RequiredArgsConstructor
@Configuration
public class SwaggerConfig {
/**
* 그룹화된 OpenAPI 설정
* 경로가 /api/** 인 API 설정
*/
@Bean
public GroupedOpenApi testOpenApi() {
return GroupedOpenApi.builder()
.group("API test")
.pathsToMatch("/api/**")
.build();
}
/**
* OpenAPI 메인 설정
* JWT 보안 스키마를 설정
*/
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList("JWT"))
.components(new Components().addSecuritySchemes("JWT", createAPIKeyScheme()));
}
/**
* JWT 보안 스키마 생성 메서드
* @return SecurityScheme JWT 보안 스키마
*/
private SecurityScheme createAPIKeyScheme() {
return new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.bearerFormat("JWT")
.scheme("bearer");
}
}
3. application.yml을 이용해 사용자 지정 경로 및 Swagger UI 설정 추가
- application.yml
springdoc:
swagger-ui:
path: /swagger-ui.html # 스웨거 접근 경로
groups-order: DESC # API 그룹 표시 순서
# alpha: 알파벳 순 정렬
# method: OpenAPI specification file에 원하는 태그 정렬 방식 직접 기재
tags-sorter: alpha # 태그 정렬 순서.
operationsSorter: method # 컨트롤러 정렬 순서
disable-swagger-default-url: true # swagger-ui default url인 petstore html의 비활성화 설정
display-request-duration: true # swagger-ui default url인 petstore html의 비활성화 설정
api-docs:
path: /api-docs # openAPI 접근 경로. default 값은 /v3/api-docs 이다.
show-actuator: true # Spring Actuator의 endpoint까지 보여줄 것인지?
default-consumes-media-type: application/json # request media type 의 기본 값
default-produces-media-type: application/json # response media type 의 기본 값
paths-to-match: # 해당 패턴에 매칭되는 controller만 swagger-ui에 노출한다.
- /v1/**
프로젝트에 필요한 설정만 추가하면 된다.
더 많은 설정은 [공식 문서] 참고하기
4. Spring Security에 Swagger Endpoint 활성화
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(
HttpSecurity httpSecurity
) throws Exception {
httpSecurity
...
// 특정 URL에 대한 권한 설정.
.authorizeHttpRequests(authz -> authz
.requestMatchers("/", "/swagger-ui/*", "/api/*", "/login/oauth2/*").permitAll() // 특정 url에 대한 인가 요청 허용
.anyRequest().permitAll()
)
...
return httpSecurity.build();
}
}
authorizeHttpRequests 메서드 안에 swagger-ui에 대한 인가 요청을 허용해주면 된다
5. Spring 프로젝트 실행
프로젝트 실행 후, application.yml에서 지정한 springdoc.swagger-ui.path 경로로 접속하면 된다.
컨트롤러에 적용하기
1. Controller에 전체에 Tag 추가
@Tag(name = "Member", description = "Member API")를 사용하여 Controller 단위에 Tag를 지정해준다.
그럼 API들이 Swagger UI에서 Tag 단위로 그룹핑된다.
- 예시
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/members")
@Validated
@Tag(name = "Member", description = "Member API")
public class MemberController {
private final MemberService memberService;
private final MemberMapper memberMapper;
}
2. 각 Controller에 API 메타 데이터 정보 명세하기
@Operation를 이용해 해당 API가 어떤 리소스를 나타내는지 간략한 설명을 추가할 수 있다.
@Operation(summary = "Get member profile", description = "특정 멤버의 상세 정보를 조회한다.")
- @ApiResponses를 이용해 해당 API의 Response 정보들을 나타낼 수 있으며 목적에 따라 여러 response들을 묶을 수 있다.
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "성공", content = {@Content(schema = @Schema(implementation = MemberProfileRes.class))}),
@ApiResponse(responseCode = "404", description = "해당 ID의 유저가 존재하지 않습니다."),
@ApiResponse(responseCode = "200", description = "성공",
content = {
@Content(mediaType = "application/json",
array = @ArraySchema(schema = @Schema(implementation = MemberRes.class)))
})
})
- @ApiResponse : 단일 Response에 대한 정보를 나타낸다.
- responseCode : HTTP status code
- description : 이 response의 의미
- content : response 데이터 포맷. void이거나 response field에 대한 설명을 추가하지 않을거라면 생략하면 된다.
만약 Response가 List<> 형태라면, array 옵션을 이용하면 된다.
- 필드에 대한 설명, 예시, 필수값 여부
컨트롤러의 파라미터에 Swagger에서 제공하는 @Schema, @Parameter와 같은 어노테이션을 활용하여 필드에 대한 정보들을 입력할 수 있다.
@PathVariable
@Positive(message = "유저 ID는 양수입니다.")
@Schema(description = "Member ID", example = "1")
Long memberId,
// TODO: Replace with member ID from JWT or that from any other authentication method
@Parameter(name = "loginId", description = "로그인 유저 ID 값", example = "3", required = true)
@Positive(message = "유저 ID는 양수입니다.") @RequestParam final Long loginId,
@RequestBody @Valid MemberProfileUpdateReq request
- 전체 코드
@GetMapping("/{memberId}")
@Operation(summary = "Get member profile", description = "특정 멤버의 상세 정보를 조회한다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "성공",
content = {@Content(schema = @Schema(implementation = MemberProfileRes.class))}),
@ApiResponse(responseCode = "404", description = "해당 ID의 유저가 존재하지 않습니다."),
})
public MemberProfileRes getMemberProfile(
@PathVariable
@Positive(message = "유저 ID는 양수입니다.")
@Schema(description = "Member ID", example = "1")
Long memberId,
// TODO: Replace with member ID from JWT or that from any other authentication method
@Parameter(name = "loginId", description = "로그인 유저 ID 값", example = "3", required = true)
@Positive(message = "유저 ID는 양수입니다.") @RequestParam final Long loginId,
@RequestBody @Valid MemberProfileUpdateReq request
) {
return memberMapper.toResponse(
memberService.findProfileByMemberId(memberId, loginId)
);
}
3. Request Body, Response 각 Schema 정보 명세
Swagger Schemas 기능을 이용해 request body, response value를 확인 / 입력 할 수 있다. 주로 DTO에 사용됨!
1. @Schema
class 상단에 @Schema 어노테이션을 이용해, 해당 클래스가 어떤 클래스인지 설명을 적어줄 수 있고 각 필드에 대한 설명, 예시, 필수값 여부를 추가할 수 있다.
Schema는 자세히 적어줄 수록 소통하기 편하기 때문에, 되도록 꼼꼼하게 적어주자!
// 클래스
@Schema(description = "Member profile update request")
public class DTO {
...
}
// 필드
@NotBlank(message = "사용자 이름을 입력해주세요.")
@Length(max = 20, message = "사용자 이름은 20글자 이하로 입력해야 합니다.")
@Schema(description = "member name", example = "John Doe")
private String name;
// 특정 객체를 변수로 갖는 경우 implementation 사용!!
@Schema(description = "친구 정보", implementation = FriendRes.class)
private FriendRes friendInfo;
- 전체 코드
@Getter
@AllArgsConstructor
@Schema(description = "Member profile update request")
public class MemberProfileUpdateReq {
@NotBlank(message = "사용자 이름을 입력해주세요.")
@Length(max = 20, message = "사용자 이름은 20글자 이하로 입력해야 합니다.")
@Schema(description = "member name", example = "John Doe")
private String name;
@NotBlank(message = "사용자 닉네임을 입력해주세요.")
@Length(max = 20, message = "사용자 닉네임은 20글자 이하로 입력해야 합니다.")
@Schema(description = "member nickname", example = "johndoe")
private String nickname;
@NotBlank
@Schema(description = "member profile emoji", example = "👨🏻💻")
private String profileEmoji;
}
추가
1. https 서버 이용 시 swagger 적용
Swagger는 기본적으로 http프로토콜을 사용하기 때문에 swagger config에서 OpenAPI를 설정해주거나 @OpenAPIDefinition을 추가해주면 된다.
서버 url은 GitHub 상에서 노출되면 안되기 때문에 따로 환경변수에 등록해서 사용해야 한다.
1. openAPI 클래스 사용
@Value("${baseUrl.server}")
private String baseUrl;
@Bean
public OpenAPI openAPI() {
return new OpenAPI().addServersItem(createServer());
}
private Server createServer() {
Server server = new Server();
server.setUrl(baseUrl);
return server;
}
2. @OpenAPIDefinition 사용
@OpenAPIDefinition(
info = @Info(
title = "test",
description = "test",
version = "test"
),
servers = {
@Server(url = "${baseUrl.server}")
}
)
@RequiredArgsConstructor
@Configuration
public class SwaggerConfig {
...
}
JWT 적용
OpenAPI에 다음과 같이 JWT 토큰에 대한 정보를 Bean으로 등록한다.
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList("JWT"))
.components(new Components().addSecuritySchemes("JWT", createAPIKeyScheme()));
}
/**
* JWT 보안 스키마 생성 메서드
* @return SecurityScheme JWT 보안 스키마
*/
private SecurityScheme createAPIKeyScheme() {
return new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.bearerFormat("JWT")
.scheme("bearer");
}
이렇게 적용하고 Swagger를 실행하면 다음과 같이 Authorization 버튼이 생성된다.


Bearer {token} 형식 그대로 Value에 입력해준다.
전체 코드
package com.alpha.DLINK.setting.config;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.servers.Server;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@OpenAPIDefinition(
info = @Info(
title = "title",
description = "description",
version = "v1"
),
servers = {
@Server(url = "${baseUrl.server}")
}
)
@RequiredArgsConstructor
@Configuration
public class SwaggerConfig {
/**
* 그룹화된 OpenAPI 설정
* 경로가 /api/** 인 API 설정
*/
@Bean
public GroupedOpenApi testOpenApi() {
return GroupedOpenApi.builder()
.group("API test")
.pathsToMatch("/api/**")
.build();
}
/**
* OpenAPI 메인 설정
* JWT 보안 스키마를 설정
*/
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList("JWT"))
.components(new Components().addSecuritySchemes("JWT", createAPIKeyScheme()));
}
/**
* JWT 보안 스키마 생성 메서드
* @return SecurityScheme JWT 보안 스키마
*/
private SecurityScheme createAPIKeyScheme() {
return new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.bearerFormat("JWT")
.scheme("bearer");
}
}
참고
[Spring Boot 3] SpringDoc과 Swagger를 이용해 API 문서화 자동화하기
💁♀️ 앗! 세상은 위험하니 이 API 문서화 자동화 툴을 챙겨 가렴! 📌 시작하기 전, 내가 API나 REST API에 대해 잘 모른다면? 더보기 ✏️ API는 Application Programming Interface(애플리케이션 프로그램
hogwart-scholars.tistory.com
https://velog.io/@ryulkim/Spring-boot-JWT%EC%99%80-Swagger-JWT-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0
[Spring boot] JWT와 Swagger JWT 적용하기
이번 프로젝트에는 로그인을 할 때 JWT 인증을 해보기로 했습니다. 먼저, JWT에 관련된 용어를 알아보겠습니다! 용어 프로젝트를 위해 알아야할 용어는 다음과 같습니다. 출처: https://datatracker.ietf.
velog.io
https://velog.io/@penrose_15/Swagger-HTTPS-%EC%84%A4%EC%A0%95-springdoc
Swagger HTTPS 설정 (springdoc)
회사에서 실서버 도메인이 https프로토콜을 사용하면서 Swagger에서 CORS 에러가 발생하는 문제가 생겼..
velog.io
'Back-end > Spring' 카테고리의 다른 글
[Spring] JPA Hibernate의 ddl-auto 속성 분석하기 (0) | 2024.06.16 |
---|---|
[Spring] WebClient를 사용한 외부 API 통신 (0) | 2024.06.16 |
[Spring] data.sql을 사용하여 서버 실행 시 데이터 삽입하기 (1) | 2024.05.28 |
[Spring] JPA "Row size too large" 문제 분석하기 (0) | 2024.05.26 |
[Spring] CORS-safelisted response header 문제 해결하기 (0) | 2024.05.26 |