RestApi ๋งŒ๋“ค๊ธฐ - spring-rest-docs (5)

๋ฐ˜์‘ํ˜•

์ž ๋“œ๋””์–ด rest-docs๋ฅผ ์ ์šฉํ• ๋•Œ๊ฐ€ ์™”๋‹ค.

 

Spring REST Docs

Document RESTful services by combining hand-written documentation with auto-generated snippets produced with Spring MVC Test.

docs.spring.io

์›๋ž˜

private MockMvc mockMvc;

@Autowired
private WebApplicationContext context;

@Before
public void setUp() {
	this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
			.apply(documentationConfiguration(this.restDocumentation)) 
			.build();
}

์ด๋Ÿฌํ•œ ์ž‘์—…์„ ์ง„ํ–‰ํ•ด์•ผ ๋˜์ง€๋งŒ,
์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ๋Š”

@AutoConfigureRestDocs
class DeliveryTest {

์ด ์–ด๋…ธํ…Œ์ด์…˜์ด๋ฉด ์œ„ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค๊ณ  ํ•œ๋‹ค.

์ด์ œ ๋งŒ๋“ค๋ ค๊ณ  ํ•˜๋Š” ํ…Œ์ŠคํŠธ์ฝ”์Šค์—

.andDo(document("create-events"))

์ด๋Ÿฌํ•œ ๋‚ด์šฉ์„ ๋„ฃ์–ด์ค€๋‹ค.
create-events๋Š” ์‹๋ณ„์ž๋กœ ์ €๊ธฐ์—๋Š” ์•„๋ฌด๊ฑฐ๋‚˜ ๋„ฃ์–ด๋„ ์ƒ๊ด€์—†๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์‹คํ–‰ํ•˜๊ฒŒ ๋˜๋ฉด,

์ด๋Ÿฌํ•œ ๋‚ด์šฉ์ด ๋“ค์–ด์žˆ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‚ด์šฉ์„ ๋ณด์ž.

์—ฌ๋Ÿฌ๊ธ€ ์ค‘ curl-request ์ฆ‰, curl ์š”์ฒญ ์ •๋ณด๋ฅผ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.
itemPrice๊ฐ€ null์ธ๊ฒŒ ์ข€ ๊ทธ๋ ‡์ง€๋งŒ.. ์•„๋ฌดํŠผ
๊ทผ๋ฐ ๋‚˜๋Š” ์ตœ๋Œ€ํ•œ ์งง๊ฒŒ ํ•ด์„œ ๊ทธ๋ฆฌ ๋ณด๊ธฐ ์–ด๋ ต์ง€๋Š” ์•Š์ง€๋งŒ json์ด ๊ธธ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž.

๊ทธ๋Ÿฌ๋ฉด ์•Œ์•„๋ณด๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค.
๋ฐฉ๋ฒ•์„ ์ฐพ์•„์•ผ ๋œ๋‹ค.
๋‹คํ–‰ํžˆ
spring-docs์—๋Š” json์ •๋ณด๋ฅผ ํฌ๋งทํŒ…ํ•˜๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ”„๋กœ์‹œ์ €๋“ค์ด ์กด์žฌํ•œ๋‹ค.

์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” RestDocsMockMvcConfigurationCustomizer์„ ๋“ฑ๋กํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค.
์–ด์ฐจํ”ผ ์ด๊ฑด ํ…Œ์ŠคํŠธ ์ฝ”์Šค์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์˜ˆ์ •์ด๋ฏ€๋กœ
ํ…Œ์ŠคํŠธ์ชฝ์— ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค๊ตฌ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.
๊ทธ๋ฆฌ๊ตฌ,

@TestConfiguration
public class RestDocsConfiguration {

