매일 한줄 코딩

#5] Spring Swagger 설정하기 본문

develop/spring

#5] Spring Swagger 설정하기

ShipJH 2021. 9. 29. 00:20

스웨거란, API를 자동으로 문서화 해주는 기능이다.

또한, 사용자가 실제로 API를 호출해 볼 수 있는 기능을 제공한다.

입력값이나 응답값등을 페이지 내에서 설정하여 호출해 볼 수 있다는 장점이 있다.

https://swagger.io

 

API Documentation & Design Tools for Teams | Swagger

 

swagger.io

 

자세한 내용은 위의 스웨거 공식사이트에서 확인이 가능하다.

 

Springboot에서 스웨거를 설정하여 앞으로 만들 API를 자동 문서화 해보도록 할 것이다.

 

사용하기 위해서는 스웨거 라이브러리를 추가하여야한다.

 

https://mvnrepository.com/

위에 직접 검색해서 추가하여도 된다. 

 

maven일 경우

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.8.0</version>
        </dependency>

 

gradle일 경우

implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.8.0'
implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.8.0'

 

 

추가하여준다. 버전은 원하시는 버전으로 다운받길 바란다. 현재 3.0 까지 나와있으나 2점대로 받았다.

사실 2나 3이나 별 차이없어보인다. ( 특별한 이유 없으면 2를 개인적으로 권함.. ) 

 

그다음, 

Swagger를 사용하기 위한 설정이 필요하다.

아래와 같이 설정하여 준다.

package com.cc.kr.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;

import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration	// 스프링 실행시 설정파일 읽어드리기 위한 어노테이션 
@EnableSwagger2	// Swagger2를 사용하겠다는 어노테이션 
@SuppressWarnings("unchecked")	// warning밑줄 제거를 위한 태그 
public class SwaggerConfig extends WebMvcConfigurationSupport {

	//리소스 핸들러 설
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
		registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
		registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
	}


    // API마다 구분짓기 위한 설정.
	@Bean
    public Docket productApi() {
        return getDocket("유저", Predicates.or(
                PathSelectors.regex("/user.*")));
    }

    
    @Bean
    public Docket searchApi() {
        return getDocket("예약", Predicates.or(
                PathSelectors.regex("/reservation.*")));
    }

    
    @Bean
    public Docket commonApi() {
        return getDocket("공통", Predicates.or(
                PathSelectors.regex("/test.*")));
        		
    }

    @Bean
    public Docket allApi() {
        return getDocket("전체", Predicates.or(
                PathSelectors.regex("/*.*")));
    }
    
    //swagger 설정.
    public Docket getDocket(String groupName, Predicate<String> predicate) {
        return new Docket(DocumentationType.SWAGGER_2)
        		.groupName(groupName)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.cc.kr"))
                .paths(predicate)
                .apis(RequestHandlerSelectors.any())
                .build();
    }
    
    //swagger ui 설정.
    @Bean
    public UiConfiguration uiConfig() {
        return UiConfigurationBuilder.builder()
                .displayRequestDuration(true)
                .validatorUrl("")
                .build();
    }
	
}

여기까지 해주면 기본적인 설정이 끝난다.

 

그다음 제대로 실행이 되는지 확인을 해본다

applicaion run하고 난 뒤,

 

localhost:[port]/swagger-ui.html

의 형태로 들어가본다.

혹시 404가 발생한다면 server.servlet.context 문제일지도 모른다.

그럴 경우 applicaion.properties에 아래와 같이 설정해준다.

server.servlet.context-path=/

처럼 추가 하고 난 뒤 다시 실행해서 들어가지는지 확인한다.

 

 

위 SwaggerConfig에 API마다 구분짓기라고 되어있는 부분들은

실제 컨트롤러의 URL 규칙에 따라 그룹으로 묶인다.

필자 같은경우 3가지로만 먼저 그룹지어보았다.
/user, /test, /reservation 으로 시작하는 것들끼리만 묶었다.

 

