Playwright 로케이터 가이드: getByRole, getByText, getByLabel, CSS & XPath

발행: (2026년 2월 9일 오후 05:46 GMT+9)
14 분 소요
원문: Dev.to

Source: Dev.to

Playwright Locators Guide: getByRole, getByText, getByLabel, CSS, XPath

Playwright는 다양한 로케이터 전략을 제공하여 테스트를 더 읽기 쉽고 유지보수하기 쉽게 만들어 줍니다. 이 가이드에서는 가장 많이 사용되는 로케이터인 getByRole, getByText, getByLabel과 전통적인 CSS 및 XPath 선택자를 비교하고, 언제 어떤 로케이터를 사용해야 하는지에 대한 모범 사례를 제시합니다.


📖 목차

  1. 왜 로케이터가 중요한가?
  2. getByRole
  3. getByText
  4. getByLabel
  5. CSS 선택자
  6. XPath 선택자
  7. 베스트 프랙티스
  8. 마무리

왜 로케이터가 중요한가?

  • 가독성: page.getByRole('button', { name: 'Submit' })와 같이 의미가 명확한 로케이터는 테스트 코드를 읽는 사람에게 UI 의도를 바로 전달합니다.
  • 안정성: 역할(role)이나 라벨(label)은 UI가 리팩터링될 때도 변하지 않는 경우가 많아 테스트가 깨지는 위험을 줄여줍니다.
  • 접근성: getByRole은 접근성 트리를 활용하므로, 접근성 검증도 자연스럽게 수행됩니다.

getByRole

사용법

// 버튼 역할을 가진 요소를 찾는다.
await page.getByRole('button', { name: 'Submit' }).click();

// 헤딩 레벨 2를 찾는다.
await expect(page.getByRole('heading', { level: 2 })).toHaveText('Overview');

주요 옵션

옵션설명
name요소의 접근성 이름(라벨, 텍스트 등)
selected선택된 상태 여부 (true/false)
checked체크박스/라디오 버튼의 체크 여부
level헤딩(heading)일 경우 레벨(1~6) 지정

언제 사용해야 할까?

  • 버튼, 링크, 체크박스 등 명확한 ARIA 역할을 가진 요소.
  • 접근성 테스트와 동시에 UI 동작을 검증하고 싶을 때.

getByText

사용법

// 정확히 일치하는 텍스트를 가진 요소
await page.getByText('Welcome to Playwright').click();

// 정규식으로 부분 매칭
await page.getByText(/error \d+/).first().waitFor();

옵션

옵션설명
exacttrue이면 정확히 일치, false이면 부분 일치 (기본값: true)
ignoreCase대소문자 무시 여부
has자식 요소에 대한 추가 로케이터 지정

언제 사용해야 할까?

  • 텍스트 기반 UI(예: 알림, 토스트 메시지, 리스트 아이템)에서 빠르게 요소를 찾고 싶을 때.
  • 역할이 명확하지 않거나, 텍스트가 유일한 경우.

getByLabel

사용법

// 라벨 텍스트와 연결된 입력 필드
await page.getByLabel('Email address').fill('user@example.com');

// 라벨이 복수인 경우
await page.getByLabel('Password', { exact: false }).fill('secret');

옵션

옵션설명
exact라벨 텍스트와 정확히 일치시킬지 여부
includeHidden숨겨진 라벨도 포함할지 여부 (기본: false)

언제 사용해야 할까?

  • <label for="..."> 혹은 aria-label/aria-labelledby가 연결된 폼 요소.
  • 폼 검증, 입력값 자동화 등에 최적.

CSS 선택자

사용법

// 클래스와 속성 조합
await page.locator('.nav-item[data-active="true"]').click();

// 자식/후손 선택
await page.locator('ul > li:first-child').hover();

장점

  • 유연성: 복잡한 구조도 한 줄로 표현 가능.
  • 성능: 브라우저 엔진이 최적화된 방식으로 처리.

단점

  • UI가 리팩터링될 때 클래스명이나 구조가 바뀌면 깨질 위험이 있음.
  • 접근성 정보를 활용하지 않으므로, 가독성이 떨어질 수 있음.

