Skip to content

Commit c53756b

Browse files
authored
Add files via upload
Upload contribution by tlsntjr
1 parent 515cf5a commit c53756b

1 file changed

Lines changed: 90 additions & 87 deletions

File tree

week6/신우석_컨트리뷰션.md

Lines changed: 90 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Zuul의 추측 기반 병합(Speculative Merge)과 Cross-project 의존성(Dependencies) 정리본
1+
# Zuul의 Speculative Merge와 Cross-project Dependencies 정리본
22

33
------------------------------------------------------------------------
44

@@ -13,46 +13,46 @@
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

4242
Zuul은 **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
6262
git 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

9395
Zuul은 다음 두 가지 방식으로 이를 해결합니다:
9496

9597
1. `required-projects` : 정적(구조적) 의존성
9698
2. `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
167173
def add(a, b):
168174
return str(a + b)
169175
```
170-
라이브러리 단독 테스트는 통과할 수 있습니다.
176+
이 경우 라이브러리 단독 테스트는 통과할 수 있습니다.
171177
172178
### demo-repo 코드
173179
그러나 demo-repo에서는:
174180
175181
``` python
176182
result = 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

Comments
 (0)