Playwright는 웹 브라우저를 위한 강력한 자동화 프레임워크로, 개발자들이 웹 애플리케이션에 대한 견고하고 효율적인 테스트를 작성할 수 있게 해줍니다. Playwright의 주요 특징 중 하나는 비동기적 특성으로, 이는 여러 작업을 동시에 처리할 수 있도록 합니다. 이러한 비동기적 행동의 핵심은 await
키워드로, 이는 Playwright 스크립트에서 비동기 작업의 흐름을 관리하는 데 중요한 역할을 합니다.
비동기 프로그래밍의 기초
Playwright의 await
의 구체적인 내용에 들어가기 전에, JavaScript의 비동기 프로그래밍의 기초를 이해하는 것이 중요합니다.
전통적인 동기 프로그래밍에서는 작업이 하나씩 순차적으로 실행되며, 각 작업이 완료될 때까지 다음 작업의 실행이 차단됩니다. 이로 인해 네트워크 요청이나 파일 작업과 같이 시간이 많이 걸리는 작업을 처리할 때 성능 문제를 일으킬 수 있습니다.
비동기 프로그래밍을 통해 여러 작업을 이전 작업이 완료될 때까지 기다리지 않고 시작할 수 있습니다. 이러한 논블로킹 접근법은 특히 I/O 작업이나 외부 자원이 포함된 시나리오에서 성능과 응답성을 개선합니다.
Playwright란?
이제 await
와 그 역할에 대해 살펴보기 전에, Playwright가 무엇인지 잠깐 살펴보겠습니다. Playwright는 Microsoft에서 웹 브라우저 자동화를 위해 개발한 오픈 소스 Node.js 라이브러리입니다. Chromium, Firefox 및 WebKit을 지원하여 서로 다른 브라우저에서 웹 애플리케이션을 테스트하는 데 유용한 도구입니다.
Playwright는 개발자와 테스터가 높은 충실도와 신뢰성 있는 테스트를 작성할 수 있도록 합니다. 여러 탭, iframe 및 심지어 네트워크 요청을 처리하는 능력으로 특히 알려져 있습니다. 그러나 그 잠재력을 최대한 활용하려면 비동기 프로그래밍과 await
키워드를 이해하는 것이 필수적입니다.
프라미스와 Async/Await
JavaScript는 비동기 작업을 처리하기 위해 프라미스를 사용합니다. 프라미스는 즉시 이용할 수 없을 수도 있는 값을 나타내지만, 미래의 어느 시점에 해결될 것입니다. ECMAScript 2017에서 도입된 async/await
구문은 프라미스를 다루는 보다 읽기 쉽고 관리하기 쉬운 방법을 제공합니다.
async
함수는 항상 프라미스를 반환합니다.await
키워드는async
함수 내부에서만 사용할 수 있습니다.await
는 프라미스가 해결될 때까지async
함수의 실행을 중단합니다.
Playwright에서 await
의 역할
Playwright에서 많은 작업은 본래 비동기적입니다. 여기에는 페이지로의 탐색, 요소와의 상호작용 및 특정 조건이 충족될 때까지 기다리는 작업이 포함됩니다. await
키워드는 이러한 비동기 작업을 효과적으로 처리하기 위해 Playwright 스크립트에서 광범위하게 사용됩니다.
다음은 Playwright에서 await
가 수행하는 작업입니다:
실행 중단: await
가 Playwright 작업이나 단언문 앞에 사용될 때, 해당 작업이나 단언문이 완료될 때까지 스크립트의 실행을 중단합니다.
프라미스 해결: Playwright 메서드에서 반환된 프라미스가 해결될 때까지 기다려 주어진 값을 직접 작업할 수 있게 해줍니다.
적절한 순서 보장: 작업의 올바른 순서를 유지하여 한 작업이 완료된 후 다음 작업으로 넘어갈 수 있도록 도와줍니다.
오류 처리: 기다리는 프라미스가 거부되면 await
는 예외를 발생시켜, 이를 효과적으로 캐치하고 처리할 수 있도록 해줍니다.
Playwright에서 await
의 실용적인 예시
이제 Playwright 스크립트에서 await
가 사용되는 몇 가지 일반적인 시나리오를 살펴보겠습니다:
1. 탐색
test('페이지 이동', async ({ page }) => {
await page.goto('https://example.com');
// 스크립트가 페이지가 로드될 때까지 대기합니다.
});
이 예에서 await
는 테스트가 계속되기 전에 탐색이 완료되도록 보장합니다.
2. 요소와의 상호작용
test('버튼 클릭', async ({ page }) => {
await page.click('#submit-button');
// 스크립트가 클릭 작업이 완료될 때까지 대기합니다.
});
여기서 await
는 클릭 작업이 완전히 실행되도록 보장합니다.
3. 요소 대기
test('요소가 보일 때까지 대기', async ({ page }) => {
await page.waitForSelector('#dynamic-content');
// 요소가 보일 때까지 스크립트를 일시 중지합니다.
});
이 경우 await
는 지정된 요소가 페이지에 나타날 때까지 스크립트를 일시 중지합니다.
4. 단언
test('페이지 제목 확인', async ({ page }) => {
await expect(page).toHaveTitle('예상 제목');
// 단언이 비동기적으로 평가됩니다.
});
await
는 단언과 함께 사용되어 적절히 평가되도록 보장하며, 조건이 충족될 때까지 기다리거나 그렇지 않을 경우 타임아웃됩니다.
Playwright에서 await
의 중요성
Playwright에서 await
를 올바르게 사용하는 것은 여러 가지 이유로 중요합니다:
동기화: 비동기 작업을 동기화하여 레이스 조건을 방지하고, 작업이 의도한 순서대로 수행되도록 도와줍니다.
신뢰성: 작업이 완료될 때까지 기다림으로써 await
는 테스트를 보다 신뢰할 수 있게 만들고 덜 발생할 수 있도록 합니다.
오류 처리: 적절한 오류 전파를 가능하게 하여 테스트에서 문제를 식별하고 디버깅하기 쉽게 만들어 줍니다.
가독성: await
는 비동기 코드를 더 읽기 쉽고 이해하기 쉽게 만들어주며, 비동기 코드를 보다 선형적인 동기적인 방식으로 작성할 수 있습니다.
일반적인 실수와 모범 사례
await
는 강력하지만, 피해야 할 일반적인 실수와 따라야 할 모범 사례가 있습니다:
1. await
사용을 잊기
가장 일반적인 실수 중 하나는 비동기 작업 앞에 await
를 사용하는 것을 잊는 것입니다. 이로 인해 예기치 않은 행동과 레이스 조건이 발생할 수 있습니다.
잘못된:
test('잘못된 사용', async ({ page }) => {
page.click('#button'); // 이는 잘못됨
expect(page.locator('#result')).toBeVisible();
});
올바른:
test('올바른 사용', async ({ page }) => {
await page.click('#button');
await expect(page.locator('#result')).toBeVisible();
});
2. await
과다 사용
비동기 작업에 await
를 사용하는 것이 중요하지만, 과다 사용하면 불필요한 순차 실행을 초래하여 비동기 프로그래밍의 이점을 감소시킬 수 있습니다.
비효율적:
test('순차 실행', async ({ page }) => {
await page.fill('#field1', 'value1');
await page.fill('#field2', 'value2');
await page.fill('#field3', 'value3');
});
더 효율적:
test('병렬 실행', async ({ page }) => {
const [field1, field2, field3] = await Promise.all([
page.fill('#field1', 'value1'),
page.fill('#field2', 'value2'),
page.fill('#field3', 'value3')
]);
});
3. 비동기 함수 외부에서 await
사용하기
await
는 async
함수 내부에서만 사용할 수 있다는 점을 기억하세요. 이를 외부에서 사용하면 구문 오류가 발생합니다.
잘못된:
test('잘못된 사용', ({ page }) => {
await page.goto('https://example.com'); // 이는 오류를 발생시킵니다
});
올바른:
test('올바른 사용', async ({ page }) => {
await page.goto('https://example.com');
});
4. 오류 처리하기
await
를 사용할 때는 항상 try-catch 블록이나 .catch()
메서드를 사용해 잠재적인 오류를 처리하세요.
test('오류 처리', async ({ page }) => {
try {
await page.click('#non-existent-button');
} catch (error) {
console.error('오류가 발생했습니다:', error);
}
});
Playwright에서 await
의 고급 사용법
Playwright에 대한 이해가 깊어질수록 await
가 중요한 역할을 하는 더 고급 시나리오를 만나게 될 것입니다:
1. 사용자 정의 단언
사용자 정의 단언을 생성할 때, 단언 논리 내에서 비동기 작업을 처리하기 위해 await
를 사용할 필요가 있을 수 있습니다.
expect.extend({
async toHaveCorrectApiResponse(page, expectedResponse) {
const response = await page.evaluate(() => fetchApiData());
return {
pass: JSON.stringify(response) === JSON.stringify(expectedResponse),
message: () => `예상한 API 응답이 ${expectedResponse}와 일치해야 합니다.`
};
}
});
test('사용자 정의 단언', async ({ page }) => {
await expect(page).toHaveCorrectApiResponse({ status: 'success' });
});
2. 여러 프라미스 처리하기
복잡한 시나리오에서는 여러 프라미스를 동시에 처리해야 할 수도 있습니다. 이런 경우에 Promise.all()
메서드와 await
를 조합하는 것이 유용합니다.
test('여러 프라미스 처리', async ({ page }) => {
const [navigationPromise, dialogPromise] = await Promise.all([
page.waitForNavigation(),
page.waitForEvent('dialog'),
page.click('#submit-button')
]);
await dialogPromise.accept();
await navigationPromise;
});
3. 조건부 대기
가끔 특정 조건이 발생할 수도 있고 발생하지 않을 수도 있는 경우가 있습니다. 이런 시나리오를 처리하기 위해 try-catch
와 함께 시간 초과를 사용할 수 있습니다.
test('조건부 대기', async ({ page }) => {
try {
await page.waitForSelector('#popup', { timeout: 5000 });
await page.click('#close-popup');
} catch (error) {
// 팝업이 나타나지 않았습니다, 테스트를 계속 진행합니다.
}
});
Playwright와 Apidog 통합하기
Playwright와 Apidog를 통합하면 테스트 수준을 한 단계 끌어올릴 수 있습니다. Apidog는 여러분의 Playwright 테스트를 완벽하게 보완해줄 수 있는 강력한 API 설계, 문서화 및 테스트 도구를 제공합니다. 이는 여러분의 웹 애플리케이션이 프론트엔드와 백엔드 모두 올바르게 작동하도록 보장합니다.
Apidog로 API 보내기
작동하는 API와 React 프론트엔드가 준비되었으니, 이제 API를 테스트할 차례입니다. Apidog는 이를 위한 환상적인 도구입니다.
1단계: Apidog를 열고 새 요청을 생성합니다.

