Skip to content

핵심 API 레퍼런스

Playwright의 특징은 **"기본적으로 스마트하고, 소음은 줄인다"**는 점입니다. Selenium에서 수동으로 작성해야 했던 많은 대기 로직이 자동으로 처리됩니다. 이 이장에서는 가장 자주 사용되는 API를 이해하기 쉽게 설명하며, JS와 Python 예시를 함께 제공합니다.


1. 페이지 탐색 (Page Navigation)

javascript
// JavaScript
await page.goto('https://example.com');
await page.goto('https://example.com', { waitUntil: 'networkidle' });
python
# Python
page.goto("https://example.com")
page.goto("https://example.com", wait_until="networkidle")

waitUntil 매개변수 설명:

의미권장 시나리오
'commit'서버의 응답 헤더를 받으면 완료로 간주합니다.거의 사용되지 않음.
'domcontentloaded'DOM 트리가 생성되었습니다.빠른 탐색; 이미지 등에 의존하지 않는 경우.
'load'모든 리소스(이미지, CSS)가 로드되었습니다.중간 난이도 (기본값).
'networkidle'최소 500ms 동안 네트워크 활동이 없습니다.SPA 웹사이트; 전체 로드가 필요한 경우.

기타 탐색 메서드:

javascript
await page.goBack();     // 뒤로 가기
await page.goForward();  // 앞으로 가기
await page.reload();     // 새로고침

2. Locator: 요소 위치 지정 (Playwright의 핵심 장점)

IMPORTANT

Playwright의 Locator는 구식 find_element보다 혁신적으로 개선된 방식입니다.

  • 자동 대기: 요소가 나타나고, 보이고, 클릭 가능해질 때까지 자동으로 기다립니다.
  • 자동 재시도: 작업이 실패하면(예: 요소가 가려짐) 자동으로 재시도합니다.
  • 의미론적 검색: 역할(Role), 라벨, 텍스트, 플레이스홀더로 검색하여 취약한 CSS 선택자에 대한 의존도를 낮춥니다.

자주 사용하는 위치 지정 메서드

javascript
// JavaScript —— 권장 우선순위 (높은 순서대로)

// 1. 역할(Role)로 찾기 (가장 권장; 의미가 명확함)
page.getByRole('button', { name: '로그인' })
page.getByRole('textbox', { name: '계정' })
page.getByRole('link', { name: '가입하기' })

// 2. 텍스트 내용으로 찾기
page.getByText('지금 구매')
page.getByText('지금 구매', { exact: true })  // 정확히 일치

// 3. 플레이스홀더(Placeholder)로 찾기
page.getByPlaceholder('전화번호 입력')

// 4. 라벨(Label) 텍스트로 찾기 (양식 시나리오에서 탁월)
page.getByLabel('이메일 주소')

// 5. CSS 선택자로 찾기 (전통적인 방식)
page.locator('#username')
page.locator('.btn-primary')
page.locator('button[type="submit"]')

// 6. XPath로 찾기
page.locator('//input[@name="password"]')
python
# Python (메서드 명칭 동일, camelCase → snake_case)
page.get_by_role("button", name="로그인")
page.get_by_text("지금 구매")
page.get_by_placeholder("전화번호 입력")
page.get_by_label("이메일 주소")
page.locator("#username")

여러 요소 찾기 (Locator 리스트 반환)

javascript
// 일치하는 모든 요소 가져오기
const items = page.locator('.product-item');
const count = await items.count();         // 전체 개수
const first = items.first();              // 첫 번째
const last  = items.last();               // 마지막
const third = items.nth(2);              // 세 번째 (0부터 시작)

// 필터링 (강력한 필터 메서드)
const buttons = page.getByRole('button');
await buttons.filter({ hasText: '구매' }).click();  // "구매" 텍스트를 포함한 버튼만 클릭

3. 자동 대기 메커니즘 (sleep과 작별하기)

Playwright의 Locator 작업(click, fill, type 등)은 실행 전에 요소가 다음 조건들을 충족할 때까지 자동으로 대기합니다.

  • 요소가 DOM에 존재함.
  • 요소가 보임 (숨겨지지 않음).
  • 요소가 안정적임 (애니메이션 중에 움직이지 않음).
  • 요소가 클릭 가능함 (차단되지 않음).
javascript
// 그냥 클릭하세요. Playwright가 클릭 가능할 때까지 기다려 줍니다.
await page.getByRole('button', { name: '제출' }).click();
// Selenium에서의 상응하는 코드:
// wait.until(EC.element_to_be_clickable(...)); element.click();

수동 대기 (특수한 경우에만 사용)

javascript
// 특정 선택자가 나타날 때까지 대기
await page.waitForSelector('.success-message');

// URL이 변경될 때까지 대기
await page.waitForURL('**/dashboard');

// 특정 함수가 true를 반환할 때까지 대기
await page.waitForFunction(() => document.querySelector('#result')?.textContent === 'Done');

// 네트워크 응답 대기 (버튼 클릭 후 API 트리거 시 자주 사용)
const [response] = await Promise.all([
  page.waitForResponse(resp => resp.url().includes('/api/login')),
  page.getByRole('button', { name: '로그인' }).click()
]);
const data = await response.json();

4. 양식(Form) 작업

javascript
// 텍스트 입력 (지운 후 채우기)
await page.getByLabel('이메일').fill('user@example.com');

// 실제 인간의 타이핑 시뮬레이션 (글자 하나씩 입력)
await page.getByLabel('비밀번호').pressSequentially('MyPassword123', { delay: 80 });

// 입력 필드 지우기
await page.getByPlaceholder('검색').clear();

