사전 Playwright
구현체

Playwright

gabury1고친 사람 github-actions[bot]

Playwright 는 코드로 브라우저를 움직여 사람 대신 웹 화면을 눌러 보는 도구입니다. 버튼을 누른 뒤 기대한 결과가 화면에 떴는지 확인합니다. 여러 브라우저를 같은 코드 하나로 다룹니다. 주로 사용자가 거치는 흐름을 처음부터 끝까지 따라가 보는 테스트에 씁니다.

쉽고 빠른 이해

Playwright 는 브라우저를 대신 조작해 주는 도구입니다. 로그인 화면을 열어 아이디와 비밀번호를 넣고 버튼을 누르는 일을 코드 몇 줄로 시킵니다. 그 뒤 「환영합니다」가 뜨는지도 코드가 봅니다.

웹 화면은 서버 응답을 기다리며 조금씩 그려집니다. 코드로 조작하면 버튼이 뜨기도 전에 누르려다 가끔 실패합니다. Playwright 는 버튼을 누를 수 있게 될 때까지 기다렸다가 누릅니다. 그래서 같은 테스트가 어떤 날은 통과하고 어떤 날은 깨지는 일이 줄어듭니다.

어떻게 도나:

  1. 테스트 코드가 「이 버튼을 눌러라」라고 시킵니다
  2. Playwright 가 버튼이 화면에 보이는지, 움직임이 멈췄는지(애니메이션 중이 아닌지) 되풀이해 확인합니다
  3. 조건이 맞으면 누릅니다. 정해 둔 시간이 지나도 안 맞으면 테스트를 실패로 끝냅니다

대가도 있습니다. 진짜 브라우저를 띄우므로 함수 하나를 불러 보는 테스트보다 훨씬 느리고 무겁습니다. 그러니 로그인 · 결제처럼 사용자가 꼭 거치는 흐름에만 씁니다. 파이어폭스와 사파리 계열은 Playwright 가 손본 빌드를 따로 받아 쓰므로 사용자의 브라우저와 똑같지 않습니다.

상세

이 절은 로그인 화면 하나를 시험한다고 치고 Playwright 가 무엇을 대신 해 주는지 따라갑니다. 브라우저를 코드로 움직이는 일이 무엇인지부터 봅니다. 그다음 그 일이 왜 자주 어긋나는지, Playwright 가 그것을 어떻게 막는지로 넘어갑니다.

코드로 브라우저를 움직이는 일

브라우저 자동화는 사람이 마우스와 키보드로 하던 조작을 프로그램이 대신 하게 하는 일입니다. 주소 열기 · 글자 넣기 · 버튼 누르기를 전부 함수 호출로 시킵니다.

이 일을 가장 많이 쓰는 곳은 테스트입니다. 종단 간 테스트(E2E 테스트, End-to-End test)는 사용자가 화면에서 거치는 흐름을 처음부터 끝까지 따라가 보는 테스트입니다. 화면과 서버와 데이터베이스가 한꺼번에 맞물려야 통과합니다. 그래서 함수 하나씩 떼어 보는 단위 테스트가 못 잡는 이음매의 고장을 잡습니다.

Playwright 로 로그인 흐름을 적으면 아래와 같습니다. 파이썬 판으로 적었습니다.

Python
page.goto("https://shop.test/login")
page.get_by_label("아이디").fill("euns")
page.get_by_label("비밀번호").fill("pw1234")
page.get_by_role("button", name="로그인").click()
expect(page.get_by_text("환영합니다")).to_be_visible()

앞의 네 줄은 사람이 하던 조작을 한 줄씩 옮긴 것입니다. 마지막 줄은 「환영합니다」라는 글자가 화면에 보이는지 확인합니다. 보이지 않으면 테스트가 실패합니다.

이 코드는 보통 창을 띄우지 않고 돌아갑니다. 화면을 그리는 일은 다 하되 모니터에 내보내지만 않는 브라우저를 헤드리스 브라우저라고 부릅니다. 모니터가 없는 서버에서도 돌릴 수 있습니다.

