티스토리 뷰

웹 서비스 개발하기에 앞서, API 개발과 RESTfull API를 문서화 할 수 있는 Swagger 를 먼저 설정한 후 진행 할 예정이다.

API 문서를 완성하고 스펙이 변경 될 때 마다 문서를 수정하는건 엄청나게 귀찮은 일이기 때문에.....

Swagger 의 경우, 내가 생각하는 장점은 아래와 같다.

 

  • Swagger 를 적용한 MSA 기반 API 서버에서, 간단한 설정만으로 UI 제공 
  • Swagger-UI 는 API 의 스펙을 확인할 수 있고, 파라미터 입력 후 실행할 수 있다 (RestClient 툴을 사용안해도 됨!)
  • 간단한 Annotation 을 통해 문서에 표기할 수 있고, 주석(?)을 겸할 수 있다.
  • 개발과 동시에 문서까지 적용하는 일거 양득 !! 
  • 쉽게 적용할 수 있고, 사용법도 엄청나게 간단 하다.
  • Swagger UI 가 이쁨

실제 업무에서도 많이 쓰고 있기 때문에, 경험해보지 못한 분들이라면 꼭 써보라고 추천함 ++

아참, 그리고 이전장에서 프로젝트 생성한 부분에 패키지 및 파일명을 변경하는 작업도 이번에 같이할거임.

 


 

1.  Gradle 설정

프로젝트 build.gradle 파일 dependencies 하위에 swagger 정보를 추가해주자.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // swagger
    compile("io.springfox:springfox-swagger2:2.9.2")
    compile("io.springfox:springfox-swagger-ui:2.9.2")

    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'com.h2database:h2'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

 

2. Config 설정

com.mellowp.bookstore 하위에 config 패키지를 추가한 후, "SwaggerConfiguration" 클래스를 생성.

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {

    @Bean
    public Docket apiDocket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                // Api Annotation 으로 선언된 부분만 swagger 로 노출되도록 설정
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build()
                .useDefaultResponseMessages(false)
                .enableUrlTemplating(false)
                .apiInfo(new ApiInfoBuilder()
                                .title("BookStore Rest API")
                                .version("0.1")
                                .description("<pre style=\"font-size: .85em;line-height: 1.2em;\">Global Response Entity : <code>{\"code\":{결과코드},\"isOk\":{결과여부},\"message\":{결과메세지},\"body\":{데이터}}</code></pre>")
                                .build()
                );
    }

}

 

Swagger2 는 @EnableSwagger2 어노테이션으로 설정이 가능하며, @Configuration 을 통해 등록되게끔 클래스위에

추가 하였다. 또한 Swagger 의 각 종 설정 같은 경우, Docket 을 통해 가능하게 된다.

 

.select()

ApiSelectorBuilder 인스턴스를 리턴하며, endpoint를 제어하는 역할을 한다.

.apis()

RequestMapping 으로 할당된 모든 URL 리스트 중, RequestHandlerSelectors 를 통해 적용할 패키지를 선택할 수 있다.

나의 경우, @ApiOperation 어노테이션이 붙은 부분만 노출 되도록 선언 하였다.

  - RequestHandlerSelectors.any() : 전체 적용

  - RequestHandlerSelectors.none() : 전체 미적용

  - RequestHandlerSelectors.basePackage(String path) : path 에 해당하는 부분만 적용

.paths()

위에 언급한 apis() 메소드를 통해 적용할 URL 목록이 오게 되고, 이에 대한 필터링을 적용할 수 있다.

나는 필터링을 하지 않았지만, 아래와 같이 필터링 할 수도 있다.

- PathSelectors.ant("/api/*") 

.useDefaultResponseMessage()

디폴트로 반환할 메세지를 설정할건지에 대한 여부를 묻는다.

.enableUrlTemplating(false)

@RequestParam 또는 @ModelAttribute 사용 시 path가 아래와 같이 나오기 때문에, 나는 Fasle 로 설정 하였다.

