김민석 (myminseok@gmail.com)
Pivotal 

 1
Consumer Driven Contract 기법을
활용하여 마이크로서비스들의
API를 안전하게 진화시키는 방법
Spring	Camp	2018	 2
소개
•  김민석 (myminseok@gmail.com)
•  Platform Architect @ Pivotal
•  Big-Data Monitoring System Developer
•  Software Architect
•  Software Quality Engineer
•  Developer
https://www.facebook.com/groups/CloudfoundryKorea
Spring	Camp	2018	 3
Message from Marcin
Spring Cloud developer at Pivotal working mostly on
●  Spring Cloud Sleuth
●  Spring Cloud Contract
●  Spring Cloud Pipelines
Connect with me
●  Twitter: @mgrzejszczak
●  Blog: http://toomuchcoding.com
Spring	Camp	2018	 4
목차
1.  Agile, MSA, 새로운 문제들
2.  안전한 API 진화를 위한 패턴
3.  Spring Cloud Contract
4.  Demo
5.  Q&A
Agile, MSA 그리고 새로운 문제들
Spring	Camp	2018	 6
Netflix
Spring	Camp	2018	 7
마이크로서비스에서의 API란?
Spring	Camp	2018	 8
API 개선 라이프사이클
API	consumer	API	
Producer	
Consumer의 Feedback 수렴
API (Contact) 설계 및 공유
Spring	Camp	2018	 9
개발/테스트/서비스반영
API	consumer	API	
Producer	
API 개선 라이프사이클
Spring	Camp	2018	 10
우리의 IT환경은 점점
•  마이크로 서비스팀이 점점 작아지고 많아짐
•  API contract 개선이 더 잦아짐(Agile)
•  다른 시간대(Timezone)의 팀간의 협업이 요구됨
Spring	Camp	2018	 11
풀기 어려운 문제
1.  Consumer에 영향없이 Producer서비스에 새로운 것을
추가하거나 삭제할 수 있을까?
2.  Consumer가 Producer서비스를 어떻게 사용하고 있는지를
Producer서비스 개발자가 알 수 있을까?
3.  Producer서비스의 릴리즈 사이클을 짧게 할 수 있을까?
Spring	Camp	2018	 12
웹서비스 진화를 위한 패턴
•  Single Message Argument
•  Dataset Amendment
•  Tolerant Reader
•  Schema Versioning
•  Consumer-Driven Contracts
http://www.servicedesignpatterns.com/WebServiceEvolution
Consumer Driven Contracts
Spring	Camp	2018	 14Source: http://martinfowler.com/articles/consumerDrivenContracts.html
CDC는 Consumer의 요구사항 중심으로 Producer
서비스를 진화하기 위한 협업 패턴
Spring	Camp	2018	 15
Consumer Driven Contracts의 장점
•  Producer는 불필요한 서비스 개발을 줄일 수 있음
(make the right thing)
•  Producer는 개선에 대한 통찰을 얻을 수 있음
•  Agile실현을 위한 자동화을 가속화함
Spring	Camp	2018	 16
Consumer Driven Contracts가 성공하려면
Contract(API)	스펙 정의	
API	문서화	
REST	API	테스트 	
API스펙과 일치하는 테스트코드 유지	
API동작을 모니터링/제어	
API	Gateway	
Consumer	Driven	Contract의		
핵심은 커뮤니케이션
Spring	Camp	2018	 17
API 관리도구
Contract(API)	스펙 정의	
REST	API	테스트	
API	문서화	
	API	운영 도구	
