오늘은 Swagger를 적용해서 API 문서 자동화를 하는 방법에 대해서 알아보겠습니다. 사이드 프로젝트를 진행하면서 프론트 개발자에게 API정의서를 만들어서 공유를 했었는데, 기존 API가 변경되면 API문서도 같이 변경을 해줘야하고, 실수할 확률도 어느정도 있었습니다. 그 와중에 Swagger-UI라는 것을 찾았고 이를 적용하여 API를 볼 수 있을 뿐만 아니라 API 호출까지 할 수 있었습니다. 아래 사진은 swagger로 API 문서화를한 예시입니다.
1. Swagger-UI란?
- 일반적인 동작, 패턴 및 일관된 UI로 RESTful API를 공유한다.
- API가 발전함에 따라 문서를 최신 상태유지한다.
- API 문서를 생성, 시각화 및 유지 관리가 편리하다.
- 문서화된 API에 대해 테스트 또한 가능하다.
즉, 자바코드를 작성할때 API에 대한 정보를 코드로 작성하여 문서 자동화를 하는 것입니다. 이렇게 했을 때 기존보다 편한 점은 코드를 짜면서 API 문서를 함께 수정할 수 있기 때문에 나중에 문서를 고치는 귀찮음이 조금 덜해졌습니다. 또한 UI적으로도 보기 편하고, 테스트 또한 가능하다는 장점이 있습니다.
아래 사이트에서 스프링부트에 swagger를 적용하는 튜토리얼을 볼 수 있습니다.
https://www.baeldung.com/swagger-2-documentation-for-spring-rest-api
2. 개발환경
- OS : Window 10
- IDE : Intellij
- Framework : Spring Boot2
- Build Tool : maven
- Lombok 적용
3. Spring Boot 적용
먼저 pom.xml에 swagger를 사용하기 위해 의존성을 추가해줍니다.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
이제 Swagger Config 클래스를 작성합니다. 제가 만든 프로젝트의 이름이 Devcrews라 그룹 이름과 제목을 제 프로젝트에 맞게 작성하였습니다.
@Configuration
@EnableSwagger2
public class SwaggerConfig {
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Devcrews api info")
.description("Devcrews API")
.build();
}
@Bean
public Docket commonApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("DevCrews")
.apiInfo(this.apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.contest.calendar.controller"))
.paths(PathSelectors.ant("/api/**"))
.build();
}
}
- Swagger의 구성은 Docket Bean을 중심으로합니다. @EnableSwagger2 애노테이션을 통하여 Swagger2를 활성화 시킵니다.
- Docket Bean이 정의되면 select () 메소드는 Swagger에 의해 노출 된 엔드 포인트를 제어하는 방법을 제공하는 ApiSelectorBuilder 인스턴스를 리턴합니다.
- RequestHandlerSelectors 및 PathSelectors를 사용하여 API에 대한 문서를 사용할 수 있도록 지정을 합니다. RequestHandlerSelectors.any(), pathSelectors.any()를 사용하면 Swagger를 통해 전체 API에 대한 문서를 사용할 수 있습니다. 저는 controller 패키지와 api로 url이 시작하는 부분만 문서화를 하였습니다.
Controller에 적용하기 전 소스입니다. 게시글 번호를 받아서 게시글의 정보를 Json 객체로 반환해주는 부분입니다. SwaggerConfig에서 api로 시작하는 부분을 문서로 만들기로 정의했기 때문에 앞에 "/api/board/{boardNo}"는 문서 자동화 대상이 됩니다.
@Controller
public class BoardController {
private final BoardServiceImpl boardService;
private final MemberService memberService;
@Autowired
public BoardController(BoardServiceImpl boardService, MemberService memberService){
this.boardService = boardService;
this.memberService = memberService;
}
@GetMapping(value="/api/board/{boardNo}")
public @ResponseBody HashMap<String, Object> getBoardDtl(BoardDto boardDto){
String resultMsg;
HashMap<String, Object> resultMap =new HashMap<>();
try {
BoardDto resultBoardDto = boardService.getBoardDtl(boardDto);
resultMap.put("status", HttpStatus.OK);
resultMap.put("resultCode", "success");
resultMap.put("boardDto", resultBoardDto);
} catch(RuntimeException e){
e.printStackTrace();
resultMsg="게시글조회에 실패하였습니다.";
resultMap.put("resultMsg", resultMsg);
resultMap.put("resultCode", "fail");
}
return resultMap;
}
}
이제 Swagger 문서화를 위해 적용한 소스입니다. @ApiOpertaion을 정의해주었고, 파라미터 정보는 @ApiImplicitParams와, @ApiImplicitParam을 통해 정의해주었습니다. @ApiIgnore와 @ModelAttribute 애노테이션을 사용하면 지정한 파라미터만 API문서에 parameter로 지정이 됩니다. 여기서는 boardNo만 파라미터로 등록되는 것 입니다.
@Api(value = "게시글 API")
@Controller
public class BoardController {
private final BoardServiceImpl boardService;
private final MemberService memberService;
@Autowired
public BoardController(BoardServiceImpl boardService, MemberService memberService){
this.boardService = boardService;
this.memberService = memberService;
}
@GetMapping(value="/api/board/{boardNo}")
@ApiOperation(value = "getBoardDtl", tags = "게시글 상세 페이지 조회")
@ApiImplicitParams({
@ApiImplicitParam(name = "boardNo", value = "게시글 번호", dataType = "long", paramType = "query", defaultValue = "16", required = true),
})
public @ResponseBody HashMap<String, Object> getBoardDtl(@ApiIgnore @ModelAttribute BoardDto boardDto){
String resultMsg;
HashMap<String, Object> resultMap =new HashMap<>();
try {
BoardDto resultBoardDto = boardService.getBoardDtl(boardDto);
resultMap.put("status", HttpStatus.OK);
resultMap.put("resultCode", "success");
resultMap.put("boardDto", resultBoardDto);
} catch(RuntimeException e){
e.printStackTrace();
resultMsg="게시글조회에 실패하였습니다.";
resultMap.put("resultMsg", resultMsg);
resultMap.put("resultCode", "fail");
}
return resultMap;
}
}
이제 localhost:포트번호/swagger-ui.html로 접속을 하면 아래와 같이 작성한 api 정보를 볼 수 있습니다.
REFERENCE
https://www.baeldung.com/swagger-2-documentation-for-spring-rest-api
'Spring Boot' 카테고리의 다른 글
[Spring Boot] Resource 추상화 (0) | 2020.08.27 |
---|---|
[Spring Boot] @Valid를 이용한 유효성 검사 (0) | 2020.08.09 |
[Spring Boot] JUnit을 활용한 테스트 코드 작성(1) (0) | 2020.05.03 |
[Spring Boot] 의존성 주입 생성자 주입 (0) | 2020.05.03 |
[Spring Boot] 타임리프(Thymeleaf) 엔진 (0) | 2020.03.04 |