๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Spring

Spring ํ”„๋กœ์ ํŠธ์— Swagger2 ์ ์šฉ

Swagger2 ์ ์šฉ

API ๋ฌธ์„œ ์ž๋™ํ™”๋ฅผ ํ•ด์ฃผ๋Š” Swagger2๋ฅผ ์Šคํ”„๋ง ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด์ž.

์˜์กด์„ฑ ์ถ”๊ฐ€

gradle์„ ์ด์šฉํ•œ๋‹ค๋ฉด build.gradle์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค.

    compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
    compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'

Swagger2Config

Config ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์€ Config ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@EnableSwagger2
@Configuration
public class Swagger2Config {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.cadi.team3"))
                .paths(PathSelectors.ant("/api/**"))
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("cadi project")
                .version("1.0")
                .description("movie & sns project apis")
                .build();
    }
}

config์— ๋“ฑ๋ก๋œ Docket Bean์œผ๋กœ Swagger๊ฐ€ ์ ์šฉ๋  ์ „์ฒด ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ด ์ค€๋‹ค.

base๊ฐ€ ๋˜๋Š” package์™€ Swagger2๋กœ ํ™•์ธํ•  api์˜ ์š”์ฒญ ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ๊ณ , ๋ฐ”๋กœ ๋ฐ‘์— ์„ ์–ธํ•œ apiInfo ๋ฉ”์„œ๋“œ๋ฅผ apiInfo๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

apiInfo()๋Š” ApiInfoBuilder()๋ฅผ ์ด์šฉํ•ด ์ง๊ด€์ ์œผ๋กœ api ๋ฌธ์„œ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฌธ์„œ์˜ ์ด๋ฆ„, ๋ฒ„์ „, ์„ค๋ช… ๋“ฑ์„ ์„ค์ •ํ•˜๊ณ  build() ํ•ด์ค€๋‹ค.

Controller์—์„œ api ๋ถ€๊ฐ€ ์ •๋ณด ์„ค์ •

๋‹ค์Œ๊ณผ ๊ฐ™์ด swagger-ui์— ๋“ฑ๋กํ•  api ์„ค๋ช…์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

@RequiredArgsConstructor
@RestController
@RequestMapping("/api")
public class AccountController {

    private final AccountService accountService;

    @PostMapping("/sign-up")
    @ApiOperation(value = "ํšŒ์›๊ฐ€์ž…", notes = "signupDto๋กœ ์ „์†ก")
    public ResponseEntity<?> singUpRequest(@RequestBody @Valid SignupDto signupDto, Errors errors){
        return accountService.signUp(signupDto, errors);
    }

    @GetMapping("/get-account")
    @ApiOperation(value = "๋กœ๊ทธ์ธ ํšŒ์›์ •๋ณด ์กฐํšŒ")
    public ResponseEntity<?> getAccount(@AuthenticationPrincipal AccountPrincipal accountPrincipal){
        return new ResponseEntity<>(accountPrincipal, HttpStatus.OK);
    }

}

@ApiOperation(value = "ํšŒ์›๊ฐ€์ž…", notes = "signupDto๋กœ ์ „์†ก")
@ApiOperation์„ ์ด์šฉํ•ด value ๊ฐ’๊ณผ notes๋กœ ๋ถ€๊ฐ€ ์„ค๋ช…์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค.

Spring Security ์„ค์ •

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์™€ Swagger2๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด Security์˜ ๋ณด์•ˆ์— ์˜ํ•ด swagger2์˜ ui๊ฐ€ ์ž‘๋™ ์•ˆ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด WebSecurityConfigurerAdapter๋ฅผ ์ƒ์†ํ•œ SecurityConfig์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•ด์ค€๋‹ค.

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/v2/api-docs/**");
        web.ignoring().antMatchers("/swagger.json");
        web.ignoring().antMatchers("/swagger-ui.html");
        web.ignoring().antMatchers("/swagger-resources/**");
        web.ignoring().antMatchers("/webjars/**");
    }

Swagger ํ™•์ธ

baseUrl ๋’ค์— "/swagger-ui.html"์„ ๋ถ™์—ฌ์ฃผ๊ณ  ์›น์—์„œ ์ ‘์†ํ•ด๋ณด์ž.

ํ™”๋ฉด์— ๋‚˜์˜ค๋Š” api๋ฅผ swagger2๋ฅผ ํ†ตํ•ด ์ ๊ฒ€ํ•˜๊ณ  ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.