 ์ด์ œ ์ด๊ฑด ํ…Œ์ŠคํŠธ์šฉ Configuration๋ผ๋Š” ๋œป์ด๋œ๋‹ค.

์ด์ œ ๋งŒ๋“ค์–ด๋ณด์ž.
๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ตฌ

@Bean
public RestDocsMockMvcConfigurationCustomizer restDocsMockMvcConfigurationCustomizer() {
    
}
configurer.operationPreprocessors().withResponseDefaults().withRequestDefaults();

์„ค์ • -> ํ”„๋กœ์‹œ์ €์—ด๋žŒ?ใ…Ž -> ๊ธฐ๋ณธ ์‘๋‹ต ์„ธํŒ… -> ๊ธฐ๋ณธ ์š”์ฒญ ์„ธํŒ…
์ฐธ๊ณ ๋กœ ์•„๋ฌด๊ฒƒ๋„ ์—†์–ด๋„ ์ปดํŒŒ์ผ์—๋Ÿฌ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ด๊ฒƒ์„ ๋ดค์„๋•Œ, ํ”„๋กœ์‹œ์ €๋Š” ํ•˜๋‚˜๋งŒ ์ž…๋ ฅํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
์ด์ œ ๊ณต์‹ ๋ฌธ์„œ์—์„œ ํ•˜๋‚˜์”ฉ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋Š”์ง€ ์ง์ ‘ ๋ˆˆ์œผ๋กœ ํ™•์ธํ•ด๋ณด์ž.

๊ทธ ์ „์— ํ•ด์•ผ๋ ๊ฒƒ์ด์žˆ๋‹ค.
์‚ฌ์‹ค ์ด๊ฒƒ๋งŒ ํ•˜๋ฉด ๋˜์ง€ ์•Š๋Š”๋‹ค.

@Import(RestDocsConfiguration.class)

์ด๋ ‡๊ฒŒ ์ž„ํฌํŠธ๋ฅผ ์‹œ์ผœ์ค€๋‹ค์Œ...

configurer.operationPreprocessors().withResponseDefaults(prettyPrint()).withRequestDefaults(prettyPrint());

์‘๋‹ต,์š”์ฒญ ํ”„๋กœ์‹œ์ € => prettyprint์ผ๋•Œ

์œ„ ๋ฉ”์‹œ์ง€๊ฐ€ ํ™•์‹คํžˆ ์˜ˆ์˜๊ฒŒ ๋‚˜์˜จ๋‹ค.

์‘๋‹ต, ์š”์ฒญ ํ”„๋กœ์‹œ์ € => Masking Links

๋ญ๊ฐ€ ๋‹ฌ๋ผ์กŒ์ง€...

์‚ฌ์‹ค ์—ฌ๊ธฐ๋Š” ํฐ ์˜๋ฏธ๋Š” ์—†๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ฃผ์†Œ๊ฐ€ ์—†์œผ๋‹ˆ๊นŒ
์ด๊ฑด ๋ชจ๋“  ์ฃผ์†Œ๋ฅผ href์„ ๊ฐ•์ œํ•จ์ด ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

์ด๊ฒŒ...

์‹œํฌ๋ฆฟ ๋ชจ๋“œ์ธ๊ฐ€...

์ด๊ฑด ๋ชจ๋ฅด๊ฒ ๋‹ค.

์‘๋‹ต, ์š”์ฒญ ํ”„๋กœ์‹œ์ € => Removing Headers

๋ˆ„๊ฐ€ ๋ด๋„ ํ—ค๋”๋ฅผ ์ง€์›Œ์ฃผ๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

origin

์•„ ํ—ค๋” ์ง€์›Œ์ค€๋ฐ๋งค...

์•Œ๊ณ ๋ณด๋‹ˆ  ์ง€์ •๋œ ํ—ค๋” ์ด๋ฆ„๊ณผ ๋™์ผํ•œ ๋ชจ๋“  ํ—ค๋”๊ฐ€ ์š”์ฒญ ๋˜๋Š” ์‘๋‹ต์—์„œ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.ใ…œใ…œ

๋‚˜์ค‘์— ๋‹ค์‹œ ํ•ด๋ด์•ผ์ง€...

์–ด? ๋‹ค๋ฅธ๊ฒƒ ๋„ ์žˆ๋„ค

removeMatchingHeaders

์ด๊ฑด๋ญ..

์ด๊ฑด ์ด๋Ÿฐ์‹์œผ๋กœ

configurer -> configurer.operationPreprocessors().withResponseDefaults(removeMatchingHeaders("[a-zA-Z]"))
        .withRequestDefaults(removeMatchingHeaders("[a-zA-Z]"));

์ •๊ทœ์‹์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.
์ด๊ฒƒ๋„ ๋‹น์žฅ์€ ์“ฐ๊ธฐ๋Š” ํž˜๋“ค๊ฒƒ ๊ฐ™๊ตฌ, ๋‚˜์ค‘์— ๊ณต๋ถ€ํ•˜๊ณ  ์‚ฌ์šฉํ•ด๋ด์•ผ ๊ฒ ๋‹ค.

์ด๋ฐ–์—๋„ 
Replacing Patterns ์ด๋ž‘ Modifying Request Parameters๋„ ์กด์žฌํ•œ๋‹ค.

์†”์งํžˆ ๋งจ ์ฒ˜์Œ ๋นผ๊ณ ๋Š” ๊ฐํฅ์ด ์—†๋‹ค.

์•„๋ฌดํŠผ

์ด๊ฒŒ ๊ธฐ๋ณธ์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์Šค๋ƒ…ํ•์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

๋Œ“๊ธ€

Designed by JB FACTORY