XPath 선택자

사용법

// 텍스트 기반 XPath
await page.locator('//button[text()="Delete"]').click();

// 복잡한 조건
await page.locator('//input[@type="email" and @required]').fill('test@example.com');

장점

  • 강력한 탐색: 부모/형제/자식 관계를 자유롭게 지정 가능.
  • 텍스트와 속성 혼합: 복합 조건을 한 번에 표현.

단점

  • 가독성이 낮고, 유지보수가 어려움.
  • 대부분의 경우 CSS 혹은 Playwright 전용 로케이터(getBy*)가 더 직관적.

베스트 프랙티스

상황권장 로케이터
버튼, 링크, 체크박스 등 명확한 역할getByRole
라벨이 연결된 폼 입력getByLabel
단순 텍스트 매칭getByText
복잡한 UI 구조(예: 그리드, 테이블)CSS 선택자
매우 정교한 트리 탐색이 필요할 때XPath (가능하면 피하기)
접근성 테스트와 동시에 UI 검증getByRole + expect

추가 팁

  1. 가능하면 exact: false 대신 정규식을 사용해 부분 매칭을 명시적으로 제어합니다.
  2. await expect(locator).toBeVisible() 로 가시성을 먼저 검증하면 flaky 테스트를 방지할 수 있습니다.
  3. page.getByRolehidden: true 옵션을 사용하면 화면에 보이지 않는 요소(예: 모달 내부)도 찾을 수 있습니다.

마무리

Playwright는 다양한 로케이터를 제공함으로써 테스트 작성자를 읽기 쉽고, 유지보수하기 쉬운 코드를 작성하도록 돕습니다.

  • UI가 접근성을 고려해 구현돼 있다면 getByRole, getByLabel을 최우선으로 사용하세요.
  • 텍스트 기반 검증이 필요하면 getByText를 활용하고,
  • 복잡한 구조에서는 CSS 선택자를, 정말 복잡한 경우에만 XPath를 고려하면 됩니다.

올바른 로케이터를 선택하면 테스트가 더 빠르고 안정적이며, 팀 전체가 코드를 이해하기 쉬워집니다. Happy testing! 🚀

Introduction

Flakiness는 테스트 신뢰성을 잠식하는 조용한 살인자입니다. 어느 순간에는 통과하고 다음 순간에는 실패하는 테스트 스위트는 신뢰를 무너뜨립니다.

대부분의 테스트 불안정성의 핵심은 부실한 요소 선택에 있습니다. 테스트가 div.btn-primary 로 버튼을 클릭하고, 누군가 CSS를 업데이트하면 실패합니다. DOM 내 위치로 요소를 찾았다가 새로운 기능이 위에 콘텐츠를 추가하면 깨집니다. 데이터 로드에 정확히 2 초를 기다리다 API가 느려지면 타임아웃됩니다. 모든 UI 업데이트가 테스트 실패의 연쇄 반응을 일으키며, 유지보수를 풀타임 작업으로 만들죠.

Playwright locators는 이러한 근본적인 문제를 다른 접근 방식으로 해결합니다: 타이밍 문제를 없애는 자동 대기, 모호한 선택을 방지하는 엄격한 매칭, 구현 변경에도 안정적인 사용자‑지향 선택자. 깨지기 쉬운 CSS 선택자와 XPath 쿼리 대신, Playwright는 사용자가 하는 방식대로, 역할(role), 텍스트, 라벨을 통해 요소를 찾도록 권장합니다.

이 가이드는 getByRole 과 같은 강력히 권장되는 사용자‑지향 선택자부터 CSS와 XPath와 같은 필수적인 대체 방법까지, Playwright locators의 전체 스펙트럼을 탐구합니다. 이를 통해 단순히 동작하는 수준을 넘어 진정으로 신뢰할 수 있는 테스트 자동화 스위트를 구축할 수 있습니다.

Playwright Locator Strategy: Think Like a User, Not the DOM