GET /user/{id}/info{?startDate,endDate}

.apiInfo()

ApiInfoBuilder 를 통해 API 에 대한 설명을 진행할 수 있다.

 

3. Controller 설정

bookstore 하위에 web 과 api 패키지를 생성하고, api 패키지 하위로는 controller 패키지를 추가로 생성 한다.

bookstore.api.controller 에 BookController 클래스를 생성후 아래와 같이 작성.

@RestController
@Api(tags = "/v1 Book API")
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@ApiResponses(value = { @ApiResponse(code = 404, message = "Not Found"),
                        @ApiResponse(code = 500, message = "Internal Server Error") })
public class BookStoreController {


    @GetMapping("/v1/book/list")
    @ApiOperation(value = "도서 목록 조회", response = List.class, notes = "/v1 도서 목록 조회")
    public List<Map<String, String>> searchBookList(){
        return Arrays.asList(
                ImmutableMap.<String, String>builder().put("title", "Book 01").put("author", "Lion").build(),
                ImmutableMap.<String, String>builder().put("title", "Book 02").put("author", "Lion").build(),
                ImmutableMap.<String, String>builder().put("title", "Book 03").put("author", "Lion").build()
        );
    }

    @GetMapping("/v1/book/info")
    @ApiOperation(value = "도서 상세 조회", response = Map.class, notes = "/v1 도서 상세 조회")
    public Map<String, String> searchBookInfo(@RequestParam(value = "num") String num){
        return null;
    }

    @PostMapping("/v1/book/create")
    @ApiOperation(value = "도서 등록", response = Boolean.class, notes = "/v1 도서 등록")
    public Boolean createBook(){
        return true;
    }

    @PutMapping("/v1/book/modify")
    @ApiOperation(value = "도서 정보 수정", response = Boolean.class, notes = "/v1 도서 정보 수젇")
    public Boolean modifyBook(){
        return true;
    }

    @DeleteMapping("/v1/book/remove")
    @ApiOperation(value = "도서 정보 삭제", response = Boolean.class, notes = "/v1 도서 정보 삭제")
    public Boolean removeBook(){
        return true;
    }

}

아직 서비스를 구현하기 전이고, 임시로 endPoint 만 만들어서 swagger-ui 를 확인하기 위해 test 성으로 추가 하였다.

파라미터 및 응답 DTO 에도 Annotation 을 사용해 작성하게 되면 swagger-ui 에서 상세하게 볼 수 있기 때문에, 

이 부분에 대한 확인은 서비스 개발 중반부에 다시 확인하여 비교하도면 될 것 같다.

 

4. swagger-ui 확인

해당 프로젝트를 bootRun 한뒤, 주소창에 http://localhost:8080/swagger-ui.html 으로 접속을 통해 확인 하자 !!

아래에 보면 apiInfo 에 설정한 화면이 메인상단에 노출되며 html 코드도 적용이 되는 부분을 볼 수 있다.

컨트롤러 별로 분류하여 상세 EndPoint 가 노출되는 형식이며, 색깔별로 Mehtod 방식을 구분할 수도 있고, 맨 하단에

Models 부분으로 해당 API 에서 사용하고 있는 모델 부분들도 한눈에 확인이 가능하게 된다.

swagger main

위에 메인 화면에서 API 를 선택하면, 아래 그림처럼 열리게 되고 이 화면을 통해서 API 테스트 실행 및 스펙을 확인할 수 있다.

swagger api excute

실행(Excute)을 할 경우, Curl 과 Request Url 방식을 보여주고 실행한 결과는 Response Body 에 노출이 된다.

만약 API에서 파라미터 정보가 존재할 경우, 입력할 수 있는 칸이 생성되며 필수값에는 * 로 표기가 되어있는 부분도

확인이 가능하다. 추가로 더 상세하게 확인해보고 싶다면 아래 링크를 참조하면 많은 도움이 될 것이다.

 

참조: https://www.baeldung.com/swagger-2-documentation-for-spring-rest-api

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday