UI 자동화 테스트가 왜 결국 플레이키 관리 문제로 수렴하는가

Selenium과 Playwright의 실무 차이, 안정성 확보 메커니즘, 플레이키 격리 정책까지 UI 자동화 테스트 운영을 정리한다

2026-08-12 · 최초 발행 2025-12-18

로그인→결제→확인처럼 사용자가 실제로 밟는 흐름을 스크립트로 재현해 검증하는 게 UI 자동화 테스트다. 기능적 E2E 플로우, 크로스 브라우저 호환성, 시각적 회귀, 성능 지표의 최소 임계 검증까지 다루지만, 테스트 피라미드에서 단위·통합 테스트보다 위쪽에 자리하는 만큼 시나리오 수는 적게, 가치는 높게 가져가야 한다. 핵심 유저 저니를 기준으로 스모크·회귀 세트를 구성하는 이유다.

안정성은 대기 전략에서 시작한다

UI 자동화가 무너지는 가장 흔한 경로는 시나리오 부족이 아니라 플레이키(Flaky) 방치다. 명시적 대기(Explicit wait)와 자동 대기(Auto-wait)를 쓰고 고정 슬립을 제거하는 것, 네트워크 정지 상태를 판단하고 애니메이션을 안정화하는 것이 기본이다. 그 위에 플레이키 감지와 재시도 정책을 분리 운영하고, 격리(quarantine) 목록을 관리하면서 원인을 라벨링(로딩 지연, 셀렉터 취약 등)하는 루프를 붙여야 한다.

테스트 케이스 설계 단계에서는 Gherkin 스타일 행동 서술과 data-testid 같은 안정적 로케이터 표준화가 유지보수 비용을 줄인다. 핵심 유저 저니(E2E), 컴포넌트/스토리북 테스트, 시각적 회귀를 계층 분리해 운영하면 중복 시나리오도 최소화된다.

실행 인프라 쪽에서는 Headless/Headed 실행을 선택하고 Docker 컨테이너로 환경을 표준화한 뒤, Selenium Grid나 Playwright의 shard 기능으로 병렬화해 처리량을 늘린다. 모바일 웹은 실제 장치나 클라우드 디바이스팜을 병행하고, 브라우저 버전은 고정한 채 주간 업데이트 윈도우로 관리한다.

데이터·상태 관리도 안정성에 직결된다. 테스트 데이터 시드/픽스처를 자동화하고 테넌트·DB 스키마로 환경을 격리해 케이스 간 상태 오염을 막는다. 외부 연동은 Mock/Stub이나 네트워크 인터셉트로 결정적 결과를 확보하고, 보안 민감 데이터는 샌드박스 키나 비식별값을 쓴다.

리포팅은 JUnit XML, HTML 리포트, 스크린샷·비디오·트레이스 아티팩트를 모아 실패 재현성을 극대화하는 쪽으로 맞춘다. 패스율, 플레이키율, 평균 실행시간, 실패 Top-5 원인, 유저 저니 대비 커버리지를 대시보드로 묶으면 어디가 병목인지 바로 보인다.

스모크 게이팅과 야간 회귀를 나누는 이유

PR 단위로는 로그인→결제→확인 같은 핵심 흐름 5~10케이스만 돌려 임계 실패율 기준으로 배포를 차단하는 스모크 게이팅을 쓴다. Playwright Trace Viewer를 쓰면 재현 시간이 줄고 개발자가 스스로 원인을 찾아 고치는 속도가 빨라진다. 반대로 Chrome/Firefox/WebKit 전체를 도는 멀티브라우저 회귀는 야간으로 돌리고, 실운영 브라우저 점유율 기반으로 가중 커버리지를 설계한다. 차등 실패가 감지되면 관련 컴포넌트 라벨을 자동으로 붙여 담당 팀에 라우팅한다.

결제·인증 시나리오는 별도로 다뤄야 한다. 결제 게이트웨이는 샌드박스와 웹훅 모킹을 병행하고, OTP/2FA는 테스트 백도어 토큰 발급으로 비결정성을 제거한다. 네트워크 타임아웃 같은 장애를 주입해 복구 플로우까지 검증하는 게 실전이다. 시각적 회귀는 SKU, 장바구니, 체크아웃 같은 크리티컬 뷰의 스냅샷 기준선을 관리하고 픽셀/퍼센트 단위로 허용 오차를 정책화한다. 다크모드·로케일별로 스냅샷을 세분화하고 폰트·OS 차이를 보정해야 오탐이 줄어든다.

CI 트리거테스트 환경프로비저닝(Docker, 브라우저)결과 수집(JUnit XML, Trace,스크린샷)임계값 비교(실패율 <= 2%)통과불통과플레이키 감지(재시도 n <= 2)재현 불가/추가 관찰에러(타임아웃,'ElementNotFound')리포트 첨부 알림코드 커밋(브랜치)빌드 의존성 설치(Node.js,Python)테스트실행(Selenium/Playwright)리포트 생성(메트릭 집계)배포 결정배포 진행(스테이징→프로덕션)롤백/배포 차단격리 리스트등록('quarantine')스냅샷/네트워크 로그 저장

