올바른 로딩 화면을 배포 검사가 거절했다
Workload Studio의 초기 HTML에는 React가 실행되기 전 보여주는 로딩 화면이 들어 있다. 그런데 Compose smoke는 로그인 뒤 받은 문서에 빈 div#root가 있는지 검사했다. root 안에 로딩 화면이 생기자 정상 문서가 그 조건을 만족하지 못했다. 저장소에 기록된 CI에서는 Python·웹·이미지 빌드를 통과한 뒤 이 검사에서 실패했고 registry 게시 단계는 건너뛰었다.
문제는 로딩 화면의 존재가 아니라 검사 기준이었다. 빈 root라는 구현 세부사항은 사용자에게 제공해야 할 문서의 계약이 아니다. 변경은 실제 배포 이미지가 가진 HTML을 기대값으로 삼도록 바꿨다.
checkout의 가정 대신 이미지 안의 바이트를 읽는다
smoke는 실행 이미지의 /app/web/dist/index.html을 꺼내 비어 있지 않은지 확인한다. 이어 인증 cookie로 /와 /results를 요청한다. HTTP 200이어야 하고, 응답은 꺼낸 파일과 cmp로 정확히 일치해야 한다. 로그인 절차를 새로 검증하는 변경이라기보다, 로그인 이후 초기 앱 문서의 전달을 확인하는 계약이다.
status="$(curl -fsS -b "$work/cookies" \
-o "$work/page.html" -w '%{http_code}' "$base$1")" || return 1
[ "$status" = 200 ] && cmp -s "$work/index.html" "$work/page.html" 위는 실제 비교 함수의 핵심이다. 이미지 안에 빈 root가 있으면 그 문서를 받아들이고, 로딩 화면이 있으면 그 문서를 받아들인다. 다른 HTML을 반환하거나 redirect·오류 상태를 반환하는 경우는 거절한다. 서버가 응답마다 초기 문서를 동적으로 바꾸는 구조라면 별도 비교 계약이 필요하지만, 여기서는 정적 index를 그대로 전달하는 동작에 맞는다.
실제 HTTP 응답을 검사해도 React를 실행한 것은 아니다
| 회귀 테스트의 응답 | 기대 판정 |
|---|---|
| 일치하는 로딩 HTML · 200 | 통과 |
| 일치하는 빈 root HTML · 200 | 통과 |
| 다른 HTML · 200 | 거절 |
| 일치하는 HTML · 404 | 거절 |
| 일치하는 HTML · 302 | 거절 |
다섯 사례는 loopback의 실제 ThreadingHTTPServer를 열고 smoke 파일에서 추출한 ui_page 함수를 실행한다. 문자열 비교 함수를 흉내 내는 테스트보다 HTTP 상태·응답 파일·실제 비교 명령의 연결을 직접 확인한다. 다만 fixture의 문서와 이미지에서 기대 파일을 꺼내는 전체 Compose 절차는 서로 다른 검증 범위다.
당시 저장소 기록에는 배포 파일 테스트 48개와 새 전체 이미지 빌드, 격리한 Compose smoke의 통과가 남아 있다. 이 smoke는 초기 문서를 받지만 JavaScript를 실행하지 않는다. JS·CSS 파일의 로드 성공, React 렌더와 사용자 조작은 실제 브라우저 검사로 남는다.
Workload Studio의 이 수정은 UI가 바뀔 때마다 특정 root 모양을 허용 목록에 추가하는 부담을 줄이고, 검사 기대값을 배포 산출물에 붙였다. tokenizer 파일의 런타임 분리와 함께, 이미지에 들어간 것과 실행 환경이 제공하는 것을 각각 확인하는 사례다.