※ 실습 프로젝트는 Github에서 확인 할 수 있습니다.
Api문서를 쉽게 알아보기 위해선 Schemas 에 대한 설명과 들어갈 값에 대한 정보가 필요하다. 또한 api method에 대한 설명도 있어야 api구성 목록을 원활하게 식별할 수 있다.
이번 포스팅에서는 Swagger v3 Annotation을 이용하여 API 문서의 설명을 구체적으로 작성하고, Java Bean Validation 을 이용하여 api 사용시 유효성 체크를 하도록 한다.
1) api 그룹 설정: @Tag
Target: ANNOTATION_TYPE, METHOD, TYPE
- name: 태그의 이름
- description: 태그에 대한 설명
Tag에 설정된 name이 같은 것 끼리 하나의 api 그룹으로 묶는다. 주로 Controller나 Controller의 Method 영역에 설정한다.
1
2
3
4
5
6
@Tag(name = "posts", description = "게시물 API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/")
public class PostsApiController {
...
PostsController에 @Tag를 설정해 보았다.
@Tag 어노테이션 설정 한 후 Swagger UI 화면이다. 설정한 태그명과 설명이 각 태그에 표시되었다.
2) api Schema 설정 : @Schema
Target : ANNOTATION_TYPE, FIELD, METHOD, PARAMETER, TYPE
- description : 한글명
- defaultValue : 기본값
- allowableValues :
Schmea(= Model)에 대한 정보를 작성하는 곳이다. Schema를 설정할 시, 더욱 완성도 높은 Swagger UI 문서를 만들 수 있다. 아래 이미지는 @Schema 설정을 하지 않은 dto클래스들의
모델 정보이다.
각 필드값들에 대한 설명이나 기본값, 허용가능한 값 등에 대한 정보 없이 string 요소가 들어간다는 정보 뿐이라 모호하다. api 문서의 완성도를 높이기 위해서는 @Schema 설정을 통해 어떤 값들이 들어가는지 설정을 추가해주는 것이 좋다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Schema(description = "게시물 리스트 응답DTO")
@Getter
public class PostsListResponseDto {
@Schema(description = "일자")
private Long id;
@Schema(description = "게시물 제목", defaultValue = "디폴트 제목", allowableValues = {"게시물1", "게시물2"})
private String title;
@Schema(description = "내용")
private String content;
@Schema(description = "수정일자")
private LocalDateTime modifiedDate;
public PostsListResponseDto(Posts posts) {
this.id = posts.getId();
this.title = posts.getTitle();
this.content = posts.getContent();
this.modifiedDate = posts.getModifiedDate();
}
}
스키마 적용 후 swagger-ui 화면
@Schema 적용을 마친 후의 PostsListResponseDto 모델의 정보이다. 좀 더 자세하게 스키마에 대한 정보를 확인 할 수 있게 된다.
참고 블로그 필자 분은 아래와 같이 스키마를 지정하였다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Schema(description = "사용자")
@Getter @Setter
public class UserValue {
@Pattern(regexp = "[0-2]")
@Schema(description = "유형", defaultValue = "0", allowableValues = {"0", "1", "2"})
private String type;
@Email
@Schema(description = "이메일", nullable = false, example = "abc@jiniworld.me")
private String email;
@Schema(description = "이름")
private String name;
@Pattern(regexp = "[1-2]")
@Schema(description = "성별", defaultValue = "1", allowableValues = {"1", "2"})
private String sex;
@DateTimeFormat(pattern = "yyMMdd")
@Schema(description = "생년월일", example = "yyMMdd", maxLength = 6)
private String birthDate;
@Schema(description = "전화번호")
private String phoneNumber;
@Schema(description = "비밀번호")
private String password;
}
Model 클래스에 대한 한글명을 설정하였고(첫번째 라인) 각 필드값에 대한 설정을 하였다. 또한 description에 한글명을 작성하고, defaultValue를 통해 기본값을 제공하였다. 그리고 allowableValues를 설정하여 Schema 정보에서 리스트 형태로 들어갈 수 있는 데이터 정보를 볼 수 있게 하였다.
만일, Validation 체크를 하고 싶다면 javax.validation.constraints 패키지를 이용하면 된다. 특정 Regex를 이용하여 패턴체크를 하고 싶다면 Pattern을 이용하면 된다.
참고 블로그 작성자분의 캡처 화면
3) api 상세 정보 설정 : @Operation
Target: ANNOTATION_TYPE, METHOD
- summary: api에 대한 간략한 설명
- description: api에 대한 상세 설명
- response: api Response 리스트
- parameters: api 파라미터 리스트
@Operation어노테이션은 api동작에 대한 명세를 작성하기 위해 Controller 메소드에 설정한다.
Swagger UI가 fold상태일때도 간략히 확인할 수 있는 간략정보는 summary에 작성하고, 필요에 따라 상세 정보를 표기하고자 한다면 description에 설명을 추가하면 된다.
responses는 아래에서 설명할 @ApiResponse 리스트들 설정하는 요소이다. parameters는 path, query, header, cookie 등의 형태로 들어오는 파라미터에 대한 정보를 설정하는 요소이다.
아래는 save메소드의 @Operation을 지정하는 코드이다.
1
2
3
4
5
@PostMapping("/posts")
@Operation(summary = "게시물 등록", description = "제목(title)과 내용(content)을 이용하여 게시물을 신규 등록합니다.")
public Long save(@RequestBody PostsSaveRequestDto dto) {
return postsService.save(dto);
}
위와 같이 @Operation 어노테이션을 지정하면 아래 이미지 처럼 swagger-ui에서 Controller메소드에 대한 정보(설명글 및 파라미터 정보 등등)를 더 자세하게 확인 할 수 있게 된다.
4) api response 설정 : @ApiResponse
Target: ANNOTATION_TYPE, METHOD, TYPE
- responseCode: http 상태코드
- description: response에 대한 설명
- content: Response payload 구조
- schema: payload에서 이용하는 Schema
- hidden: Schema 숨김 여부
- implementation: Schema 대상 클래스
- schema: payload에서 이용하는 Schema
@ApiResponse
는 응답 결과에 따른 response 구조를 미리 확인할 수 있게 해준다.
만약 @ApiResponse를 지정하지 않으면 아래 이미지처럼 Swagger UI에서는 상태코드 200과 비어있는 response body를 보여준다.
무늬뿐인 response 구조가 아닌, api 조회 성공 및 실패시 발생될 상태코드 및 Response 구조를 설정하고자 한다면 @ApiResponse
를 설정하면 된다.
게시글 조회 API에 @ApiResponse 어노테이션을 추가해보자.
테스트 애플리케이션의 게시글 조회 API에서는 200, 404 상태코드가 설정되어 있다. 조회가 성공되었을 시, 200 상태코드와 PostsResponseDto클래스가 reseponseBody에 반환되고 조회 실패시엔, 404 상태코드와 ErrorResponse클래스가 responseBody가 반환됩니다.
implementation 에 responseBody로 제공될 클래스의 Class 타입을 반환해야하는데, 이때 주의해야할 점은 implementation에는 class literal 타입만 들어갈 수 있다는 점입니다.
1
2
3
4
5
6
7
8
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "게시글 조회 성공", content = @Content(schema = @Schema(implementation = PostsResponseDto.class))),
@ApiResponse(responseCode = "404", description = "존재하지 않는 리소스 접근", content = @Content(schema = @Schema(implementation = ErrorResponse.class))) })
@Operation(summary = "게시글 조회", description = "id를 이용하여 posts 레코드를 조회합니다.")
@GetMapping("/posts/{id}")
public PostsResponseDto findById(@PathVariable Long id) {
return postsService.findById(id);
}
@ApiResponse 리스트는 @ApiResponses 에 담아 api method에 설정해도 되고,
1
2
3
4
5
6
7
8
@Operation(summary = "게시글 조회", description = "id를 이용하여 posts 레코드를 조회합니다.", responses = {
@ApiResponse(responseCode = "200", description = "게시글 조회 성공", content = @Content(schema = @Schema(implementation = PostsResponseDto.class))),
@ApiResponse(responseCode = "404", description = "존재하지 않는 리소스 접근", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
@GetMapping("/posts/{id}")
public PostsResponseDto findById(@PathVariable Long id) {
return postsService.findById(id);
}
@Operation의 responses 요소에 설정해도 된다. 위와 같이 적용하고 swagger-ui를 실행하면 아래와 같은 결과를 확인할 수 있다.
5) api parameter 설정 : @Parameter
Target: ANNOTATION_TYPE, FIELD, METHOD, PARAMETER
- name: 파라미터 이름
- description: 파라미터 설명
- in: 파라미터 위치
- query, header, path, cookie
@ApiResponse와 마찬가지로 @parameters 어노테이션에 @Parameter 리스트를 담아 api메서드에 설정할 수 있고, @Operation 어노테이션에 parameters 요소에 설정할 수도 있다.
그리고 파라미터의 경우 api method의 인자 값에 붙여 명시적으로 설정할 수도 있다.
@Parameters 나 @Operation에 설정하는 방법은 @ApiResponse에서와 유사하므로, 이번에는 method 인자값에 붙이는 방법을 예제로 살펴보자.
1
2
3
4
5
6
7
8
9
@Operation(summary = "게시글 조회", description = "id를 이용하여 posts 레코드를 조회합니다.", responses = {
@ApiResponse(responseCode = "200", description = "게시글 조회 성공", content = @Content(schema = @Schema(implementation = PostsResponseDto.class))),
@ApiResponse(responseCode = "404", description = "존재하지 않는 리소스 접근", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
@GetMapping("/posts/{id}")
public PostsResponseDto findById(@Parameter(name = "id", description = "posts 의 id", in = ParameterIn.PATH)
@PathVariable Long id) {
return postsService.findById(id);
}
path로부터 들어올 파라미터인 id에 대한 설정을 추가하였다. @PathVariable 설정 앞에 @Parameter 어노테이션 설정을 추가했는데, 메서드의 인자앞에 직접 설정할 경우에는 name을 생략할 수 있다.
만일 @Parameters 나 @Operations에 파라미터를 설정할 경우에는 어떤 파라미터에 대한 설정인지 알 수 없기 때문에 반드시 name을 설정해 줘야 한다.
실행 결과 Swagger-ui는 아래 이미지에서 확인 할 수 있다.