// 체크박스 체크/해제
await page.getByRole('checkbox', { name: '로그인 상태 유지' }).check();
await page.getByRole('checkbox', { name: '로그인 상태 유지' }).uncheck();

// 드롭다운 선택
await page.getByRole('combobox', { name: '국가' }).selectOption('CN');
await page.getByRole('combobox').selectOption({ label: '한국' });   // 텍스트로 선택

// 파일 업로드
await page.getByLabel('업로드').setInputFiles('path/to/file.jpg');

5. 키보드 및 마우스 작업

javascript
// 키보드 키 (주요 단축키)
await page.keyboard.press('Enter');
await page.keyboard.press('Control+A');    // 전체 선택
await page.keyboard.press('Control+C');    // 복사
await page.keyboard.press('Escape');

// 마우스 작업
await page.mouse.move(100, 200);           // 마우스 이동
await page.mouse.click(100, 200);         // 해당 좌표 클릭
await page.mouse.dblclick(100, 200);      // 더블 클릭
await page.mouse.wheel(0, 300);           // 아래로 300px 스크롤

// 호버 (마우스 올리기, 호버 메뉴 트리거)
await page.getByRole('menuitem', { name: '더 보기' }).hover();

6. 요소 정보 검색

javascript
// 텍스트 내용 가져오기
const text = await page.getByRole('heading').innerText();

// 속성 값 가져오기
const href = await page.locator('a.link').getAttribute('href');
const val  = await page.locator('input#amount').inputValue();  // 입력값

// 상태 판별
const isVisible = await page.locator('#modal').isVisible();
const isEnabled = await page.getByRole('button').isEnabled();
const isChecked = await page.getByRole('checkbox').isChecked();

7. 네트워크 가로채기 및 모킹 (독보적인 장점)

Playwright의 가장 강력한 기능 중 하나는 브라우저를 떠나기 전의 요청을 가로채고 수정할 수 있다는 점입니다.

API 응답 가로채기 및 모킹

javascript
// 특정 API 요청을 가로채고 모의 데이터 반환
await page.route('**/api/user/info', async route => {
  await route.fulfill({
    status: 200,
    contentType: 'application/json',
    body: JSON.stringify({ name: 'Mbbrowser 테스트 사용자', vip: true })
  });
});

특정 요청 완료 대기

javascript
// 시나리오: "더 보기" 클릭 후, 콘텐츠를 읽기 전에 데이터 API가 반환될 때까지 대기함.
const [response] = await Promise.all([
  page.waitForResponse(resp => resp.url().includes('/api/products') && resp.status() === 200),
  page.getByRole('button', { name: '더 보기' }).click()
]);
const products = await response.json();
console.log(`${products.length}개의 상품을 가져왔습니다.`);

광고/불필요한 리소스 차단 (페이지 성능 향상)

javascript
await page.route('**/*.{png,jpg,gif,webp,svg}', route => route.abort()); // 이미지 차단
await page.route('**/{ads,analytics,tracker}**', route => route.abort()); // 광고 차단

8. 쿠키 작업

javascript
// 모든 쿠키 가져오기
const cookies = await context.cookies();
console.log(cookies);

// 쿠키 주입 (웹 페이지를 열기 전에 설정하는 것이 좋음)
await context.addCookies([
  { name: 'token', value: 'abc123', domain: '.example.com', path: '/' }
]);

// 모든 쿠키 삭제
await context.clearCookies();

9. 멀티 탭 작업

javascript
// 새 탭이 열리는 이벤트 수신
const [newPage] = await Promise.all([
  context.waitForEvent('page'),            // 새 탭이 나타날 때까지 대기
  page.getByRole('link').click()           // 새 탭을 여는 작업 실행
]);
await newPage.waitForLoadState();
console.log('새 탭 타이틀:', await newPage.title());

// 열려 있는 모든 탭 가져오기
const allPages = context.pages();
console.log(`전체 탭 개수: ${allPages.length}`);

// 수동으로 새 탭 열기
const anotherPage = await context.newPage();
await anotherPage.goto('https://www.google.com');

10. iframe 작업

javascript
// iframe을 찾아 그 안에서 상호작용
const iframe = page.frameLocator('iframe#loginFrame');
await iframe.getByLabel('사용자 아이디').fill('my_user');
await iframe.getByRole('button', { name: '로그인' }).click();

11. 스크린샷 및 PDF

javascript
// 현재 화면 스크린샷
await page.screenshot({ path: 'screenshot.png' });

// 전체 페이지 스크린샷 (스크롤 콘텐츠 포함)
await page.screenshot({ path: 'full-page.png', fullPage: true });

// 특정 요소 스크린샷
await page.locator('#product-card').screenshot({ path: 'product.png' });

// PDF 생성 (Chromium 전용)
await page.pdf({ path: 'report.pdf', format: 'A4' });

12. JavaScript 실행

javascript
// 페이지 내부에서 JS 실행 및 반환값 가져오기
const title = await page.evaluate(() => document.title);

// 페이지 측 JS에 매개변수 전달
const itemCount = await page.evaluate(
  selector => document.querySelectorAll(selector).length,
  '.product-item'
);

// DOM 직접 조작: 차단된 요소 강제 클릭
await page.evaluate(selector => {
  document.querySelector(selector).click();
}, '#hidden-btn');

TIP

API 사용법을 익히셨나요? 다음 장 실전 사례 가이드에서는 자동 로그인, 스크래핑, 네트워크 가로채기, 동시 실행 등 실무에서 즉시 활용할 수 있는 5가지 템플릿을 제공합니다. 바로 복사해서 사용해 보세요!