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

Spring/Boost Course Web

4.5 Swagger

1) Swagger ๊ฐœ์š”

1. ์Šค์›จ๊ฑฐ(Swagger)๋ž€?

์Šค์›จ๊ฑฐ๋Š” Web API ๋ฌธ์„œํ™”๋ฅผ ์œ„ํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

์Šค์›จ๊ฑฐ ํ™ˆํŽ˜์ด์ง€(https://swagger.io)์—์„œ๋Š” ์Šค์›จ๊ฑฐ๋ฅผ OAS(Open API Specification)์ด๋ผ๊ณ  ์†Œ๊ฐœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋ง๊ทธ๋Œ€๋กœ API๋“ค์ด ๊ฐ€์ง€๋Š” ๋ช…์„ธ(Spec)์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กœ์ ํŠธ๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Web API๋ฅผ ์ˆ˜๋™์œผ๋กœ ๋ฌธ์„œํ™” ํ•˜๋Š” ๊ฒƒ์€ ๊ต‰์žฅํžˆ ํž˜๋“  ์ž‘์—…์ž…๋‹ˆ๋‹ค.

Web API์˜ ์ŠคํŽ™์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ ๋ฌธ์„œ ์—ญ์‹œ ๋ณ€๊ฒฝ์ด ๋˜์•ผ ํ•˜๋Š”๋ฐ ์ด๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์‰ฝ์ง€๊ฐ€ ์•Š์Šต๋‹ˆ๋‹ค.

 

Swagger๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Web API๊ฐ€ ์ˆ˜์ •๋˜๋”๋ผ๋„ ์ƒ๊ด€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ๊ฐ€ ์ž๋™์œผ๋กœ ๊ฐฑ์‹ ์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

2. ์Šค์›จ๊ฑฐ์˜ ๊ธฐ๋Šฅ

์Šค์›จ๊ฑฐ ํ™ˆํŽ˜์ด์ง€๋ฅผ ๊ฐ€๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

1) API Design

2) API Development

3) API Documentation

4) API Testing

5) API Mocking and Virtualization

6) API Governance

7) API Monitoring

8) OpenAPI & Swagger

 

Web API๋ฅผ ๋งŒ๋“œ๋Š” ๊ฐœ๋ฐœ์ž์™€ Web API๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Web API๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋Š” Web API๊ฐ€ ๋งŒ๋“ค์–ด์งˆ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค๋ฉด ์ž‘์—…์ด ์ƒ๋‹นํžˆ ๋Š๋ ค์งˆ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Web API๋ฅผ ๋งŒ๋“œ๋Š” ์‚ฌ๋žŒ๊ณผ Web API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ ๊ฐ„์— ๋ฏธ๋ฆฌ ๋ช…์„ธ๋ฅผ ์ •์˜ํ•˜๊ณ  ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด

๊ฐœ๋ฐœ์ด ์ƒ๋‹นํžˆ ํŽธ๋ฆฌํ•ด ์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ง€๊ธˆ ์ด์•ผ๊ธฐ ํ•œ ๊ฒƒ๋“ค์„ ํŽธํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ๋„๊ตฌ ์ค‘์— ํ•˜๋‚˜๊ฐ€ ‘์Šค์›จ๊ฑฐ’๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. ์Šค์›จ๊ฑฐ ํ—ˆ๋ธŒ๋ฅผ ์ด์šฉํ•˜์—ฌ API๋ฅผ ๋ช…์„ธํ™” ํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ

์Šค์›จ๊ฑฐ ํ—ˆ๋ธŒ ์‚ฌ์ดํŠธ๋ฅผ ์ด์šฉํ•˜๋ฉด Web API๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋”๋ผ๋„ Web API๋ฅผ ๋ช…์„ธํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, Web API๋ฅผ ๋ช…์„ธํ™”๋งŒ ํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ๊ฐ„๋‹จํžˆ ํ…Œ์ŠคํŠธ๋„ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.


2) Swagger ์„ค์ •ํ•˜๊ธฐ

์ฝ”๋“œ๋งํฌ: calculator06

1. pom.xml ํŒŒ์ผ ์ˆ˜์ •

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

2. WebAppInitializer ํด๋ž˜์Šค ์ž‘์„ฑํ•˜๊ธฐ