도입 순서와 운영에서 갈리는 트레이드오프

도입은 유저 저니 식별과 브라우저 타깃, 임계 지표(실패율, 소요시간)를 정하는 데서 시작한다. 그다음 Playwright(올인원, 병렬·트레이스 강점)와 Selenium(언어·생태계 유연성) 중 프레임워크를 정하고, 로케이터·대기 전략·폴더/픽스처 구조·공통 유틸 규약을 표준화한다. Docker 이미지를 고정하고 CI 셰어드 캐시, 아티팩트 업로드, 시크릿 관리로 인프라를 갖춘 뒤, 스모크 10케이스 내외로 시작해 야간 회귀를 분리하고 플레이키 격리 루프를 돌린다. 이후 샤딩·병렬 최적화, 테스트 데이터 팩토리, 리포트 대시보드·알림 자동화로 확장한다.

운영에서는 몇 가지 트레이드오프를 결정해야 한다. 시크릿·자격증명은 Vault나 CI Secret Store에 테스트 전용 최소 권한 계정으로 두고 브라우저 옵션의 위험 플래그를 최소화한다. 원격 그리드를 자체 호스팅하면 비용과 제어성은 좋지만 관리 오버헤드가 늘고, 클라우드 디바이스팜은 실디바이스 커버리지와 운영 편의는 좋지만 사용량 기반 비용이 늘어난다. 모킹을 늘리면 안정성은 오르지만 실제 통합 신뢰성은 떨어지므로 핵심 결제·인증 구간은 샌드박스 통합 테스트를 병행해야 한다. 리트라이 정책도 마찬가지다 — 일시 오류를 흡수하는 효과는 크지만 진짜 결함을 은폐할 위험도 커지므로, 재시도 후에도 실패하면 즉시 격리하고 원인 분석 티켓을 자동 발급하는 규칙이 필요하다.

Playwright와 Selenium, 숫자로 갈라보면

지표 Selenium Playwright
성능 드라이버-브라우저 통신 오버헤드로 상대적 느림 단일 러너·자동 대기 최적화로 빠른 경향
확장성 Grid·클러스터로 대규모 확장 용이, 구성 복잡 내장 병렬·샤딩 간단, 대규모는 워커/샤드 관리 필요
일관성 다양한 바인딩/드라이버로 이질성 존재 API 일관·오토웨이트로 플레이키 저감
안정성 적절한 Explicit wait 설계 필요 네트워크/페이지 안정화 빌트인, 트레이스 복구 용이
운영 편의 생태계·툴 다양, 설정 분산 설치·기본값 우수, 리포트/트레이스 일체형

전제조건은 Node.js 18+, Playwright 1.49+ 또는 Python 3.11+, 최신 Chrome, 선택적으로 Docker다.

Playwright(TypeScript)로 로그인→대시보드 스모크는 이렇게 짠다.

// npm i -D @playwright/test
// npx playwright install
import { test, expect } from '@playwright/test';

test('로그인→대시보드 스모크', async ({ page }) => {
  await page.goto('https://example.com/login');
  await page.getByTestId('username').fill('test-user');
  await page.getByTestId('password').fill('P@ssw0rd!');
  await page.getByRole('button', { name: 'Sign in' }).click();
  await expect(page.getByTestId('dashboard')).toBeVisible();
});

같은 흐름을 Selenium(Python)으로 짜면 명시적 대기를 직접 걸어야 한다는 차이가 바로 드러난다.

# pip install selenium==4.25.0 webdriver-manager
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager

driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get("https://example.com/login")
driver.find_element(By.CSS_SELECTOR, "[data-testid='username']").send_keys("test-user")
driver.find_element(By.CSS_SELECTOR, "[data-testid='password']").send_keys("P@ssw0rd!")
driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
WebDriverWait(driver, 10).until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, "[data-testid='dashboard']"))
)
driver.quit()

도입 효과와 남는 문제

이 체계를 갖춘 조직에서는 회귀 결함이 4070% 줄고, 릴리스 리드타임이 3050% 단축되며, MTTR이 20~40% 개선되고, 수동 QA 시간이 30% 이상 절감된다고 보고된다(조직 성숙도에 비례). 정성적으로는 배포 신뢰도가 오르고 개발자 피드백 루프가 짧아지며, 장애 재발 방지 지식이 쌓이고 규제·감사 대응이 쉬워진다.

결국 UI 자동화 테스트는 핵심 유저 저니를 기준으로 소수 정예 시나리오를 안정적으로 운영하는 체계를 만드는 일이다. Selenium과 Playwright의 장단을 보고 도구를 고르되, 로케이터 표준·대기 전략·데이터 격리·메트릭 기반 운영을 결합해 플레이키를 관리하고, CI 게이팅과 야간 회귀의 이중 전략으로 품질과 속도를 동시에 잡는 게 실무의 답이다.

UI자동화테스트PlaywrightSelenium플레이키테스트시각적회귀