API스펙과 일치하는 코드유지	 ?	 ?	 ?	 ?
내가 작성한 코드가
API 스펙과 일관성이 있는가?
Spring	Camp	2018	 19
End-to-end 테스트전략은 확실하나 비효율적
•  모든 마이크로서비스를
배포하여 환경을 구성
•  실제 환경과 유사
•  테스트 자원 소모
•  긴 환경 준비시간
•  느린 feedback(실행시간)
•  debug가 어렵다
Spring	Camp	2018	 20
Mock(Stub)을 활용하는 테스트 전략이 일반적
•  빠른 feedback
•  적은 테스트 자원필요
•  테스트가 통과하더라도 실제
서비스에서 실패할 수 있음
Spring	Camp	2018	 21
Mock(Stub)을 활용한 테스트코드의 작성
API	consumer	
API	
Producer	
Producer	
TestCase	
Producer	
TestCase	
API (Contact) 스펙 문서
Spring	Camp	2018	 22
테스트가 성공해도 실제 서비스는 실패할 수 있다.
API	consumer	
API	
Producer	
Producer	
TestCase	
Producer	
TestCase	
API (Contact) 스펙 문서
Spring	Camp	2018	 23
Consumer의 코드는
•  Contract(API)와 정합성을
보장하는 메커니즘이 없음
•  JSON 데이터파일의
최신상태 관리의 어려움
Spring	Camp	2018	 24
Contract(API)	스펙 정의	
API	문서화	
REST	API	테스트 	
API스펙과 일치하는 테스트코드 유지	
API동작을 모니터링/제어	
API	Gateway	
Consumer	Driven	Contract의		
핵심은 커뮤니케이션 	
Consumer Driven Contracts가 성공하려면
contract와 정합성을 보장하는
메커니즘이 필요
Spring Cloud Contract
Spring	Camp	2018	 26
Spring Cloud Contract 목표
1. Contract를 공유하는 메커니즘을 제공 (Consumer Driven Contract)
- 정의하고 읽기 쉬운 형태로 Contract 형식(DSL)
- REST, Messaging 지원
2. Contract를 적용할 때 자동화를 통해 확신을 주자
-  Producer는 Contract를 만족하는 Producer Stubs를 자동 생,
Producer테스트에 활용
-  Consumer의 테스트코드는 Producer가 테스트에 활용한 그 stub을 다
운로드, stub은 정합성이 보장
-  서비스로 넘어가기전에 Fail-Fast
Spring	Camp	2018	 27
Spring Cloud Contract Maven Plugin
Spring cloud Contract verifier
<dependency>
<groupId>org.Springframework.cloud</groupId>
<artifactId>Spring-cloud-starter-contract-verifier</artifactId>
<scope>test</scope>
</dependency>	
Spring cloud Contract stub runner
<dependency>
<groupId>org.Springframework.cloud</groupId>
<artifactId>Spring-cloud-contract-stub-runner</artifactId>
<scope>test</scope>
</dependency>
Spring	Camp	2018	 28
Contract로 부터 자동으로 stub.jar 생성
$ mvn clean install OutputsReads
Producer테스트용
Junit 테스트케이스
Contract.make {
request{
url "/check"
method POST()
body(
age: value(regex('[2-9][0-9]')))
headers{
contentType(applicationJson()) } }
response{
status 200
body("""
{"status": "OK" }
"””)
}
Producer-stub.jar
•  Contract정의파일
•  Wiremock stub 정의(json)
Spring	Camp	2018	 29
Consumer는 자동으로 stub을 내려받아
Mock서버를 생성
Producer-stub.jar
Spring-cloud-contract-stub-runner
자동 다운로드
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureWireMock
@AutoConfigureStubRunner(workOffline=true,
ids="com.example:beer-server:+:stubs:8081")
public class BeerClientApplicationTests {
@Test
public void old_enough_stubs() {
…
}
Spring	Camp	2018	 30
Spring Cloud Contract workflow
Contract 정의/테스트
(stub runner offline
mode)
Contract 구현/테스트
Contract stubs.jar 자동생성
(sub runner offline mode)
Contract 정의
Pull Request
Consumer Project Producer Project
stub.jar 업로드
Stub.jar
자동 다운로드
Contract stubs.jar를
이용한 consumer테스트
(stub runner online
mode)
Spring	Camp	2018	 31
활용 시나리오 데모
1.  기본동작
2.  Stateful 시나리오 지원
3.  Stub을 Mock Server로 실행하기
4.  Spring cloud 지원
5.  Contract 파일 관리 방안
6.  다양한 언어 지원
7.  PACT 파일 지원
8.  Spring cloud pipeline에 활용
Demo#1 기본동작
32
Spring	Camp	2018	 33
기본 데모 구성
POST /check {age=22}
Local Maven Repo
Contract.make {
request {
…
}
response {
…
}
}
Stub등록
Beer-client project Beer-server project
consumer ProducerBeer-server-stub.jar
{ “status”: “OK”}
https://github.com/myminseok/Spring-cloud-contract-beer-sample
Spring	Camp	2018	 34
Groovy, YML형식의 DSL 제공
Contract의 정의
request:
method: POST
url: /check
body:
“age”: 22
headers:
Content-Type: application/json
matchers:
body:
- path: $.[’age']
type: by_regex
value: ”[2-9][0-9]"
response:
status: 200
body:
status: ”OK”
Contract.make {
request{
url "/check"
method POST()
body(
age: value(regex('[2-9][0-9]')))
headers{
contentType(applicationJson()) } }
response{
status 200
body("""
{"status": "OK" }
"””)
}
Demo#2 Stub을 Mock Server로 실행하기
35
Spring	Camp	2018	 36
Stub을 Mock Server로 실행하기
Stub runner boot
ConsumerStub-runner.jar
80818080
REMOTE, LOCAL, CLASSPATH
$ java -jar stub-runner.jar --stubrunner.ids=com.example:beer-server:+:stubs:8081
--stubrunner.workOffline=true
http://localhost:8081/__admin
https://github.com/myminseok/Spring-cloud-contract-beer-sample
Demo#3 Stateful 시나리오 지원
37
Spring	Camp	2018	 38
State-machine처럼 이전상태에 기반한 상태전이
테스트가 가능
Consumer
SOBER
Producer stub
TIPSY
Drunk
curl X POST localhost/beer
=> {"currentStatus":"TIPSY","previousStatus":"SOBER”}
curl X POST localhost/beer
=> {"currentStatus":”DRUNK","previousStatus":"TIPSY”}
WASTED curl X POST localhost/beer
=> {"currentStatus":”WASTED","previousStatus":”DRUNK”}
https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/
producer
Spring	Camp	2018	 39
시나리오 순서대로 Contract를 정의
request {
method 'POST'
url '/beer'
body( name: "marcin”)
}
response {
status 200
body(
previousStatus: "SOBER",
currentStatus: "TIPSY"
)
request {
method 'POST'
url '/beer'
body( name: "marcin”)
}
response {
status 200
body(
previousStatus: "TIPSY",
currentStatus: "DRUNK"
)
Spring	Camp	2018	 40
자동생성된 stub, Spring cloud contract wiremock을 통해 작동
Wiremock의 stateful기능 기반의 JSON 자동생성
{
"request" : {
"url" : "/beer",
},
"bodyPatterns" : [ {
"matchesJsonPath" : "$[?(@.['name'] == 'marcin')]"
} ]
},
"response" : {
"status" : 200,
"body" : "{"currentStatus":"TIPSY",
"previousStatus":"SOBER"}",
"uuid" : "2690ba56-b024-4de5-9492-33c37c2d9208",
"scenarioName" : "Scenario_intoxication",
"requiredScenarioState" : "Started",
"newScenarioState" : "Step1"
}
Demo#4 Spring cloud 지원
41
Spring	Camp	2018	 42
Spring cloud를 연동하는 프로젝트 지원
Spring	Camp	2018	 43
Spring cloud를 연동하는 테스트케이스 지원
Beer-client-controller.java
ResponseEntity<Response>	response	=	
this.restTemplate.exchange(	
						RequestEntity	
												.post(URI.create("http://beer-api-from-eureka/check"))	
												.body(person),	
						Response.class);
테스트 코드
@@AutoConfigureMockMvc	
public	class	BeerControllerTest	{	
Stub runner boot
beer-api-from-eureka	
https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/
consumer_with_discovery
Spring	Camp	2018	 44
Spring cloud를 연동하는 테스트케이스 지원
Beer-client-controller.java
stubrunner:	
		idsToServiceIds:	
				beer-api-stub:	beer-api-from-eureka
Test/
applicaton.yml
ResponseEntity<Response>	response	=	
this.restTemplate.exchange(	
						RequestEntity	
												.post(URI.create("http://beer-api-from-eureka/check"))	
												.body(person),	
						Response.class);
테스트 코드
@@AutoConfigureMockMvc	
@AutoConfigureStubRunner(workOffline	=	true,	ids	=	
"com.example:beer-api-stub")	
public	class	BeerControllerTest	{	
Stub runner boot
beer-api-from-eureka	
beer-api-stub
Spring	Camp	2018	 45
Spring cloud eureka에 stub자동등록 지원
Stub runner boot
Spring cloud
Stub runner boot
eureka에 stub들을
자동으로 등록
Stub runner boot
API호출
Consumer
https://github.com/Spring-cloud-samples/github-analytics-stub-runner-boot
Spring	Camp	2018	 46
import	org.Springframework.cloud.contract.stubrunner.server.EnableStubRunnerServer;	
import	org.Springframework.cloud.contract.stubrunner.Spring.AutoConfigureStubRunner;	
	
@SpringBootApplication	
@EnableStubRunnerServer	
@EnableEurekaClient	
public	class	StubrunnereurekaApplication	{	
	public	static	void	main(String[]	args)	{	
	 	SpringApplication.run(StubrunnereurekaApplication.class,	args);	
	}	
	@AutoConfigureStubRunner	
	static	class	Config	{}	
}	
커스텀 Stubrunner app
Demo#5 Contract파일 관리방안
47
Spring	Camp	2018	 48
방안1: Contract파일을 Producer 프로젝트에 포함
•  Producer가 주도적으로 관리
•  (보안)정책상 Consumer가 Producer
프로젝트에 접근하기 어려울수 있음
Spring	Camp	2018	 49
방안2: Consumer와 Producer가 접근할 수 있는
공통의 프로젝트 구성
Contract Project
-  Contract 파일 관리
-  maven-assembly-plugin 빌드
Producer Project
-  Pom.xml에 contractDependency 설정
<plugin>
<artifactId>Spring-cloud-contract-maven-plugin
<configuration>
<contractDependency>
<groupId>com.example</groupId>
<artifactId>beer-contracts</artifactId>
</contractDependency>
https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/
beer_contracts
Demo#6 다양한 언어 지원
50
Spring	Camp	2018	 51
maven
JAVA
Docker
다양한 언어의 서비스에 대해 stub생성지원
Polygot 언어지원
$ docker pull Springcloud/Spring-cloud-contract
/contracts Spring Cloud Contractread
https://github.com/Spring-cloud-samples/Spring-cloud-contract-nodejs
-stub.jar
nodeJS app
Demo#7 PACT 파일 지원
52
Spring	Camp	2018	 53
Groovy DSL
PACT 지원
Contract.make {
request{
url "/check"
method POST()
body(
age: value(regex('[2-9][0-9]')))
headers{
contentType(applicationJson()) } }
response{
status 200
body("""
{"status": "OK" }
"””)
}
PACT DSL
{ “interactions”: [
“request”: {
path: “/check”,
method: “POST”,
"body": {
"age": "22"
},
“matchingRules”: {
header{
…
} body: {
"$.age": {
“matchers”: [
{ "match": "regex",
"regex": "[2-9][0-9] }]}
}
},
“response”: {
Spring	Camp	2018	 54
PACT파일을 활용하여 stub과 테스트케이스 생성가능
Spring cloud contract Pact plugin추가
<plugin>
<groupId>org.Springframework.cloud</groupId>
<artifactId>Spring-cloud-contract-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.Springframework.cloud</groupId>
<artifactId>Spring-cloud-contract-spec-pact</artifactId>
<version>1.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-model</artifactId>
<version>2.4.18</version>
Demo#8 Spring Cloud Pipeline
55
Spring	Camp	2018	 56
Spring cloud pipeline에 활용
https://github.com/Spring-cloud/Spring-cloud-pipelines
Spring	Camp	2018	 57
Spring cloud pipeline에 활용
Spring	Camp	2018	 58
Spring cloud pipeline에 활용
•  의존성이 있는 service를 실제로 구성할 필요 없음(stub runner활용)
•  테스트 속도 증가
•  PaaS플랫폼과 연계하여 테스트 환경구성 자동화
Demo#9 Messaging 지원
59
Spring	Camp	2018	 60
Messaging 지원
Contract.make {
label 'accepted_verification'
input {
triggeredBy('clientIsOldEnough()')
}
outputMessage {
sentTo 'verifications'
body(
eligible: true
)
headers {
header("contentType",
applicationJsonUtf8())
}
}
Producer프로젝트:
- Spring-cloud-stream-test-support
Consumer프로젝트:
Spring-cloud-stream-test-support
Spring-cloud-starter-stream-rabbit
Spring-cloud-starter-contract-stub-runner
•  Apache Camel
•  Spring Integration
•  Spring Cloud Stream
•  Spring AMQP
필요한 dependency
Spring	Camp	2018	 61
Summary
Consumer Driven Contract패턴을 지원하는 Spring Cloud
Contract를 활용하여 마이크로서비스 API를 안전하게 개선
•  Contract 스펙정의에 필요한 도구 제공
•  Contract를 만족하는 Producer Stubs를 자동 생성
•  Consumer는 Producer 서비스 테스트에 활용한 그 stub을 사용(일관성)
•  Stub 패턴을 활용하여 의존성이 있는 service를 배포할 필요없고 빠른
feedback제공(failfast)
•  테스트 파이프라인에 쉽게 적용, 테스트 자동화 가능
•  Dependency가 복잡한 마이크로 서비스 테스트에 효과적
•  contract를 개선할 때 Producer /Consumer조율 시간과 비용을 줄일 수 있음
Spring	Camp	2018	 62
Learn More. Stay Connected.
▪  데모샘플
https://github.com/myminseok/Spring-cloud-contract-beer-sample
▪  Read the docs
http://cloud.Spring.io/Spring-cloud-contract/
▪  Talk to us on Gitter
https://gitter.im/Spring-cloud/Spring-cloud-contract
Twitter: twitter.com/Springcentral
YouTube: Spring.io/video
LinkedIn: Spring.io/linkedin
Google Plus: Spring.io/gplus
Q&A
63

consumer_driven_contract with spring cloud contract at spring camp 2018

  • 1.
    김민석 (myminseok@gmail.com) Pivotal 1 Consumer Driven Contract 기법을 활용하여 마이크로서비스들의 API를 안전하게 진화시키는 방법
  • 2.
    Spring Camp 2018 2 소개 •  김민석(myminseok@gmail.com) •  Platform Architect @ Pivotal •  Big-Data Monitoring System Developer •  Software Architect •  Software Quality Engineer •  Developer https://www.facebook.com/groups/CloudfoundryKorea
  • 3.
    Spring Camp 2018 3 Message fromMarcin Spring Cloud developer at Pivotal working mostly on ●  Spring Cloud Sleuth ●  Spring Cloud Contract ●  Spring Cloud Pipelines Connect with me ●  Twitter: @mgrzejszczak ●  Blog: http://toomuchcoding.com
  • 4.
    Spring Camp 2018 4 목차 1.  Agile,MSA, 새로운 문제들 2.  안전한 API 진화를 위한 패턴 3.  Spring Cloud Contract 4.  Demo 5.  Q&A
  • 5.
    Agile, MSA 그리고새로운 문제들
  • 6.
  • 7.
  • 8.
    Spring Camp 2018 8 API 개선라이프사이클 API consumer API Producer Consumer의 Feedback 수렴 API (Contact) 설계 및 공유
  • 9.
  • 10.
    Spring Camp 2018 10 우리의 IT환경은점점 •  마이크로 서비스팀이 점점 작아지고 많아짐 •  API contract 개선이 더 잦아짐(Agile) •  다른 시간대(Timezone)의 팀간의 협업이 요구됨
  • 11.
    Spring Camp 2018 11 풀기 어려운문제 1.  Consumer에 영향없이 Producer서비스에 새로운 것을 추가하거나 삭제할 수 있을까? 2.  Consumer가 Producer서비스를 어떻게 사용하고 있는지를 Producer서비스 개발자가 알 수 있을까? 3.  Producer서비스의 릴리즈 사이클을 짧게 할 수 있을까?
  • 12.
    Spring Camp 2018 12 웹서비스 진화를위한 패턴 •  Single Message Argument •  Dataset Amendment •  Tolerant Reader •  Schema Versioning •  Consumer-Driven Contracts http://www.servicedesignpatterns.com/WebServiceEvolution
  • 13.
  • 14.
    Spring Camp 2018 14Source: http://martinfowler.com/articles/consumerDrivenContracts.html CDC는Consumer의 요구사항 중심으로 Producer 서비스를 진화하기 위한 협업 패턴
  • 15.
    Spring Camp 2018 15 Consumer DrivenContracts의 장점 •  Producer는 불필요한 서비스 개발을 줄일 수 있음 (make the right thing) •  Producer는 개선에 대한 통찰을 얻을 수 있음 •  Agile실현을 위한 자동화을 가속화함
  • 16.
    Spring Camp 2018 16 Consumer DrivenContracts가 성공하려면 Contract(API) 스펙 정의 API 문서화 REST API 테스트 API스펙과 일치하는 테스트코드 유지 API동작을 모니터링/제어 API Gateway Consumer Driven Contract의 핵심은 커뮤니케이션
  • 17.
    Spring Camp 2018 17 API 관리도구 Contract(API) 스펙정의 REST API 테스트 API 문서화 API 운영 도구 API스펙과 일치하는 코드유지 ? ? ? ?
  • 18.
    내가 작성한 코드가 API스펙과 일관성이 있는가?
  • 19.
    Spring Camp 2018 19 End-to-end 테스트전략은확실하나 비효율적 •  모든 마이크로서비스를 배포하여 환경을 구성 •  실제 환경과 유사 •  테스트 자원 소모 •  긴 환경 준비시간 •  느린 feedback(실행시간) •  debug가 어렵다
  • 20.
    Spring Camp 2018 20 Mock(Stub)을 활용하는테스트 전략이 일반적 •  빠른 feedback •  적은 테스트 자원필요 •  테스트가 통과하더라도 실제 서비스에서 실패할 수 있음
  • 21.
    Spring Camp 2018 21 Mock(Stub)을 활용한테스트코드의 작성 API consumer API Producer Producer TestCase Producer TestCase API (Contact) 스펙 문서
  • 22.
    Spring Camp 2018 22 테스트가 성공해도실제 서비스는 실패할 수 있다. API consumer API Producer Producer TestCase Producer TestCase API (Contact) 스펙 문서
  • 23.
    Spring Camp 2018 23 Consumer의 코드는 • Contract(API)와 정합성을 보장하는 메커니즘이 없음 •  JSON 데이터파일의 최신상태 관리의 어려움
  • 24.
    Spring Camp 2018 24 Contract(API) 스펙 정의 API 문서화 REST API 테스트 API스펙과 일치하는 테스트코드 유지 API동작을 모니터링/제어 API Gateway Consumer Driven Contract의 핵심은 커뮤니케이션 Consumer Driven Contracts가 성공하려면 contract와 정합성을 보장하는 메커니즘이 필요
  • 25.
  • 26.
    Spring Camp 2018 26 Spring CloudContract 목표 1. Contract를 공유하는 메커니즘을 제공 (Consumer Driven Contract) - 정의하고 읽기 쉬운 형태로 Contract 형식(DSL) - REST, Messaging 지원 2. Contract를 적용할 때 자동화를 통해 확신을 주자 -  Producer는 Contract를 만족하는 Producer Stubs를 자동 생, Producer테스트에 활용 -  Consumer의 테스트코드는 Producer가 테스트에 활용한 그 stub을 다 운로드, stub은 정합성이 보장 -  서비스로 넘어가기전에 Fail-Fast
  • 27.
    Spring Camp 2018 27 Spring CloudContract Maven Plugin Spring cloud Contract verifier <dependency> <groupId>org.Springframework.cloud</groupId> <artifactId>Spring-cloud-starter-contract-verifier</artifactId> <scope>test</scope> </dependency> Spring cloud Contract stub runner <dependency> <groupId>org.Springframework.cloud</groupId> <artifactId>Spring-cloud-contract-stub-runner</artifactId> <scope>test</scope> </dependency>
  • 28.
    Spring Camp 2018 28 Contract로 부터자동으로 stub.jar 생성 $ mvn clean install OutputsReads Producer테스트용 Junit 테스트케이스 Contract.make { request{ url "/check" method POST() body( age: value(regex('[2-9][0-9]'))) headers{ contentType(applicationJson()) } } response{ status 200 body(""" {"status": "OK" } "””) } Producer-stub.jar •  Contract정의파일 •  Wiremock stub 정의(json)
  • 29.
    Spring Camp 2018 29 Consumer는 자동으로stub을 내려받아 Mock서버를 생성 Producer-stub.jar Spring-cloud-contract-stub-runner 자동 다운로드 @RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureWireMock @AutoConfigureStubRunner(workOffline=true, ids="com.example:beer-server:+:stubs:8081") public class BeerClientApplicationTests { @Test public void old_enough_stubs() { … }
  • 30.
    Spring Camp 2018 30 Spring CloudContract workflow Contract 정의/테스트 (stub runner offline mode) Contract 구현/테스트 Contract stubs.jar 자동생성 (sub runner offline mode) Contract 정의 Pull Request Consumer Project Producer Project stub.jar 업로드 Stub.jar 자동 다운로드 Contract stubs.jar를 이용한 consumer테스트 (stub runner online mode)
  • 31.
    Spring Camp 2018 31 활용 시나리오데모 1.  기본동작 2.  Stateful 시나리오 지원 3.  Stub을 Mock Server로 실행하기 4.  Spring cloud 지원 5.  Contract 파일 관리 방안 6.  다양한 언어 지원 7.  PACT 파일 지원 8.  Spring cloud pipeline에 활용
  • 32.
  • 33.
    Spring Camp 2018 33 기본 데모구성 POST /check {age=22} Local Maven Repo Contract.make { request { … } response { … } } Stub등록 Beer-client project Beer-server project consumer ProducerBeer-server-stub.jar { “status”: “OK”} https://github.com/myminseok/Spring-cloud-contract-beer-sample
  • 34.
    Spring Camp 2018 34 Groovy, YML형식의DSL 제공 Contract의 정의 request: method: POST url: /check body: “age”: 22 headers: Content-Type: application/json matchers: body: - path: $.[’age'] type: by_regex value: ”[2-9][0-9]" response: status: 200 body: status: ”OK” Contract.make { request{ url "/check" method POST() body( age: value(regex('[2-9][0-9]'))) headers{ contentType(applicationJson()) } } response{ status 200 body(""" {"status": "OK" } "””) }
  • 35.
    Demo#2 Stub을 MockServer로 실행하기 35
  • 36.
    Spring Camp 2018 36 Stub을 MockServer로 실행하기 Stub runner boot ConsumerStub-runner.jar 80818080 REMOTE, LOCAL, CLASSPATH $ java -jar stub-runner.jar --stubrunner.ids=com.example:beer-server:+:stubs:8081 --stubrunner.workOffline=true http://localhost:8081/__admin https://github.com/myminseok/Spring-cloud-contract-beer-sample
  • 37.
  • 38.
    Spring Camp 2018 38 State-machine처럼 이전상태에기반한 상태전이 테스트가 가능 Consumer SOBER Producer stub TIPSY Drunk curl X POST localhost/beer => {"currentStatus":"TIPSY","previousStatus":"SOBER”} curl X POST localhost/beer => {"currentStatus":”DRUNK","previousStatus":"TIPSY”} WASTED curl X POST localhost/beer => {"currentStatus":”WASTED","previousStatus":”DRUNK”} https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/ producer
  • 39.
    Spring Camp 2018 39 시나리오 순서대로Contract를 정의 request { method 'POST' url '/beer' body( name: "marcin”) } response { status 200 body( previousStatus: "SOBER", currentStatus: "TIPSY" ) request { method 'POST' url '/beer' body( name: "marcin”) } response { status 200 body( previousStatus: "TIPSY", currentStatus: "DRUNK" )
  • 40.
    Spring Camp 2018 40 자동생성된 stub,Spring cloud contract wiremock을 통해 작동 Wiremock의 stateful기능 기반의 JSON 자동생성 { "request" : { "url" : "/beer", }, "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.['name'] == 'marcin')]" } ] }, "response" : { "status" : 200, "body" : "{"currentStatus":"TIPSY", "previousStatus":"SOBER"}", "uuid" : "2690ba56-b024-4de5-9492-33c37c2d9208", "scenarioName" : "Scenario_intoxication", "requiredScenarioState" : "Started", "newScenarioState" : "Step1" }
  • 41.
  • 42.
    Spring Camp 2018 42 Spring cloud를연동하는 프로젝트 지원
  • 43.
    Spring Camp 2018 43 Spring cloud를연동하는 테스트케이스 지원 Beer-client-controller.java ResponseEntity<Response> response = this.restTemplate.exchange( RequestEntity .post(URI.create("http://beer-api-from-eureka/check")) .body(person), Response.class); 테스트 코드 @@AutoConfigureMockMvc public class BeerControllerTest { Stub runner boot beer-api-from-eureka https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/ consumer_with_discovery
  • 44.
    Spring Camp 2018 44 Spring cloud를연동하는 테스트케이스 지원 Beer-client-controller.java stubrunner: idsToServiceIds: beer-api-stub: beer-api-from-eureka Test/ applicaton.yml ResponseEntity<Response> response = this.restTemplate.exchange( RequestEntity .post(URI.create("http://beer-api-from-eureka/check")) .body(person), Response.class); 테스트 코드 @@AutoConfigureMockMvc @AutoConfigureStubRunner(workOffline = true, ids = "com.example:beer-api-stub") public class BeerControllerTest { Stub runner boot beer-api-from-eureka beer-api-stub
  • 45.
    Spring Camp 2018 45 Spring cloudeureka에 stub자동등록 지원 Stub runner boot Spring cloud Stub runner boot eureka에 stub들을 자동으로 등록 Stub runner boot API호출 Consumer https://github.com/Spring-cloud-samples/github-analytics-stub-runner-boot
  • 46.
  • 47.
  • 48.
    Spring Camp 2018 48 방안1: Contract파일을Producer 프로젝트에 포함 •  Producer가 주도적으로 관리 •  (보안)정책상 Consumer가 Producer 프로젝트에 접근하기 어려울수 있음
  • 49.
    Spring Camp 2018 49 방안2: Consumer와Producer가 접근할 수 있는 공통의 프로젝트 구성 Contract Project -  Contract 파일 관리 -  maven-assembly-plugin 빌드 Producer Project -  Pom.xml에 contractDependency 설정 <plugin> <artifactId>Spring-cloud-contract-maven-plugin <configuration> <contractDependency> <groupId>com.example</groupId> <artifactId>beer-contracts</artifactId> </contractDependency> https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/ beer_contracts
  • 50.
  • 51.
    Spring Camp 2018 51 maven JAVA Docker 다양한 언어의서비스에 대해 stub생성지원 Polygot 언어지원 $ docker pull Springcloud/Spring-cloud-contract /contracts Spring Cloud Contractread https://github.com/Spring-cloud-samples/Spring-cloud-contract-nodejs -stub.jar nodeJS app
  • 52.
  • 53.
    Spring Camp 2018 53 Groovy DSL PACT지원 Contract.make { request{ url "/check" method POST() body( age: value(regex('[2-9][0-9]'))) headers{ contentType(applicationJson()) } } response{ status 200 body(""" {"status": "OK" } "””) } PACT DSL { “interactions”: [ “request”: { path: “/check”, method: “POST”, "body": { "age": "22" }, “matchingRules”: { header{ … } body: { "$.age": { “matchers”: [ { "match": "regex", "regex": "[2-9][0-9] }]} } }, “response”: {
  • 54.
    Spring Camp 2018 54 PACT파일을 활용하여stub과 테스트케이스 생성가능 Spring cloud contract Pact plugin추가 <plugin> <groupId>org.Springframework.cloud</groupId> <artifactId>Spring-cloud-contract-maven-plugin</artifactId> <dependencies> <dependency> <groupId>org.Springframework.cloud</groupId> <artifactId>Spring-cloud-contract-spec-pact</artifactId> <version>1.2.4.RELEASE</version> </dependency> <dependency> <groupId>au.com.dius</groupId> <artifactId>pact-jvm-model</artifactId> <version>2.4.18</version>
  • 55.
  • 56.
    Spring Camp 2018 56 Spring cloudpipeline에 활용 https://github.com/Spring-cloud/Spring-cloud-pipelines
  • 57.
  • 58.
    Spring Camp 2018 58 Spring cloudpipeline에 활용 •  의존성이 있는 service를 실제로 구성할 필요 없음(stub runner활용) •  테스트 속도 증가 •  PaaS플랫폼과 연계하여 테스트 환경구성 자동화
  • 59.
  • 60.
    Spring Camp 2018 60 Messaging 지원 Contract.make{ label 'accepted_verification' input { triggeredBy('clientIsOldEnough()') } outputMessage { sentTo 'verifications' body( eligible: true ) headers { header("contentType", applicationJsonUtf8()) } } Producer프로젝트: - Spring-cloud-stream-test-support Consumer프로젝트: Spring-cloud-stream-test-support Spring-cloud-starter-stream-rabbit Spring-cloud-starter-contract-stub-runner •  Apache Camel •  Spring Integration •  Spring Cloud Stream •  Spring AMQP 필요한 dependency
  • 61.
    Spring Camp 2018 61 Summary Consumer DrivenContract패턴을 지원하는 Spring Cloud Contract를 활용하여 마이크로서비스 API를 안전하게 개선 •  Contract 스펙정의에 필요한 도구 제공 •  Contract를 만족하는 Producer Stubs를 자동 생성 •  Consumer는 Producer 서비스 테스트에 활용한 그 stub을 사용(일관성) •  Stub 패턴을 활용하여 의존성이 있는 service를 배포할 필요없고 빠른 feedback제공(failfast) •  테스트 파이프라인에 쉽게 적용, 테스트 자동화 가능 •  Dependency가 복잡한 마이크로 서비스 테스트에 효과적 •  contract를 개선할 때 Producer /Consumer조율 시간과 비용을 줄일 수 있음
  • 62.
    Spring Camp 2018 62 Learn More.Stay Connected. ▪  데모샘플 https://github.com/myminseok/Spring-cloud-contract-beer-sample ▪  Read the docs http://cloud.Spring.io/Spring-cloud-contract/ ▪  Talk to us on Gitter https://gitter.im/Spring-cloud/Spring-cloud-contract Twitter: twitter.com/Springcentral YouTube: Spring.io/video LinkedIn: Spring.io/linkedin Google Plus: Spring.io/gplus
  • 63.