1- # Zuul의 추측 기반 병합( Speculative Merge)과 Cross-project 의존성( Dependencies) 정리본
1+ # Zuul의 Speculative Merge와 Cross-project Dependencies 정리본
22
33------------------------------------------------------------------------
44
1313학습하게 되었습니다.
1414
1515특히 실습을 진행하는 과정에서\
16- ** Zuul Hands-on Part 6: Cross-project Dependencies** (https://www.softwarefactory-project.io/zuul-hands-on-part-6-cross-project-dependencies.html ) 문서를 참고하여\
17- 추측 기반 병합(Speculative Merge)와 Cross-project 의존성(Dependencies) 기능을 직접 실험해 보았습니다.
16+ ** Zuul Hands-on Part 6: Cross-project Dependencies(교차 프로젝트 의존성) ** (https://www.softwarefactory-project.io/zuul-hands-on-part-6-cross-project-dependencies.html ) 문서를 참고하여\
17+ 추측 기반 병합과 교차 프로젝트 의존성 기능을 직접 실험해 보았습니다.
1818
1919------------------------------------------------------------------------
2020
2121## 1. 기존 CI/CD 도구(Jenkins)의 한계
2222
23- 전통적인 Jenkins 기반 CI는 주로 ** Post-merge 방식** 으로 동작합니다.
23+ 전통적인 Jenkins 기반 CI는 주로 ** Post-merge(병합 후 검증) 방식** 으로 동작합니다.
2424
2525즉, 코드가 ` main ` 브랜치에 병합된 이후 테스트가 수행됩니다.
2626
2727### 문제 상황
2828
29- - 개발자 A와 B가 각각 테스트를 통과
30- - 두 패치가 함께 존재할 때 충돌 발생
31- - main 브랜치가 ** Broken State** 상태가 됨
29+ - 개발자 A와 B가 각각 테스트를 통과함
30+ - 두 패치가 함께 존재할 때 충돌이 발생함
31+ - ` main ` 브랜치가 ** Broken State(빌드 오류 상태) ** 가 됨
3232
3333### 결과
3434
35- - 빌드 복구 전까지 전체 팀 생산성 저하
36- - 병합 이후 문제 발견 → 롤백 비용 증가
35+ - 빌드 복구 전까지 전체 팀 생산성 저하됨
36+ - 병합 이후 문제 발견 → 롤백 비용 증가함
3737
3838------------------------------------------------------------------------
3939
40- ## 2. Zuul의 Speculative Merge
40+ ## 2. Zuul의 추측 기반 병합
4141
4242Zuul은 ** Pre-merge Gating 모델** 을 사용합니다.
4343
44- > 변경 사항이 실제 병합되기 전에 모든 검증을 완료합니다 .
44+ > 변경 사항이 실제 병합되기 전에 모든 검증을 완료해야 합니다 .
4545
4646### 핵심 아이디어
4747
48- - 대기열(queue)에 있는 패치들이 이미 병합되었다고 가정
49- - 미래의 가상 상태를 시뮬레이션하여 테스트 수행
48+ - 대기열(queue)에 있는 패치들이 이미 병합되었다고 가정함
49+ - 미래의 가상 상태를 시뮬레이션하여 테스트 수행함
5050
5151### 동작 예시
5252
53- 1 . A 패치 테스트
54- 2 . B 패치 테스트 시 → A가 이미 병합되었다고 가정
55- 3 . C 패치 테스트 시 → A + B 병합 상태 가정
53+ 1 . A 패치 테스트 수행
54+ 2 . B 패치 테스트 시 → A가 이미 병합되었다고 가정함
55+ 3 . C 패치 테스트 시 → A + B 병합 상태 가정함
5656
5757내부적으로는 다음과 같은 가상 병합을 수행합니다:
5858
@@ -62,69 +62,86 @@ git merge A
6262git merge B
6363```
6464
65- 이 방식이 바로 ** Speculative Merge ** 입니다.
65+ 이 방식이 바로 ** 추측 기반 병합 ** 입니다.
6666
6767------------------------------------------------------------------------
6868
69- ## 3. Dependent vs Independent Pipeline
69+ ## 3. Dependent(의존형) vs Independent(독립형) Pipeline
7070
71- ### Independent Pipeline
71+ ### Independent Pipeline (독립형 파이프라인)
7272
73- - 각 변경 사항을 독립적인 workspace에서 테스트
74- - 다른 패치와 상호 영향 없음
73+ - 각 변경 사항을 독립적인 workspace에서 테스트함
74+ - 다른 패치와 상호 영향을 주고 받지 않음
75+ - ![ alt text] ( https://i.imgur.com/MMh8eBK.png )
7576
76- ### Dependent Pipeline
77+ ### Dependent Pipeline (의존형 파이프라인)
7778
78- - 변경 사항을 큐에 묶어 순차적으로 speculative merge 수행
79- - 대규모 협업 환경에 적합
79+ - 변경 사항을 큐에 묶어 순차적으로 추측 기반 병합함
80+ - 대규모 협업 환경에서 프로젝트 간 영향을 파악하기에 적합함
81+ - ![ alt text] ( https://i.imgur.com/gG5ty27.png )
8082
8183------------------------------------------------------------------------
8284
83- ## 4. Cross-project Dependencies
85+ ## 4. 교차 프로젝트 의존성
8486
8587여러 프로젝트가 서로 의존하는 경우, 단일 프로젝트 테스트만으로는
8688안정성을 보장할 수 없습니다.
8789
8890예를 들어, 라이브러리와 애플리케이션이 분리된 구조에서는 다음과 같은 문제가 발생할 수 있습니다.
89- * 라이브러리 변경은 테스트를 통과
90- * 애플리케이션도 기존 버전 기준으로는 저앙
91- * 그러나 두 변경이 함께 존재하면 오류 발생
91+ - 라이브러리 변경 사항은 테스트를 통과함
92+ - 애플리케이션도 기존 라이브러리 버전 기준으로는 정상 동작함
93+ - 그러나 두 변경 사항이 함께 존재하면 오류 발생
9294
9395Zuul은 다음 두 가지 방식으로 이를 해결합니다:
9496
95971 . ` required-projects ` : 정적(구조적) 의존성
96982 . ` Depends-On ` : 동적(변경 단위) 의존성
97- 구 기능은 목적과 동작 범위가 다릅니다.
99+
100+ 두 기능은 목적과 동작 범위가 다릅니다.
101+
98102------------------------------------------------------------------------
99103
100104## 5. required-projects 설정 예제
101- 이제 Cross-project 테스트를 가능하게 만드는 실제 설정을 살펴보겠습니다.
105+ 이제 Cross-project(교차 프로젝트) 테스트를 가능하게 만드는 실제 설정을 살펴보겠습니다.
102106
103107` .zuul.yaml `
104108
105109``` yaml
106110- job :
107111 name : tox-demorepo
108- parent : tox-py39
112+ description : tox test for demo-repo with dependencies
113+ parent : tox-py27
109114 required-projects :
110- - demo-lib
111115 - demo-repo
116+ - demo-lib
117+ vars :
118+ zuul_work_dir : " {{ zuul.projects['sftests.com/demo-repo'].src_dir }}"
119+
120+ - project :
121+ check :
122+ jobs :
123+ - tox-demorepo
124+ - tox-pep8
125+ gate :
126+ jobs :
127+ - tox-demorepo
128+ - tox-pep8
112129` ` `
113130
114131### 설명
115132
116- - demo-lib와 demo-repo를 동일 workspace에 체크아웃
117- - demo-lib 변경이 demo-repo 테스트에 반영됨
118- - 라이브러리 변경이 앱에 어떤 영향을 미치는지 병합 전에 확인
133+ - demo-lib와 demo-repo를 동일 워크스페이스에 체크아웃함
134+ - demo-lib 변경 사항이 demo-repo 테스트에 즉각 반영됨
135+ - 라이브러리 변경이 애플리케이션에 어떤 영향을 미치는지 병합 전에 확인함
119136
120137즉, required-projects는 “어떤 프로젝트를 함께 테스트할 것인가”를 정의합니다.
121138
122139------------------------------------------------------------------------
123140
124- ## 6. 실습 예제 구성
125- 구조를 단순화한 예제를 통해 동작 방식을 살펴보겠습니다
141+ ## 6. 실습 예제 구성: 왜 의존성 관리가 필요한가?
142+ 구조를 단순화한 예제를 통해 동작 방식을 살펴보겠습니다.
126143
127- ### demo-lib
144+ ### demo-lib (라이브러리)
128145
129146` ` ` python
130147# demo_lib/math_utils.py
@@ -133,7 +150,7 @@ def add(a, b):
133150 return a + b
134151` ` `
135152
136- ### demo-repo
153+ ### demo-repo (애플리케이션)
137154
138155` ` ` python
139156# app.py
@@ -144,87 +161,76 @@ def calculate():
144161 return add(3, 4)
145162` ` `
146163
147- ### 기본 Zuul 설정
148-
149- ` ` ` yaml
150- - project :
151- check :
152- jobs :
153- - tox-py39
154- gate :
155- jobs :
156- - tox-py39
157- ` ` `
158-
159164------------------------------------------------------------------------
160165
161166## 7. 실패 시나리오
162- 그렇다면 required-projects 설정이 없으면 어떤 문제가 발생할까요?
167+ 그렇다면 required-projects 설정이 없다면 어떤 문제가 발생할까요?
163168
164169### demo-lib 변경
170+ 라이브러리 프로젝트 설정에 애플리케이션 테스트 작업(tox-demorepo)을 추가합니다. 이렇게 하면 라이브러리 코드가 바뀔 때마다 앱이 깨지는지 자동으로 검사합니다.
165171
166172` ` ` python
167173def add(a, b) :
168174 return str(a + b)
169175` ` `
170- 라이브러리 단독 테스트는 통과할 수 있습니다.
176+ 이 경우 라이브러리 단독 테스트는 통과할 수 있습니다.
171177
172178### demo-repo 코드
173179그러나 demo-repo에서는:
174180
175181` ` ` python
176182result = add(3, 4)
177- print(result + 1)
183+ print(result + 1) # 문자열과 숫자의 더하기 연산 발생
178184```
179185
180186### 결과
181187
182- TypeError 발생
183-
184- 이 경우:
188+ TypeError가 발생함
185189
186- * 라이브러리는 통과
190+ ![ alt text ] ( https://i.imgur.com/gCs7kqm.png )
187191
188- * 애플리케이션도 기존 기준으로는 통과
192+ 이 경우 다음과 같은 상황이 벌어집니다:
189193
190- * 하지만 함께 배포되면 장애 발생
194+ * 라이브러리 테스트는 통과함
191195
192- required-projects가 있다면,
196+ * 애플리케이션 테스트도 (기존 라이브러리 기준으로는) 통과함
193197
194- 라이브러리 변경을 적용한 상태로 애플리케이션 테스트를 먼저 수행
198+ * 하지만 실제 병합되어 함께 배포되면 장애가 발생함
195199
196- 하여 병합 전에 문제를 차단합니다.
200+ ` required-projects ` 가 있다면, 라이브러리 변경을 적용한 상태로 애플리케이션 테스트를 먼저 수행하여 병합 전에 문제를 차단합니다.
197201
198202------------------------------------------------------------------------
199203
200204## 8. Depends-On 사용 예제
201- 한 단계 더 나아가 보겠습니다.
202205
203206이번에는 라이브러리와 애플리케이션을 동시에 수정하는 상황입니다.
204207
205208### 상황
206209
207- - demo-lib에 ` multiply ` 함수 추가
208- - demo-repo에서 해당 함수 사용
209- - 두 변경 모두 아직 merge되지 않음
210+ - ` demo-lib ` 에 ` multiply ` 함수를 새로 추가함
211+ - ` demo-repo ` 에서 해당 함수 사용하도록 수정함
212+ - 두 변경 모두 아직 ` main ` 에 병합되지 않음
213+
214+ 이때 단순히 프로젝트를 묶어주는 ` required-projects ` 만으로는 부족합니다.
210215
211- 이때 단순히 require-projects만으로는 부족할 수 있습니다.
216+ 그 이유는 다음과 같습니다:
217+ - 라이브러리의 ** 특정 패치** 와
218+ - 애플리케이션의 ** 특정 패치** 를
219+ - 하나의 논리적 변경 세트로 묶어서 검증해야 하기 때문입니다.
212220
213- 왜냐하면:
214- - 라이브러리의 특정 변경과
215- - 애플리케이션의 특정 변경을
216- - 하나의 논리적 변경 세트로 묶어야 하기 때문입니다.
217221### demo-repo 커밋 메시지
218222
219223 Depends-On: https://review.example.com/c/demo-lib/+/12345
220224
221225### Zuul 동작
222226
223- 1 . demo-lib의 해당 변경 사항 추측 기반 병합
224- 2 . 그 위에 demo-repo 변경 사항 추측 기반 병합
225- 3 . 통합 테스트 실행
227+ 1 . ` demo-lib ` 의 해당 패치(12345)를 추측 기반 병합함
228+ 2 . 그 위에 ` demo-repo ` 변경 사항 추측 기반 병합함
229+ 3 . 통합 테스트를 실행함
226230
227- 즉, Depends-On은 “이번 변경이 어떤 변경 위에서 동작해야 하는지”를 선언합니다.
231+ 즉, ** Depends-On** 은 “이번 변경이 어떤 변경 위에서 동작해야 하는지”를 선언합니다.
232+
233+ ![ alt text] ( https://i.imgur.com/vhuz1up.png )
228234
229235### 정리
230236
@@ -244,21 +250,19 @@ required-projects가 있다면,
244250
245251## 9. 결론
246252
247- 추측 기반 병합(Speculative Merge)는 단순한 가상 병합이 아닙니다.
253+ 추측 기반 병합은 단순한 가상 병합이 아닙니다.
248254
249- - 병합될 가능성이 있는 미래 상태를 먼저 검증하고
255+ - 병합될 가능성이 있는 미래 상태를 먼저 검증함
250256
251- - 프로젝트 간 의존성을 사전에 확인하며
257+ - 프로젝트 간 의존성을 사전에 확인함
252258
253- - 변경 간 관계까지 추적합니다.
259+ - 변경 사항 간의 논리적 관계까지 추적함
254260
255- 이를 통해 `main` 브랜치는 항상 배포 가능한 상태를 유지합니다 .
261+ 이를 통해 ` main ` 브랜치는 항상 배포 가능한 상태를 유지할 수 있습니다 .
256262
257263대규모 협업 환경, 특히 멀티 레포 구조에서는
258-
259- - required-projects로 구조를 묶고
260-
261- - Depends-On으로 변경을 묶는 전략이 필수적입니다.
264+ ** required-projects로 구조를 묶고** ,
265+ ** Depends-On으로 변경을 묶는 전략** 이 필수적입니다.
262266
263267------------------------------------------------------------------------
264268
@@ -268,5 +272,4 @@ required-projects가 있다면,
268272- Dependent Pipeline
269273- Gate
270274- required-projects
271- - Depends-On
272- - Cross-repo CI
275+ - Depends-On
0 commit comments