전통적인 테스트 프레임워크는 컴퓨터처럼 생각하도록 강요합니다: DOM 내 위치, CSS 클래스, 혹은 내부 ID로 요소를 찾는 것이죠. 하지만 애플리케이션은 끊임없이 변합니다. 스타일 업데이트로 클래스가 바뀌고, 프레임워크 업그레이드로 DOM 구조가 이동하며, 빌드마다 ID가 재생성됩니다. 테스트가 이러한 요소들에 과도하게 결합돼 있다면, UI가 조금만 바뀌어도 연쇄적인 실패가 발생합니다.

가장 흔한 로케이터 불안정성 원인은 다음과 같습니다:

  • Timing issues – 요소가 아직 준비되지 않았을 때 상호작용을 시도하는 경우. 현대 웹 앱은 동적으로 동작하며, 컴포넌트가 비동기적으로 렌더링되고, API에서 데이터를 로드하고, 애니메이션으로 요소 위치가 바뀝니다. 버튼은 DOM에 존재하지만 데이터가 로드될 때까지 비활성화될 수 있고, 모달은 존재하지만 아직 화면에 완전히 나타나지 않을 수 있습니다.
  • Ambiguous selections – 선택자와 일치하는 요소가 여러 개 존재하는 경우. 특히 리스트, 그리드, 반복되는 컴포넌트에서 문제가 됩니다. 로컬에서는 “Delete” 버튼이 하나라 테스트가 통과되지만, 스테이징에서는 버튼이 스무 개라 실패할 수 있습니다.
  • Implementation coupling – 사용자에게 보이는 동작이 아니라 구현 세부 사항에 묶인 선택자. div.btn-primary-new-style 로 선택한다면 구현을 테스트하는 것이지 사용자 경험을 테스트하는 것이 아닙니다. 리팩터링이 있을 때마다 테스트 유지보수가 부담이 됩니다.
  • Dynamic content – 데이터, 사용자 상태, 시간 등에 따라 변하는 요소. 사용자 권한에 따라 다른 위젯을 보여주는 대시보드, 단계적으로 필드를 드러내는 폼, 실시간으로 업데이트되는 콘텐츠 등이 해당됩니다.

Playwright는 이러한 문제들을 현대적이고 의견이 반영된 요소 선택 방식으로 해결합니다. DOM을 직접 쿼리하는 전통적인 방법과 달리, Playwright 로케이터는 자동화 테스트를 작성하는 방식을 근본적으로 바꾸는 패러다임을 제공합니다.

Playwright 자동 대기 설명

테스트가 불안정해지는 가장 흔한 원인 중 하나는 타이밍입니다. 애플리케이션이 동적으로 동작하고 요소가 비동기적으로 렌더링·하이드레이션·활성화될 때, 기존 테스트 스크립트는 버튼이 실제로 인터랙티브해지기 전에 클릭을 시도해 실패할 수 있습니다.

Playwright의 자동 대기 메커니즘이 이를 해결합니다. 로케이터에 대해 동작을 수행하면 Playwright는 해당 동작을 실행하기 전에 일련의 검사를 자동으로 수행합니다. Playwright는 로케이터가 정확히 하나의 보이는 요소로 해결되고, 안정적이며, 이벤트를 받을 수 있고, 활성화된 경우(fill인 경우는 편집 가능)일 때만 동작을 실행하도록 자동으로 대기합니다.

test('auto-waiting prevents timing issues', async ({ page }) => {
  // 명시적인 대기가 필요 없음
  await page.goto('/dashboard');

  // Playwright가 버튼이 작동 가능해질 때까지 대기
  await page.getByRole('button', { name: 'Load Report' }).click();

  // 동적 콘텐츠 로딩이 있더라도
  await expect(page.getByRole('table', { name: 'Sales Data' }))
    .toBeVisible();
});
0 조회
Back to Blog

관련 글

더 보기 »

Playwright Codegen

Playwright & Codegen – .NET에서 통합 테스트를 기록하는 방법 Playwright는 시장에서 가장 완전한 엔드‑투‑엔드 테스트 라이브러리 중 하나이며, 주요 …