지속적 통합(CI, Continuous Integration)은 코드가 저장소에 들어올 때마다 빌드와 테스트를 자동으로 돌리는 일입니다. 헤드리스 브라우저는 모니터 없이 돌아가므로 Playwright 테스트도 CI 서버에 올려 둘 수 있습니다.

한 코드로 다루는 세 렌더링 엔진

렌더링 엔진은 웹 문서를 읽어 화면에 그리는 브라우저 속 부품입니다. 같은 페이지라도 엔진마다 그리는 방식이 조금씩 다릅니다. 그래서 한 브라우저에서 멀쩡한 화면이 다른 브라우저에서 깨지기도 합니다.

지금 널리 쓰이는 엔진은 셋입니다. Playwright 는 셋을 모두 띄웁니다.

엔진 이 엔진을 쓰는 브라우저 Playwright 가 띄우는 것
Blink 크롬 · 엣지 크롬의 바탕인 공개 소스 브라우저 Chromium
Gecko Firefox 원격 조종을 받도록 손본 파이어폭스
WebKit Safari 원격 조종을 받도록 손본 WebKit 브라우저

세 엔진을 같은 함수로 다루므로 위 테스트 코드를 고치지 않고 세 번 돌릴 수 있습니다. 테스트 설정에서 브라우저 이름만 바꿉니다. 이렇게 여러 브라우저에서 같은 흐름을 시험하는 것을 크로스 브라우저 테스트라고 부릅니다.

표의 오른쪽 칸에 보이듯 Playwright 는 자기 버전에 맞춘 브라우저 빌드를 따로 내려받아 씁니다. 파이어폭스와 WebKit 은 손본 빌드입니다. 그러므로 이 손본 빌드에서 통과한 테스트가 사용자의 사파리에서도 통과한다는 보장은 없습니다.

테스트가 가끔 깨지는 까닭

코드를 안 바꿨는데 돌릴 때마다 통과와 실패가 오가는 테스트를 불안정한 테스트라고 부릅니다. 브라우저를 쓰는 테스트는 유난히 이렇게 되기 쉽습니다.

웹 화면은 서버 응답을 기다리며 조금씩 그려지기 때문입니다. 테스트가 버튼을 누르려는 순간 버튼이 아직 없을 수 있습니다. 있더라도 움직이는 중이거나 로딩 표시에 가려져 있을 수 있습니다. 그 순간에 누르면 테스트가 실패합니다.

흔한 땜질은 누르기 전에 몇 초씩 잠자게 하는 것입니다. 이러면 매번 그 몇 초를 버립니다. 서버가 평소보다 늦은 날에는 여전히 깨집니다.

누를 수 있을 때까지 기다리는 자동 대기

Playwright 는 클릭 같은 조작을 받으면 바로 누르지 않습니다. 그 요소를 지금 조작할 수 있는지 먼저 확인합니다. 이것을 자동 대기라고 부릅니다.

확인하는 것은 아래와 같습니다.

확인하는 것 안 맞으면 생기는 일
페이지에 붙어 있나 없는 버튼을 누르게 됩니다
화면에 보이나 숨은 버튼을 누르려다 실패합니다
움직임이 멈췄나 버튼이 지나간 빈 곳을 누릅니다
다른 것에 가려지지 않았나 로딩 표시처럼 위에 덮인 것이 눌립니다
켜져 있나 비활성 버튼을 눌러도 아무 일이 안 일어납니다

넷째 줄은 클릭이 그 요소에 닿는지를 봅니다. 요소가 다른 것 밑에 깔려 있으면 누른 좌표에서 맨 위에 있는 것이 대신 눌리기 때문입니다.

조건이 안 맞으면 짧은 간격을 두고 다시 확인합니다. 정해 둔 제한 시간이 지나도 안 맞을 때 비로소 실패로 끝냅니다. 이 제한 시간이 타임아웃입니다.

버튼 하나를 누를 때 테스트 코드와 Playwright 와 브라우저 사이에 오가는 일을 그림으로 보면 아래와 같습니다. 가운데 되풀이 칸이 방금 말한 다시 확인하기입니다.