์ž๋ฐ” ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ๋•Œ๋Š” web.xml ํŒŒ์ผ์ด๋‚˜ WebApplicationInitializer๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜ ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์•ž์—์„œ ์„ค๋ช…ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. (Spring MVC๋ฅผ ์ด์šฉํ•œ ์›น ํŽ˜์ด์ง€ ์ž‘์„ฑ ์‹ค์Šต ์ฐธ๊ณ )

์•ž์—์„œ ์„ค๋ช…ํ•œ WebApplicationInitializer๋ฅผ ์•ž์—์„œ๋Š” ์ง์ ‘ ๊ตฌํ˜„ํ–ˆ์—ˆ๋Š”๋ฐ

์ด๋ฒˆ์—๋Š” WebApplicationInitializer๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š” AbstractAnnotationConfigDispatcherServletInitializer๋ฅผ

์ƒ์†๋ฐ›์•„ ์ž‘์„ฑํ•ด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

AbstractAnnotationConfigDispatcherServletInitializer ํด๋ž˜์Šค๋Š” WebApplicationInitializer๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์œผ๋ฉด์„œ

ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋„๋ก ์ œ๊ณตํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

 

WebApplicationInitializer.java

package org.edwith.webbe.calculator.config;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.*;

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	// Spring ๊ธฐ๋ณธ ์„ค์ •ํŒŒ์ผ ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
// ์—ฌ๋Ÿฌ๋ถ„์€ ApplicationConfig.class๋ฅผ ์ž‘์„ฑํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class<?>[] { ApplicationConfig.class };
	}

	// Spring MVC ์„ค์ • ํŒŒ์ผ ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
	// ์—ฌ๋Ÿฌ๋ถ„์€ MvcConfig.class๋ฅผ ์ž‘์„ฑํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class<?>[] { MvcConfig.class };
	}

	/*
	 * DispatcherServlet์ด ๋™์ž‘ํ•  ๋งตํ•‘์ •๋ณด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. "/"๋ฅผ ์„ค์ •ํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋ชจ๋“  ์š”์ฒญ์„ DispatcherServlet์ด
	 * ์ฒ˜๋ฆฌํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
	 */
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}

	/*
	 * ํ•„ํ„ฐ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ๋Š” ์ธ์ฝ”๋”ฉ ํ•„ํ„ฐ๋ฅผ ์„ค์ •ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
	 */
	@Override
	protected Filter[] getServletFilters() {
		CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
		encodingFilter.setEncoding("UTF-8");
		return new Filter[] { encodingFilter };
	}
}

3. ๊ธฐ๋ณธ์ ์ธ ์Šคํ”„๋ง ์„ค์ • ํŒŒ์ผ ์ž‘์„ฑํ•˜๊ธฐ

Spring MVC์—์„œ ์‚ฌ์šฉํ•  Bean๋“ค์„ ์„ค์ •ํ•˜๋Š” ์Šคํ”„๋ง ์„ค์ • ํŒŒ์ผ์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ๋Š” 'org.edwith.webbe.calculator.service' ํŒจํ‚ค์ง€ ์ดํ•˜์˜ Bean๋“ค๋งŒ ์ฐพ๋„๋ก ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

ApplicationConfig.java

package org.edwith.webbe.calculator.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = {"org.edwith.webbe.calculator.service"})
public class ApplicationConfig {
}

4. Spring MVC ์„ค์ • ํŒŒ์ผ ์ž‘์„ฑํ•˜๊ธฐ

MvcConfig.java

package org.edwith.webbe.calculator.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;


@Configuration
@EnableWebMvc
@EnableSwagger2
@ComponentScan(basePackages = {"org.edwith.webbe.calculator.controller.api"})
public class MvcConfig implements WebMvcConfigurer {
	// DefaultServlet์— ๋Œ€ํ•œ ์„ค์ •์„ ํ•ฉ๋‹ˆ๋‹ค.
	// DispatcherServlet์ด ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๋Š” URL์€ DefaultServlet์ด ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
	// ํ•ด๋‹น ์„ค์ •์ด ์—†์œผ๋ฉด ์ž๋™ ์ƒ์„ฑ๋œ Swagger ํŽ˜์ด์ง€๋ฅผ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		configurer.enable();
	}

