Playwright 시각적 회귀 테스트: 기준 이미지 갱신을 승인으로 착각하지 않기
Playwright 스크린샷 비교의 안정화와 제품 승인을 구분한다. 고정 입력·환경·허용치·마스킹을 점검하고, AI 코드 수정에서도 기준 이미지 갱신을 별도로 검토하는 운영 방법을 정리한다.
화면의 차이를 찾는 일과 새 기준을 승인하는 일은 분리해야 한다. AI 생성 에디토리얼 이미지.
버튼은 클릭되고 제목도 정확한데, 결과물은 어제와 전혀 다른 인상을 준다. 여백이 넓어지고 글자가 밀리거나 강조색이 바뀌어도 기능 테스트는 통과할 수 있다. AI가 UI 코드를 수정하는 작업에서도 마찬가지다. 요구한 문구를 넣었다는 사실과 유지해야 할 디자인을 지켰다는 사실은 서로 다르다.
이때 시각적 회귀 테스트가 유용하다. 다만 실패한 테스트를 보고 기준 이미지를 바로 갱신하면, 발견한 회귀를 새 정답으로 저장할 수 있다. 차이 검출은 자동화하고, 기준 변경은 별도의 검토 대상으로 다루는 것이 이 글의 핵심이다.
1. 안정된 화면과 올바른 화면은 다르다
Playwright의 toHaveScreenshot()은 연속 두 번의 스크린샷이 같은 결과가 될 때까지 기다린 뒤, 마지막 이미지를 저장된 기준과 비교한다. locator에 적용하면 페이지 전체 대신 특정 컴포넌트만 비교할 수 있다. 이 안정화는 촬영 조건에 관한 동작이지, 제품 데이터가 모두 준비되었다거나 디자인이 옳다는 판정이 아니다. LocatorAssertions 공식 문서
예를 들어 로딩 화면이 멈춰 있으면 안정적인 스크린샷을 얻을 수 있다. 따라서 실제 서비스에서는 먼저 필요한 텍스트나 상태를 검증하고, 폰트·이미지 등 화면 구성에 필요한 자원이 준비된 뒤 비교해야 한다. 무조건 몇 초 쉬는 방식보다 ‘무엇이 준비되어야 하는가’를 테스트에 적는 편이 원인을 추적하기 쉽다.
기준 이미지도 검토 대상이다. 처음 생성한 파일은 프로그램이 처음 본 결과일 뿐, 팀이 승인한 디자인이라는 의미는 없다.
2. 비교 범위를 작게 잡고 입력을 고정한다
전체 페이지를 처음부터 촬영하면 광고·시각·추천 목록처럼 테스트 목적과 무관한 변동까지 실패 원인이 된다. 우선 가격 카드, 결제 버튼 주변, 미리보기 패널처럼 유지해야 할 영역 하나를 고르고 고정된 데이터를 넣는 편이 낫다.
아래 예시는 네트워크 요청 없이 작은 카드를 렌더링한다. SHIFT_LAYOUT=1이면 내부 여백만 24px에서 32px로 바뀐다. 제목 검증과 화면 비교를 함께 두어, 내용이 같아도 배치는 달라질 수 있음을 살펴보는 구성이다.
Playwright Test와 해당 버전의 Chromium이 설치된 프로젝트를 전제로 한다. 처음 설치하는 경우에는 공식 설치 안내를 따른다.
playwright.config.mjs
tests/card.spec.mjs
화면 크기·배율·색상 모드·언어·시간대는 비교 조건의 일부다. 각 설정은 Playwright의 use 옵션에서 관리한다. 위 예제의 document.fonts.ready는 폰트 준비를 기다리기 위한 장치이며, 애플리케이션의 API 응답이나 이미지 로딩까지 대신 기다려 주지는 않는다.
스크린샷 assertion에서 animations의 기본값은 disabled다. 예제에는 촬영 의도를 드러내기 위해 명시했다. 유한 애니메이션은 종료 상태로 진행하고, 무한 애니메이션은 촬영을 위해 초기 상태로 취소되었다가 촬영 후 다시 재생된다. 이 설명을 일반 page.screenshot()의 기본값과 혼동하면 안 된다. 스크린샷 assertion 옵션
3. 검증 명령과 갱신 명령을 분리한다
기준 생성·일반 검증·변경 검증을 따로 실행한다. 아래 환경변수 문법은 POSIX 셸 기준이다.
마지막 명령은 레이아웃 차이를 검출하도록 의도한 재현 절차다. 제목 텍스트는 그대로이므로 내용 assertion과 시각 assertion이 다른 책임을 맡는다.
검증 범위: 위 JavaScript 파일은 정적 구문 검사를 통과했다. 작성 환경에서는 Chromium이 시작되지 않아 실제 스크린샷 통과·실패 결과를 측정하지 못했다. 따라서 이 예제는 공식 API를 바탕으로 구성한 실행 예시이며, 위 절차의 브라우저 실행 결과를 검증 완료로 주장하지 않는다.
현재 CLI에서 --update-snapshots는 실제 결과로 스냅샷을 갱신하는 옵션이다. 이 글에서는 의미를 분명히 하려고 all과 none을 명시했다. 설치된 버전에 따라 지원 모드와 기본 동작이 다를 수 있으므로 npx playwright test --help도 확인한다. CLI 공식 문서
문제의 여백 변경을 승인하기로 했다면 그때 갱신한다. 반대로 의도하지 않은 변경이면 코드를 고쳐 기존 기준을 다시 통과시켜야 한다. 실패를 없애려는 목적만으로 갱신 명령을 실행하면 이 두 경우가 구분되지 않는다.
4. 허용치를 키우기 전에 실패를 분류한다
먼저 코드 변경인지 환경 차이인지 구분한다. OS·브라우저·폰트·실행 모드 등의 차이가 픽셀 결과에 영향을 줄 수 있다. macOS에서 만든 기준을 Linux CI에서 그대로 비교하는 방식은 불필요한 차이를 만들 수 있다. 기준을 생성한 환경과 검증 환경을 맞추라는 것이 공식 가이드의 권고다. Visual comparisons
실무에서는 Playwright 버전과 브라우저 버전, 사용 폰트, CI 실행 이미지를 함께 고정하고, 의도적으로 여러 환경을 지원한다면 환경별 기준을 관리하는 방식을 권한다. 설정 파일에 viewport만 넣는 것으로 모든 렌더링 차이가 사라지지는 않는다. 컨테이너를 활용하는 방법은 CI 공식 안내를 참고할 수 있다.
허용치도 서로 다른 의미를 가진다.
threshold: 같은 위치의 두 픽셀을 비교할 때 허용하는 지각 색상 차이다. 기본값 0.2를 ‘전체 픽셀의 20%까지 달라도 통과’로 해석하면 틀린다.
maxDiffPixelRatio: 전체 픽셀 중 다른 픽셀이 차지하는 허용 비율이다. 0.01은 그 비율의 상한을 1%로 둔다는 뜻이다.
maxDiffPixels: 달라도 되는 픽셀의 개수다.
이 값들은 공식 assertion 옵션에 정의되어 있다. 작은 핵심 아이콘 하나가 바뀌어도 전체 화면에서는 차이 비율이 작을 수 있다. 그래서 넓은 화면에 느슨한 비율을 적용하기보다, 중요한 영역을 따로 검사할지 먼저 판단해야 한다.
5. 동적 영역을 가리는 순간 검증 범위도 줄어든다
시간 표시나 매번 달라지는 데이터는 고정 입력으로 바꾸는 것이 우선이다. 고정하기 어렵다면 mask나 촬영용 스타일을 고려할 수 있지만, 가려진 내용의 시각적 검증을 포기한다는 점을 명시해야 한다. 마스크의 위치와 크기는 비교 이미지에 남는다.
mask는 대상의 bounding box를 색으로 덮는다. 요소를 DOM에서 제거하는 옵션이 아니며, 보이지 않는 요소에도 적용될 수 있다. stylePath는 촬영 중 스타일을 적용하고, 공식 가이드는 visibility: hidden을 이용하는 예제를 제공한다. 콘텐츠를 가리는 것과 공간까지 없애 레이아웃을 바꾸는 것은 구별해야 한다. 마스크 옵션 · stylePath 예제
브랜드 색상이나 제목 배치를 검증하고 싶은데 바로 그 영역을 마스킹하면 테스트 목적을 잃는다. 마스크를 추가할 때는 ‘왜 변동하는가’와 ‘무엇을 포기하는가’를 리뷰 설명에 남기는 편이 좋다.
새로 생성하는 사진이나 일러스트 전체에 픽셀 일치를 요구하는 것도 적절하지 않을 수 있다. 생성 결과마다 구도가 달라지는 영역과, 고정되어야 하는 로고·자막 위치·UI 프레임은 요구사항이 다르다. AI 생성물에는 픽셀 검증과 별도로 스타일 참고 이미지, 가독성, 내용 정확성을 확인하는 검수 항목이 필요하다. 시각적 회귀 테스트만으로 ‘원래 분위기를 잘 살렸는가’까지 자동 판정할 수는 없다.
6. 기준 변경을 작은 승인 절차로 만든다
팀에 처음 도입한다면 다음 정도로 시작할 수 있다. 이는 Playwright가 제공하는 자동 승인 기능이 아니라, 비교 기능 위에 팀이 정하는 운영 규칙이다.
- PR의 일반 검증에서는 기준을 갱신하지 않는다. 실패하면 기대 이미지·실제 이미지·차이 이미지를 검토할 수 있도록 테스트 산출물을 보존한다.
- 코드 회귀와 환경 변경을 먼저 구분한다. 환경이 바뀐 경우에도 전체 기준을 일괄 갱신하기 전에 대표 화면을 확인한다.
- 의도한 디자인 변경이라면 기준 이미지 변경을 해당 코드 변경과 함께 리뷰한다. 무엇이 달라졌고 왜 허용하는지 적는다.
- AI 코딩 작업에도 같은 절차를 적용한다. 수정한 코드의 테스트를 통과시키기 위해 에이전트가 기준까지 임의로 바꾸지 않도록 작업 범위를 정한다.
Playwright는 스냅샷을 버전 관리에 포함하고 변경을 리뷰하도록 안내한다. CI에서는 HTML report 등 결과물을 남기는 예제를 제공한다. 이 두 가지를 연결하면 ‘테스트 실패 → 자동 갱신’ 대신 ‘차이 확인 → 의도 판단 → 기준 승인’이라는 흐름을 만들 수 있다. 스냅샷 관리 · CI 결과물 보존 예제
테스트가 초록색이라는 사실만으로 디자인이 올바르다고 결론 내릴 수는 없다. 무엇을 정답으로 저장했는지, 그 정답이 바뀌는 순간 누가 검토하는지가 시각적 회귀 테스트의 신뢰도를 결정한다.