sequenceDiagram
    participant 테스트 as 테스트 코드
    participant Playwright
    participant 브라우저
    테스트->>Playwright: 로그인 버튼을 눌러라
    loop 조건이 맞을 때까지
        Playwright->>브라우저: 버튼이 보이고 멈춰 있나
        브라우저-->>Playwright: 아직 아니다
    end
    Note over Playwright,브라우저: 제한 시간을 넘기면 여기서 실패로 끝난다
    Playwright->>브라우저: 누른다
    Playwright-->>테스트: 끝났다

앞 코드의 마지막 줄처럼 결과가 맞는지 검사하는 줄을 단언(assertion)이라 합니다. 단언도 같은 방식으로 기다립니다. to_be_visible() 은 글자가 나타날 때까지 다시 확인하다가 제한 시간을 넘기면 실패합니다. 조작 전의 자동 대기와 단언의 자동 대기, 이 둘 덕분에 테스트 코드에 잠자기를 넣지 않아도 됩니다.

요소를 가리키는 로케이터

브라우저는 읽은 페이지의 요소들을 나무 모양으로 엮어 둡니다. 이 나무가 DOM(Document Object Model, 문서 객체 모델)입니다. 테스트는 이 나무에서 누를 요소를 골라야 합니다.

흔히 쓰던 방법은 CSS 선택자입니다. 웹 문서의 꾸밈 규칙을 적는 언어 CSS(Cascading Style Sheets)가 꾸밀 요소를 고를 때 쓰는 표기입니다. 나무 안의 위치나 요소에 붙인 class · id 같은 표시로 요소를 고릅니다. 화면 구조를 조금만 바꿔도 위치가 달라져서 선택자가 깨지기 쉽습니다.

로케이터는 요소를 어떻게 찾을지 적어 둔 것입니다. 앞 코드의 get_by_role 과 get_by_label 이 로케이터를 만듭니다. Playwright 는 사람이 보는 기준으로 찾게 권합니다. 「로그인이라고 적힌 버튼」은 화면 구조를 바꿔도 남기 때문입니다.

get_by_role 의 역할은 화면 낭독기 같은 보조 프로그램이 요소를 구분하는 이름표입니다. 버튼 · 링크 · 입력 칸 같은 것이 역할입니다. 역할로 찾으면 보조 프로그램이 이 버튼을 알아보는지도 함께 확인하게 됩니다.

로케이터는 만들 때 요소를 찾지 않습니다. 누르거나 읽을 때마다 새로 찾습니다. 그래서 그 사이 페이지가 다시 그려져도 옛 요소를 붙들고 있다가 실패하는 일이 없습니다.

테스트마다 새로 받는 브라우저 컨텍스트

브라우저 컨텍스트는 브라우저 하나 안에 따로 떼어 둔 사용자 공간입니다. 컨텍스트마다 쿠키와 웹 스토리지를 따로 가집니다. 크롬의 시크릿 창을 하나 새로 연 것을 떠올리면 됩니다.

이것이 필요한 까닭은 테스트끼리 서로 흔적을 남기기 때문입니다. 앞 테스트가 로그인해 둔 쿠키가 남으면 뒤 테스트는 로그인 화면을 못 봅니다. 그러면 결과가 실행 순서에 따라 달라집니다.

flowchart TD
    subgraph B["브라우저 프로세스 하나"]
        subgraph C1["컨텍스트 A · 테스트 1"]
            K1["쿠키 A"]
            P1["페이지"]
        end
        subgraph C2["컨텍스트 B · 테스트 2"]
            K2["쿠키 B"]
            P2["페이지"]
        end
    end

그림의 페이지는 컨텍스트 안에 연 탭 하나입니다. 앞 코드의 page 가 이 탭을 가리킵니다.

그림처럼 브라우저 프로세스 하나 안에 컨텍스트를 여럿 만듭니다. 컨텍스트는 브라우저를 새로 띄우는 것보다 훨씬 가볍게 만들어집니다. 그래서 테스트마다 새 컨텍스트를 하나씩 줍니다. 테스트가 끝나면 그 컨텍스트를 버립니다.

