개념
한 번에 다 돌리는 파이프라인은 어디에서도 쓸모가 없다
모든 검증을 PR마다 돌리면 PR 하나에 한 시간이 걸린다. 개발자는 기다리지 않고 병합 권한이 있는 사람을 찾아간다. 반대로 모든 검증을 릴리스 직전에만 돌리면 일주일치 변경이 한꺼번에 실패하고, 어느 변경이 원인인지 찾는 데 하루가 간다.
해법은 오래된 것이다. 같은 기준을, 다른 강도로, 다른 시점에 돌린다. 모듈 14에서 CI/CD와 품질 게이트를 배웠다. 이 레슨은 거기에 두 가지를 더한다. 첫째, 세 층이 같은 기준 ID 체계 를 공유해서 한 층의 결과가 다음 층의 입력이 되게 한다. 둘째, AI 판정을 어느 층에 얼마나 배치할지 정한다.
세 층의 역할
| PR 검증 | 주기 회귀 | 릴리스 전 검증 | |
|---|---|---|---|
| 언제 | PR 생성·갱신마다 | 매일 밤 또는 몇 시간마다, main 기준 | 주간 배포 후보가 정해졌을 때 |
| 질문 | 이 변경이 기준을 깼는가 | 변경들이 합쳐져서 기준을 깼는가, 환경이 흔들리는가 | 이 후보를 운영에 내보내도 되는가 |
| 시간 예산 | 10~15분 | 1~3시간 | 반나절 이내 |
| 범위 | 변경 영향 범위의 기준 | 전체 결정적 기준 + 핵심 해석 기준 | 전체 기준 + 운영 유사 환경 전용 기준(성능·장애 주입·업그레이드) |
| 판정 | 결정적 판정 위주, 해석 판정은 변경된 사용자 노출 문구만 | 결정적 + 해석(보정된 판정자) | 결정적 + 해석 + 사람 표본 검토 |
| 막는 것 | 병합 | 다음 날 병합(빨간 main 정책) | 배포 |
| 실패 시 주인 | PR 작성자 | 당번(빌드 경찰) + 원인 PR 작성자 | 릴리스 책임자 + QA |
세 층의 시간 예산은 조직마다 다르다. 중요한 것은 숫자를 정해 두는 것 이다. 예산이 없으면 PR 검증은 계속 무거워진다. 새 검사를 추가할 때마다 "이것이 PR 층의 예산 안에 들어가는가, 아니면 회귀 층으로 가야 하는가"를 묻게 만드는 것이 예산이다.
PR 층 — 변경 영향 기반 선택
PR 층의 핵심 기술은 돌릴 기준을 고르는 것 이다. 레슨 2에서 테스트 이름에 기준 ID를 넣었다. 이제 변경 파일에서 기준 ID로 가는 지도가 있으면 선택이 기계적이 된다.
[변경 영향 지도 — 예시]
services/compute/handlers/servers.py → D-COMP-001..030, I-COMP-ERRMSG
services/compute/workers/build.py → D-COMP-010..018 (비동기 수렴), D-COMP-040..044 (부분 생성 누수)
services/quota/ → D-COMP-014, D-TRAIN-020..025, D-INFER-011 ← 여러 도메인에 걸침
deploy/charts/compute/values.yaml → 스모크 전체 + 해당 서비스 배포 기준 (m39 레슨 4)
docs/ → 없음지도 없이 "바뀐 서비스의 테스트만 돌린다"는 규칙을 쓰면 services/quota/ 같은 공용 모듈 변경에서 다른 도메인의 기준을 놓친다.
쿼터는 컴퓨트·학습·추론 모두에 걸린다. 공용 모듈의 영향은 지도에 명시 해야 한다.
지도를 사람이 손으로 유지하면 금방 낡는다. 세 가지 보조 수단을 섞는다.
| 수단 | 방식 | 한계 |
|---|---|---|
| 정적 의존 분석 | import 그래프로 영향 모듈 추정 | 설정·메시지 큐·HTTP 호출로 이어진 의존은 못 본다 |
| 커버리지 기반 | 과거 실행에서 각 테스트가 지나간 파일 기록 | 기록이 오래되면 틀린다 |
| AI 영향 분석 | 에이전트가 diff를 읽고 영향 기준 ID를 제안 | 제안이다. 결정적 수단의 결과에 더하기만 하고 빼지는 못하게 한다 |
마지막 줄의 규칙이 중요하다. AI가 "이 변경은 영향이 없다"고 판단해 결정적 선택 결과에서 테스트를 빼면, 판정자 보정 없이 판정을 맡기는 셈이 된다. AI 영향 분석은 선택 범위를 넓히는 방향 으로만 쓴다.
그리고 PR 층은 선택이 틀릴 수 있다는 것을 전제로 한다. 그 안전망이 회귀 층이다.
회귀 층 — 합쳐진 변경과 흔들리는 환경
회귀 층은 PR 층이 고른 것만 돌렸기 때문에 존재한다. PR마다 따로 통과한 변경들이 main에서 합쳐져 깨지는 경우, PR 층의 선택 지도가 놓친 영향, 그리고 시간이 지나야 드러나는 문제를 잡는다.
회귀 층에서만 볼 수 있는 것들이 있다.
| 항목 | 이유 |
|---|---|
| 전체 결정적 기준 | 선택 누락의 안전망 |
| 같은 기준의 반복 실행 결과 | 흔들리는 테스트(플래키)를 지표로 잡는다(레슨 6) |
| 해석 판정 전체 | 판정 비용이 커서 PR 층에 못 넣는 것 |
| 장시간 비동기 수렴 | 학습 작업 체크포인트, 스냅샷 복제처럼 수십 분 걸리는 흐름 |
| 환경 드리프트 | 의존 서비스·이미지·드라이버 버전이 조용히 바뀐 것 |
회귀 층이 실패했을 때의 규칙을 미리 정한다. 가장 흔한 두 가지 정책이 있다.
- 빨간 main 정책: 회귀가 실패하면 원인이 확인될 때까지 main 병합을 멈춘다. 강하지만 실패가 잦으면 팀이 정책을 우회한다
- 원인 PR 되돌리기 정책: 이진 탐색(모듈 9 레슨 11의 bisect)으로 원인 커밋을 찾아 자동 되돌리기 PR을 만들고, 원 작성자가 고쳐서 다시 올린다
어느 쪽이든 플래키로 판명된 실패는 정책 대상에서 빼고 격리 목록으로 보낸다. 플래키를 원인 PR로 몰면 엉뚱한 개발자가 되돌림을 당하고, 팀은 회귀 결과를 믿지 않게 된다.
릴리스 전 층 — 운영에 가장 가까운 질문
릴리스 전 층은 기능 검증을 다시 하는 곳이 아니다. 회귀 층까지 통과한 후보에 대해 운영에서만 나타나는 조건 을 묻는다.
| 검증 | 왜 여기서 |
|---|---|
| 업그레이드 경로 | 직전 운영 버전에서 후보 버전으로 올렸을 때 기존 리소스(실행 중 VM·학습 작업·엔드포인트)가 살아남는가 |
| 롤백 리허설 | 후보에서 직전 버전으로 되돌렸을 때 데이터 스키마·설정이 호환되는가 |
| 운영 규모 성능 | 대표 부하에서 지연·처리량 기준(m39 레슨 6) |
| 장애 주입 | 노드·네트워크·GPU 장애 시 복구 기준(m39 레슨 7) |
| 보안 스캔 | 이미지 취약점, 설정 검사 |
| 사람 표본 검토 | 이번 주 해석 판정의 PASS 표본(레슨 3) |
업그레이드와 롤백은 PR 층에서 절대 볼 수 없다. PR 환경은 매번 새로 만들어지기 때문이다. 인프라 플랫폼 결함 중 고객 영향이 가장 큰 부류가 "새로 만든 리소스는 괜찮은데 기존 리소스가 업그레이드 후 깨지는" 결함이다. 릴리스 전 층의 존재 이유다.
판정 레코드 — 세 층이 같은 말을 하게 만들기
세 층이 각자 다른 형식으로 결과를 남기면 게이트에서 그것을 모으는 데 사람의 반나절이 든다. 판정 결과를 기준 ID 단위의 한 형식 으로 남긴다.
{
"run_id": "rgr-2026-09-16-0200",
"layer": "regression",
"commit": "a1b2c3d",
"environment": "stg-2 (k8s 1.36.4, gpu-operator 25.x, driver 580.x)",
"criteria_version": "compute 2026.09.2",
"criterion_id": "D-COMP-042",
"judge": { "type": "deterministic", "check": "no_orphan_ports_after_quota_reject" },
"verdict": "fail",
"attempts": 3,
"attempt_verdicts": ["fail", "fail", "fail"],
"evidence": {
"artifact": "s3://qa-evidence/rgr-2026-09-16-0200/D-COMP-042/",
"summary": "쿼터 거부 후 60초 시점에 포트 1개 잔존 (port-7f3a)"
},
"defect": "PLAT-2231"
}해석 판정이면 judge 칸이 이렇게 바뀐다.
"judge": {
"type": "llm",
"rubric": "R-ERRMSG-02 rev4",
"judge_model": "고정된 모델 식별자",
"calibration_ref": "cal-errmsg-2026-09-01 (kappa 0.78, fail recall 0.92)",
"quotes": ["GPU 쿼터(8개)를 모두 사용해", "관리자에게 쿼터 증설을 요청하세요"]
}이 형식에서 눈여겨볼 칸은 넷이다.
criteria_version: 기준이 바뀐 뒤의 판정과 전의 판정을 섞지 않게 한다environment: 같은 기준이 환경에 따라 결과가 갈릴 때 원인을 좁힌다attempts·attempt_verdicts: 재시도로 통과한 것인지 드러낸다. 세 번 중 한 번 통과를 "통과"로 요약하면 플래키가 숨는다calibration_ref: 해석 판정이 어떤 보정 근거 위에 있는지 연결한다
이 레코드가 쌓이면 레슨 5의 게이트는 레코드를 조회해서 판정 요약을 만들고, 레슨 6의 대시보드는 레코드를 집계해서 지표를 만든다. 모듈 18c 레슨 7의 감사 로그가 "무엇이 누구의 판단이었는지 재구성"을 목표로 했다면, 판정 레코드는 그 감사 로그의 기준 단위 버전 이다.
환경과 테스트 데이터
세 층의 결과가 비교 가능하려면 환경이 설명 가능해야 한다. 모듈 7 레슨 3의 환경 패리티 원칙이 파이프라인에서 구체화된다.
| 층 | 환경 | 데이터 |
|---|---|---|
| PR | PR마다 만드는 임시 환경(네임스페이스·가상 클러스터) 또는 공유 스테이징의 격리 프로젝트 | 테스트가 스스로 만들고 스스로 지운다. 정리 실패 자체를 기준으로 본다 |
| 회귀 | 고정된 스테이징. 버전 목록을 레코드에 기록 | 시드 데이터 + 테스트 생성 데이터, 매일 초기화 |
| 릴리스 전 | 운영과 같은 토폴로지의 사전 운영 환경 | 운영 규모를 흉내 낸 데이터, 직전 운영 버전에서 만든 기존 리소스 |
GPU처럼 비싼 자원은 PR 층에서 실제로 쓰기 어렵다. 그래서 PR 층은 스케줄링·쿼터·상태 전이까지를 가짜 GPU 노드(확장 리소스를 흉내 내는 노드)로 검증하고, 실제 GPU가 필요한 기준은 회귀·릴리스 층에 둔다. 어떤 기준이 어떤 층에서 흉내로 검증되고 어디서 실물로 검증되는지 를 기준 문서에 적어 둔다. 흉내로만 검증된 기준이 릴리스 전까지 실물 검증을 한 번도 안 거치는 일이 없게.
실무에서 왜 필요한가
채용 공고의 "PR 단위 검증, 주기 회귀, 릴리즈 전 검증으로 이어지는 파이프라인 운영"은 세 개의 CI 잡을 만드는 일이 아니다. 세 층이 같은 기준으로 다른 질문 을 하고, 결과가 한 형식으로 모여 게이트가 판단할 수 있게 하는 일이다. 층 사이의 약속이 없으면 PR은 통과, 회귀는 실패, 릴리스는 "지난주에도 실패했으니 괜찮다"로 흘러간다.
판정 레코드 형식은 한 번 정하면 바꾸기 어렵다. 조회·집계·보고가 모두 그 위에 쌓이기 때문이다. 파이프라인을 처음 설계하는 단계의 QA가 정한 형식이 팀의 표준 이 된다. 공고가 "지금 설계하는 기준이 곧 팀의 표준이 됩니다"라고 쓰는 이유다.