2단계: 테스트 편집기에서 API 엔드포인트의 URL을 입력하고, HTTP 메서드를 선택하며, 필요한 모든 헤더, 파라미터 또는 본문 데이터를 추가합니다. 예를 들어, 앞서 만든 간단한 메시지를 반환하는 경로를 테스트할 수 있습니다:

3단계: 전송 버튼을 클릭하고 테스트 결과를 확인합니다. API의 상태 코드, 응답 시간 및 응답 본문을 확인할 수 있어야 합니다. 예를 들어, 다음과 같은 결과를 볼 수 있습니다:

Apidog는 API 테스트를 위해 훌륭한 도구로, 여러분의 웹 서비스의 품질, 신뢰성 및 성능을 보장하는 데 도움을 줄 수 있습니다. 또한, 코드를 작성하거나 소프트웨어를 설치할 필요 없이 API 테스트를 할 수 있어 시간과 노력을 절약할 수 있습니다. 단순히 웹 브라우저를 사용하고 Apidog의 사용자 친화적인 인터페이스와 기능을 즐기면 됩니다.
결론
Playwright에서 await
가 수행하는 기능을 이해하는 것은 효과적이고 신뢰할 수 있는 테스트를 작성하는 데 중요합니다. async/await를 활용함으로써 테스트 스크립트의 각 단계가 올바른 순서로 실행되도록 보장하여 잠재적인 문제를 방지하고 테스트 유지 관리를 개선할 수 있습니다.
테스트 도구 키트를 더욱 향상시키기 위해 Apidog를 무료로 다운로드하는 것을 잊지 마세요. Playwright와 Apidog가 결합되면 프론트엔드와 백엔드 테스트 모두를 위한 종합적인 솔루션을 갖출 수 있습니다.