이렇게 테스트끼리 흔적이 안 섞이게 떼어 두는 원칙을 테스트 격리라고 합니다. 앞 테스트가 남긴 쿠키가 뒤 테스트의 결과를 바꾸는 일이 이 원칙으로 막힙니다.

브라우저에 붙는 방식

이 절은 테스트 코드에서 브라우저까지 명령이 어떤 길로 가는지 따라갑니다. 먼저 언어별 라이브러리와 본체가 어떻게 나뉘는지 봅니다. 그다음 본체가 브라우저에 붙는 연결을 봅니다.

Playwright 의 본체는 JavaScript 로 짜여 있습니다. 파이썬 · 자바 · C# 에서도 쓸 수 있습니다. 이 언어들의 판은 본체를 Node.js 프로세스로 따로 띄워 두고 명령을 넘기는 얇은 껍데기입니다.

flowchart TD
    A["테스트 코드 · 파이썬이나 자바"] --> B["Playwright 라이브러리"]
    B -- 명령 --> C["Playwright 본체 · Node.js 프로세스"]
    C -- 연결 하나 --> D["Chromium"]
    C -- 연결 하나 --> E["손본 Firefox"]
    C -- 연결 하나 --> F["손본 WebKit"]

그래서 자바로 테스트를 짜도 Node.js 프로세스가 함께 뜹니다. JavaScript 로 짜면 이 껍데기 없이 본체를 바로 부릅니다.

본체는 브라우저와 연결 하나를 열어 둔 채 명령을 보냅니다. 페이지에서 요청이 나가거나 응답이 오는 일도 브라우저가 그 연결로 알려 옵니다. 그 소식을 받은 본체는 나가는 요청을 중간에서 붙잡아 가짜 응답을 돌려줄 수도 있습니다. 이 기능을 네트워크 가로채기라고 합니다.

같은 일을 하는 오래된 도구 Selenium 은 길이 다릅니다. 브라우저마다 따로 있는 드라이버 프로그램에 명령을 보냅니다. 드라이버가 그 명령을 받아 브라우저를 움직입니다.

이 명령의 모양은 WebDriver 라는 표준 규격이 정합니다. 원래 WebDriver 는 테스트가 명령을 보내고 답을 받는 문답으로 짜여 있습니다. 브라우저 쪽에서 먼저 소식을 보내 오는 길은 없습니다. 이 규격을 거치지 않는 Playwright 는 브라우저가 알려 오는 소식을 연결 하나로 바로 받습니다.

함께 딸려 오는 도구

테스트 러너는 테스트 파일을 찾아 돌리고 결과를 모아 보여주는 프로그램입니다. JavaScript 판에는 Playwright Test 라는 전용 러너가 함께 들어 있습니다. 다른 언어에서는 pytest 나 JUnit 같은 익숙한 러너에 붙여 씁니다.

전용 러너와 함께 쓰는 도구는 아래와 같습니다.

도구 하는 일
병렬 실행 테스트 파일을 여러 작업 프로세스에 나눠 동시에 돌립니다
재시도 실패한 테스트를 정해 둔 횟수만큼 다시 돌려 봅니다
트레이스 뷰어 조작마다 화면 · 네트워크 요청 · 로그를 기록해 두었다가 한 단계씩 되짚어 봅니다
코드 생성기 사람이 브라우저에서 누른 순서를 받아 적어 테스트 코드 초안을 만듭니다
네트워크 가로채기 브라우저가 보내는 요청을 중간에서 잡아 가짜 응답을 돌려줍니다
스크린샷 비교 화면을 찍어 전에 저장해 둔 사진과 픽셀 단위로 견줍니다

트레이스 뷰어는 지속적 통합 서버에서만 가끔 깨지는 테스트를 볼 때 쓸모가 큽니다. 그 서버 화면을 직접 볼 수 없으니 기록을 내려받아 어느 조작에서 멈췄는지 봅니다.