그다음 전체로는 모든 URL을 /*.* 로써 전부 보여지게 만들었다.

그렇다고 하나씩 API가 나오는 것이 아닌 그룹별로 그룹지어서 나오기 때문에 보기 아주 편하다.

 

그룹별로 묶었던 SwaggerConfig가 잘 반영됬는지 확인한다.

 

 

처음 실행하면 위처럼 기본적으로 영어로만 나오게 되는데,

전체로 보았을때 필자같은 경우 예약이라는 글자는 한글로 나왔다.

 

컨트롤러에 swagger의 어노테이션을 주게되면 반영이 가능하다.

위처럼 @Api 어노테이션은 큰 대제목을 뜻하고, 

@ApiOperation은 각각 API 마다 명칭을 줄 수 있다.

 

 

이번엔 예약 조회 API의 샘플로 실제 실행까지 진행하여 보겠다.

코드는 간단하다. 사용자에게 name과 age를 받으면 Reservation의 객체를 리턴해주는 형태의 샘플이다.

위는 Reservation의 객체이다

모델객체의 설명과 각각 변수의 설명을 덫붙일 수 있다. 더 많은 옵션도 있으니 필요에따라 사용하면 된다.

 

 

parameters와 Response를 보여준다.

Response 같은경우 Reservation객체에 기입했던 내용들을 볼 수 있다.

 

이제 우측 상단에 Try it out 을 누른 뒤,

name과 age를 입력하여 보자.

입력후 Execute 를 누르면 실제 API가 호출이된다.

파라미터를 던진것이 Json형태로 잘 리턴되는 것을 볼 수 있다.

 

이런식으로 API를 어노테이션 몇개로 손쉽게 만들 수 있다.

 

 

그 외에 글로벌한 변수설정이나, 에러에대한 정보 변경등 많은 커스터마이징이 가능하다.

 

 

 

먼저 에러에 대한 정보를 UI에 적용하여보자.

package com.cc.kr.config;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;

import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration	// 스프링 실행시 설정파일 읽어드리기 위한 어노테이션 
@EnableSwagger2	// Swagger2를 사용하겠다는 어노테이션 
@SuppressWarnings("unchecked")	// warning밑줄 제거를 위한 태그 
public class SwaggerConfig extends WebMvcConfigurationSupport {

	//리소스 핸들러 설
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
		registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
		registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
	}


    // API마다 구분짓기 위한 설정.
	@Bean
    public Docket productApi() {
        return getDocket("유저", Predicates.or(
                PathSelectors.regex("/user.*")));
    }

    
    @Bean
    public Docket searchApi() {
        return getDocket("예약", Predicates.or(
                PathSelectors.regex("/reservation.*")));
    }

    
    @Bean
    public Docket commonApi() {
        return getDocket("공통", Predicates.or(
                PathSelectors.regex("/test.*")));
        		
    }

    @Bean
    public Docket allApi() {
        return getDocket("전체", Predicates.or(
                PathSelectors.regex("/*.*")));
    }
    
    //swagger 설정.
    public Docket getDocket(String groupName, Predicate<String> predicate) {
        return new Docket(DocumentationType.SWAGGER_2)
        		.groupName(groupName)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.cc.kr"))
                .paths(predicate)
                .apis(RequestHandlerSelectors.any())
                .build()
                .globalResponseMessage(RequestMethod.GET, getCustomizedResponseMessages())
                .globalResponseMessage(RequestMethod.POST, getCustomizedResponseMessages())
                .globalResponseMessage(RequestMethod.DELETE, getCustomizedResponseMessages())
                .globalResponseMessage(RequestMethod.PUT, getCustomizedResponseMessages())
                .globalResponseMessage(RequestMethod.PATCH, getCustomizedResponseMessages());
    }
    
    //swagger ui 설정.
    @Bean
    public UiConfiguration uiConfig() {
        return UiConfigurationBuilder.builder()
                .displayRequestDuration(true)
                .validatorUrl("")
                .build();
    }
    
    
    private List<ResponseMessage> getCustomizedResponseMessages() {
        List<ResponseMessage> responseMessages = new ArrayList<>();
        responseMessages.add(new ResponseMessageBuilder().code(200).message("성공").build());
        responseMessages.add(new ResponseMessageBuilder().code(204).message("데이터 미존재").build());
        responseMessages.add(new ResponseMessageBuilder().code(400).message("입력값 오류").build());
        responseMessages.add(new ResponseMessageBuilder().code(401).message("미 로그인").build());
        responseMessages.add(new ResponseMessageBuilder().code(403).message("권한없음").build());
        responseMessages.add(new ResponseMessageBuilder().code(412).message("처리중 오류").build());
        responseMessages.add(new ResponseMessageBuilder().code(500).message("서버에러").build());
        return responseMessages;
    }
	
}

위의 SwaggerConfig.java 와의 차이는 HttpStatusCode에 따라서, 각각 어떠한 형태인지 알려주고자 하는 설정이 추가되었다.

이렇게 실행한다면 

위 처럼 에러코드에대한 설명을 추가 할 수 있다.

 

 

 

Swagger는 운영환경에서는 실행되지 않도록 하는것이 좋다. 실수로 누르거나 다른 사용자가 실행을 할 경우도 있기 때문이다.

그런것은 SwaggerConfig에서 아래와 같이 추가한 뒤

@Profile(value = "!prod")

properties에 아래와같이 추가해주면 된다.

spring.profiles.active=prod

 

이것은, prod 라는 명칭의 profiles인 운영환경에서는 스웨거가 작동하지않고

!prod 일 경우에만 스웨거를 설정할 수 있게 된다. 

 

 

Comments