Swagger ๋ฅผ ์ฌ์ฉํ๋ฉด, API ๋ฌธ์๋ฅผ ์๋์ผ๋ก ๊ตฌ์ฑํด์ฃผ๋ฉฐ ์๋ํฌ์ธํธ๋ฅผ ํ ์คํธ ํ ์ ์๋ค๋ ์ฅ์ ์ด ์๋ค.
@Tag
, @Operation
, @ApiResponses
์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ๋ฉด ์ค์จ๊ฑฐ ๋ฌธ์์ ๋ถ๊ฐ์ ์ธ ์ค๋ช
์ ์ถ๊ฐ์ ์ผ๋ก ๋ฃ์ ์ ์์ด์ API ๋ฌธ์๋ฅผ ์ดํดํ๋๋ฐ ๋์์ ์ค ์ ์๋ค.
@RestController
@RequestMapping("/api/v1/posts")
@RequiredArgsConstructor
public class PostApiController {
private final PostService postService;
@Tag(name = "Post", description = "๊ฒ์๊ธ ๊ด๋ จ API")
@Operation(summary = "๊ฒ์๊ธ ์กฐํ", description = "๐ก์นดํ
๊ณ ๋ฆฌ์ ์๊ด์์ด ๋ชจ๋ ๊ฒ์๊ธ์ ํ์ด์ง๋ก ์กฐํํฉ๋๋ค.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "โญ SUCCESS", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
examples = {@ExampleObject(value = "{\"message\":\"SUCCESS\",\"result\":{\"content\":[{\"postId\":1,\"title\":\"title\",\"content\":\"content\",\"category\":\"category\",\"userId\":1,\"nickName\":\"nickName\",\"userName\":\"userName\",\"createdDate\":\"2023/04/27 21:14\",\"lastModifiedDate\":\"2023/04/27 21:14\",\"imageUrl\":\"imageUrl\",\"view\":0,\"totalNumOfComments\":0,\"totalNumOfLikes\":0},{\"postId\":2,\"title\":\"title\",\"content\":\"content\",\"category\":\"category\",\"userId\":1,\"nickName\":\"nickName\",\"userName\":\"userName\",\"createdDate\":\"2023/05/13 00:15\",\"lastModifiedDate\":\"2023/05/13 00:15\",\"imageUrl\":\"imageUrl\",\"view\":0,\"totalNumOfComments\":0,\"totalNumOfLikes\":0}],\"pageable\":{\"sort\":{\"empty\":true,\"sorted\":false,\"unsorted\":true},\"offset\":0,\"pageNumber\":0,\"pageSize\":20,\"unpaged\":false,\"paged\":true},\"totalPages\":1,\"totalElements\":2,\"last\":true,\"size\":20,\"number\":0,\"sort\":{\"empty\":true,\"sorted\":false,\"unsorted\":true},\"numberOfElements\":2,\"first\":true,\"empty\":false}}")}, schema = @Schema(implementation = Response.class))),
})
@GetMapping
public ResponseEntity<Response<Page<PostGetResponse>>> getAll(Pageable pageable) {
Page<PostGetResponse> response = postService.getAllPosts(pageable);
return ResponseEntity.ok(Response.success(response));
}
@Tag(name = "Post", description = "๊ฒ์๊ธ ๊ด๋ จ API")
@Operation(summary = "๊ฒ์๊ธ ์์ฑ", description = "<strong>๐JWT ํ์</strong><br>๐ก๊ฒ์๊ธ์ ์์ฑํฉ๋๋ค.<br>๐จ๊ฐ์
๋ ํ์์ด ์กด์ฌํ์ง ์์ ์ ์๋ฌ ๋ฐ์")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "โญ SUCCESS", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
examples = {@ExampleObject(value = "{\"message\":\"SUCCESS\",\"result\":{\"id\":1,\"nickName\":\"nickName\",\"blog\":\"blog\",\"email\":\"email\"}}")}, schema = @Schema(implementation = Response.class))),
@ApiResponse(responseCode = "404", description = "โ ERROR (๊ฐ์
๋ ํ์์ด ์กด์ฌํ์ง ์์ ์)", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
examples = {@ExampleObject(value = "{\"message\":\"ERROR\",\"result\":\"๊ฐ์
๋ ํ์์ด ์๋๋๋ค.\"}")}, schema = @Schema(implementation = Response.class)))
})
@PostMapping
public ResponseEntity<Response<PostResponse>> create(Authentication authentication, @Validated @RequestBody PostCreateRequest requestDto, BindingResult br) {
String userName = authentication.getName();
PostResponse response = postService.createPost(userName, requestDto);
return ResponseEntity.status(CREATED).body(Response.success(response));
}
}
์์ ๊ฐ์ด, Controller์ ํน์ ๋ฉ์๋์ ๋ถ๊ฐ ์ค๋ช ์ ์ถ๊ฐํ ์ ์๋ค.
@Tag
์ฌ์ฉ์,