/*
    	Swagger ์‚ฌ์šฉ ์‹œ์—๋Š” Docket Bean ์„ ํ’ˆ๊ณ ์žˆ๋Š” ์„ค์ • ํด๋ž˜์Šค 1๊ฐœ๊ฐ€ ๊ธฐ๋ณธ์œผ๋กœ ํ•„์š”ํ•˜๋‹ค.
    	Spring Boot ์—์„œ๋Š” ์ด ๊ธฐ๋ณธ์ ์ธ ์„ค์ •ํŒŒ์ผ 1๊ฐœ๋กœ Swagger ์™€ Swagger UI ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜์ง€๋งŒ,
    	Spring MVC ์˜ ๊ฒฝ์šฐ Swagger UI ๋ฅผ ์œ„ํ•œ ๋ณ„๋„์˜ ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค.
    	์ด๋Š”, Swagger UI ๋ฅผ ResourceHandler ์— ์ˆ˜๋™์œผ๋กœ ๋“ฑ๋กํ•ด์•ผ ํ•˜๋Š” ์ž‘์—…์ธ๋ฐ,
    	Spring Boot ์—์„œ๋Š” ์ด๋ฅผ ์ž๋™์œผ๋กœ ์„ค์ •ํ•ด์ฃผ์ง€๋งŒ Spring MVC ์—์„œ๋Š” ๊ทธ๋ ‡์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
     */
	@Bean
	public Docket api() {
		return new Docket(DocumentationType.SWAGGER_2)
				.select()
				.apis(RequestHandlerSelectors.any()) // // ํ˜„์žฌ RequestMapping์œผ๋กœ ํ• ๋‹น๋œ ๋ชจ๋“  URL ๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”์ถœ
				.paths(PathSelectors.ant("/api/**"))// PathSelectors.any() ๋ฅผ ํ• ๊ฒฝ์šฐ ๋ชจ๋“  ๊ฒฝ๋กœ๊ฐ€ ๋‹ค ์‚ฌ์šฉ๋œ๋‹ค. RestController๊ฐ€ ์•„๋‹Œ ๊ฒƒ ๊นŒ์ง€ ์‚ฌ์šฉ๋œ๋‹ค.
				.build()
				.apiInfo(apiInfo())
				.useDefaultResponseMessages(false);
	}

	/**
	 * API Info
	 */
	private ApiInfo apiInfo() {
		Contact contact = new Contact("๊ฐ•๊ฒฝ๋ฏธ", "https://www.edwith.org", "carami@edwith.org");
		ApiInfo apiInfo =
				new ApiInfo("Swagger Sample", "APIs Sample", "Sample Doc 0.1v", "", contact, "This sentence will be display.", "/");
		return apiInfo;
	}
}

ํด๋ž˜์Šค ์œ„์— @EnableWebMvc, @EnableSwagger2๊ฐ€ ๋ถ™์–ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ๊ฐ Spring MVC์„ค์ •, Swagger2์„ค์ •์ด๋ผ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์–ด ์žˆ์„ ๊ฒฝ์šฐ Spring MVC์™€ Swagger2์˜ ๊ธฐ๋ณธ ์„ค์ •์ด ์ž๋™์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

Swagger2๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Docket๊ฐ์ฒด๋ฅผ Bean์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Docker๊ฐ์ฒด์—๋Š” ์–ด๋–ค ๊ฒฝ๋กœ์˜ Web API๋“ค์„ ์ž๋™์œผ๋กœ ๋ฌธ์„œํ™” ํ•  ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•œ ์„ค์ •๊ณผ ๋ฌธ์„œ ์„ค๋ช…์— ๋Œ€ํ•œ ๋‚ด์šฉ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ๊นŒ์ง€ ์„ค์ •ํ•˜์˜€๋‹ค๋ฉด, Web API๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์Šค์›จ๊ฑฐ๋ฅผ ์ด์šฉํ•  ์ค€๋น„๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


3) Swagger-ui ํ™•์ธ ๋ฐ ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธํ•˜๊ธฐ

swagger-ui

 

'Spring > Boost Course Web' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

5.1 ์ƒํƒœ์œ ์ง€๊ธฐ์ˆ  - Cookie & Session  (0) 2020.11.19
4.4 Controller  (0) 2020.11.19
4.3 WEB API  (0) 2020.11.19
4.2 Layered Architecture  (0) 2020.11.19
4.1 Spring MVC  (0) 2020.11.19
3.3 Spring JDBC  (0) 2020.11.19