스크린샷 비교는 코드를 고친 뒤 화면 모양이 뜻과 달리 바뀌었는지 잡습니다. 고친 뒤에 멀쩡하던 것이 망가지지 않았는지 다시 확인하는 테스트가 회귀 테스트입니다. 화면 모양을 사진으로 견주는 쪽은 따로 시각적 회귀 테스트라고 부릅니다.

쓰는 곳과 피하는 곳

Playwright 가 맞는 일과 다른 도구가 나은 일을 상황별로 가릅니다.

상황 고르는 것
로그인 · 결제처럼 사용자가 꼭 거치는 흐름을 확인한다 Playwright
화면 모양이 바뀌지 않았는지 본다 Playwright 의 스크린샷 비교
화면을 JavaScript 로 그리는 페이지에서 내용을 긁어 온다 Playwright
함수 하나의 계산을 확인한다 단위 테스트
서버 응답만 확인한다 브라우저 없이 요청을 직접 보내는 테스트
수많은 동시 사용자로 서버를 누른다 부하 테스트 도구
진짜 휴대폰에서의 동작을 본다 실기기 테스트

셋째 줄은 테스트 밖의 쓰임입니다. 서버가 빈 틀만 보내고 브라우저가 JavaScript 로 내용을 채우는 페이지는 문서만 받아서는 내용이 없습니다. 그래서 브라우저로 끝까지 그려 본 뒤 읽는 웹 크롤러가 Playwright 를 씁니다.

아래 넷은 브라우저가 짐이 되거나 모자라는 경우입니다. 함수 하나나 서버 응답만 볼 때 브라우저를 띄우면 느려지기만 합니다.

브라우저 하나는 메모리를 많이 먹어 수천 개를 한꺼번에 띄울 수 없습니다. 그래서 부하를 거는 데는 맞지 않습니다. Playwright 는 휴대폰의 화면 크기와 터치를 흉내 낼 뿐입니다. 그래서 진짜 기기에서 도는 것과 다릅니다.

종단 간 테스트는 느리고 무거워서 개수를 적게 둡니다. 단위 테스트를 가장 많이 두고 위로 갈수록 줄이는 배분을 테스트 피라미드라고 부릅니다. Playwright 테스트는 그 꼭대기에 섭니다.

관련 항목

Playwright 가 조종하는 브라우저와 엔진

브라우저 · Chromium · Firefox · WebKit · Safari · 렌더링 엔진 · Blink · Gecko · 헤드리스 브라우저

Playwright 로 돌리는 테스트 종류

종단 간 테스트 · 회귀 테스트 · 시각적 회귀 테스트 · 크로스 브라우저 테스트 · 인수 테스트 · 스모크 테스트

Playwright 를 이루는 구성 요소

로케이터 · 자동 대기 · 브라우저 컨텍스트 · 트레이스 뷰어 · 테스트 러너 · 네트워크 가로채기

Playwright 와 같은 역할을 두고 겨루는 도구

Selenium · WebDriver · Puppeteer · Cypress · WebDriver BiDi

Playwright 를 붙여 쓰는 언어와 테스트 러너

JavaScript · TypeScript · Node.js · Python · Java · pytest · JUnit

Playwright 테스트에서 자주 나는 문제

불안정한 테스트 · 경쟁 상태 · 타임아웃 · 테스트 격리

Playwright 가 브라우저에서 다루는 웹 요소

DOM · CSS 선택자 · 접근성 트리 · 쿠키 · 웹 스토리지

Playwright 를 테스트 밖에서 쓰는 작업

웹 크롤러 · 웹 스크래핑 · 클라이언트 사이드 렌더링 · 단일 페이지 애플리케이션

Playwright 대신 고르는 테스트 방식

단위 테스트 · 통합 테스트 · 부하 테스트 · 실기기 테스트

Playwright 테스트를 돌리는 자동화 환경

지속적 통합 · GitHub Actions · Docker

Playwright 가 속하는 상위 분류

브라우저 자동화 · QA와 테스트 · 테스트 자동화 · 테스트 피라미드

다른 이름: 플레이라이트