์์ ๊ฐ์ด ๊ฐ์ Tag name
์ด ๋ฌ๋ ค์๋ ์๋ํฌ์ธํธ๋ผ๋ฆฌ ๋ฌถ์ ์ ์๋ค.
@Operation
์ ์ต์
์ธ summary
์ description
์ ํตํด

์ด๋ฐ์์ผ๋ก ์๋ํฌ์ธํธ์ ๋ํ ๋ถ๊ฐ ์ค๋ช ๋ ์ถ๊ฐํด์ค ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ @ApiResponse
๋ฅผ ํตํด ์๋ต response ์ ์ํ ์ฝ๋ ์์๋ฅผ ๋ณด์ฌ์ค ์ ์๋ค.

๋จ, ์ด๋ฐ ์์ ์ ๊ฑฐ์น๋ฉด API ๋ฌธ์๋ ์น์ ํด์ง๊ณ ๊ฐ๋ ์ฑ์ด ์ข์์ง์ง๋ง Controller ์ฝ๋๊ฐ ๋งค์ฐ ์ง์ ๋ถํด์ง๋ค..
๊ทธ๋์, ์ด ๋ฌธ์ ๋ฅผ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉด ํด๊ฒฐํ ์ ์๋ค!
@RestController
@RequestMapping("/api/v1/posts")
@RequiredArgsConstructor
public class PostApiController {
private final PostService postService;
@Tag(name = "Post", description = "๊ฒ์๊ธ ๊ด๋ จ API")
@Operation(summary = "๊ฒ์๊ธ ์กฐํ", description = "๐ก์นดํ
๊ณ ๋ฆฌ์ ์๊ด์์ด ๋ชจ๋ ๊ฒ์๊ธ์ ํ์ด์ง๋ก ์กฐํํฉ๋๋ค.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "โญ SUCCESS", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
examples = {@ExampleObject(value = "{\"message\":\"SUCCESS\",\"result\":{\"content\":[{\"postId\":1,\"title\":\"title\",\"content\":\"content\",\"category\":\"category\",\"userId\":1,\"nickName\":\"nickName\",\"userName\":\"userName\",\"createdDate\":\"2023/04/27 21:14\",\"lastModifiedDate\":\"2023/04/27 21:14\",\"imageUrl\":\"imageUrl\",\"view\":0,\"totalNumOfComments\":0,\"totalNumOfLikes\":0},{\"postId\":2,\"title\":\"title\",\"content\":\"content\",\"category\":\"category\",\"userId\":1,\"nickName\":\"nickName\",\"userName\":\"userName\",\"createdDate\":\"2023/05/13 00:15\",\"lastModifiedDate\":\"2023/05/13 00:15\",\"imageUrl\":\"imageUrl\",\"view\":0,\"totalNumOfComments\":0,\"totalNumOfLikes\":0}],\"pageable\":{\"sort\":{\"empty\":true,\"sorted\":false,\"unsorted\":true},\"offset\":0,\"pageNumber\":0,\"pageSize\":20,\"unpaged\":false,\"paged\":true},\"totalPages\":1,\"totalElements\":2,\"last\":true,\"size\":20,\"number\":0,\"sort\":{\"empty\":true,\"sorted\":false,\"unsorted\":true},\"numberOfElements\":2,\"first\":true,\"empty\":false}}")}, schema = @Schema(implementation = Response.class))),
})
@GetMapping
public ResponseEntity<Response<Page<PostGetResponse>>> getAll(Pageable pageable) {
Page<PostGetResponse> response = postService.getAllPosts(pageable);
return ResponseEntity.ok(Response.success(response));
}
}
์์ ๊ฐ์ ์ฝ๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํด๋ณด๊ฒ ๋ค.
public interface PostApiSpecification {
@Tag(name = "Post", description = "๊ฒ์๊ธ ๊ด๋ จ API")
@Operation(summary = "๊ฒ์๊ธ ์กฐํ", description = "๐ก์นดํ
๊ณ ๋ฆฌ์ ์๊ด์์ด ๋ชจ๋ ๊ฒ์๊ธ์ ํ์ด์ง๋ก ์กฐํํฉ๋๋ค.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "โญ SUCCESS", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
examples = {@ExampleObject(value = "{\"message\":\"SUCCESS\",\"result\":{\"content\":[{\"postId\":1,\"title\":\"title\",\"content\":\"content\",\"category\":\"category\",\"userId\":1,\"nickName\":\"nickName\",\"userName\":\"userName\",\"createdDate\":\"2023/04/27 21:14\",\"lastModifiedDate\":\"2023/04/27 21:14\",\"imageUrl\":\"imageUrl\",\"view\":0,\"totalNumOfComments\":0,\"totalNumOfLikes\":0},{\"postId\":2,\"title\":\"title\",\"content\":\"content\",\"category\":\"category\",\"userId\":1,\"nickName\":\"nickName\",\"userName\":\"userName\",\"createdDate\":\"2023/05/13 00:15\",\"lastModifiedDate\":\"2023/05/13 00:15\",\"imageUrl\":\"imageUrl\",\"view\":0,\"totalNumOfComments\":0,\"totalNumOfLikes\":0}],\"pageable\":{\"sort\":{\"empty\":true,\"sorted\":false,\"unsorted\":true},\"offset\":0,\"pageNumber\":0,\"pageSize\":20,\"unpaged\":false,\"paged\":true},\"totalPages\":1,\"totalElements\":2,\"last\":true,\"size\":20,\"number\":0,\"sort\":{\"empty\":true,\"sorted\":false,\"unsorted\":true},\"numberOfElements\":2,\"first\":true,\"empty\":false}}")}, schema = @Schema(implementation = Response.class))),
})
@GetMapping
ResponseEntity<Response<Page<PostGetResponse>>> getAll(Pageable pageable);
}
์์ ๊ฐ์ API ๋ช ์ธ๋ฅผ ์ํ ์ด๋ ธํ ์ด์ ์ ๋ถ๋ฆฌํ ์ ์๋ ์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๋ค.
@RestController
@RequestMapping("/api/v1/posts")
@RequiredArgsConstructor
public class PostApiController implements PostApiSpecification {
private final PostService postService;
@GetMapping
public ResponseEntity<Response<Page<PostGetResponse>>> getAll(Pageable pageable) {
Page<PostGetResponse> response = postService.getAllPosts(pageable);
return ResponseEntity.ok(Response.success(response));
}
}
๊ทธ๋ฆฌ๊ณ ๊ธฐ์กด ์ฝ๋์ ์ค์จ๊ฑฐ ๊ด๋ จ ์ด๋ ธํ ์ด์ ์ ์ง์ฐ๊ณ
์ ์ํ PostApiSpecification
์ธํฐํ์ด์ค๋ฅผ implements
ํด์ค๋ค.
๊ทธ๋ฌ๋ฉด, API ๊ด๋ จ ์ด๋ ธํ ์ด์ ์ค๋ช ์ ์ธํฐํ์ด์ค ํ ๊ณณ์ ๋ชฐ์์ ์์ฑํ ์ ์์ด ๊ธฐ์กด ์ฝ๋์ ๋ถ๋ฆฌ์ํฌ ์ ์๋ค!
์๋ฐ์ ์์๊ณผ ๋คํ์ฑ ๊ทธ๋ฆฌ๊ณ Spring์ ์๋ฆฌ๋ง ์๋ฉด ์ฝ๊ฒ ์ ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ด์๋๋ฐ,
๋ค๋ฆ๊ฒ ๋ฐฉ๋ฒ์ด ๋ ์ฌ๋ผ์ ์ ์ฉํ๊ฒ ๋์๋ค.
