콘텐츠로 이동

수동 설정

대부분은 init을 실행하는 편이 좋습니다. 아래 모든 파일을 대신 작성해 줍니다. 이 페이지는 init이 생성하는 내용의 참조 자료이므로, 직접 연결하거나 코드 생성을 버리거나 각 부분을 이해하는 데 쓸 수 있습니다.

서버와 브라우저가 모두 API를 호출하는 Next.js 및 유사 프레임워크용입니다. 두 기록 메커니즘을 함께 사용하세요. 작동 원리를 참조하세요.

프록시는 테스트 실행 동안 앱 옆에서 시작하는 가벼운 프로세스입니다(아래처럼 스크립트를 통해, 또는 Playwright의 webServer로). 배포하거나 유지 관리할 인프라가 아닙니다. 전체 설정은 이렇습니다. 앱 옆에서 프록시를 시작하고, 앱의 API 기본 URL을 프록시로 연결하고, SSR에서 세션 헤더를 전파하고, 픽스처를 하나 작성하면 됩니다.

{
"scripts": {
"proxy": "test-proxy-recorder http://localhost:8000 --port 8100 --dir ./e2e/recordings",
"dev:proxy": "concurrently \"npm run proxy\" \"TEST_PROXY_RECORDER_ENABLED=1 npm run dev\"",
"serve:proxy": "concurrently \"npm run proxy\" \"TEST_PROXY_RECORDER_ENABLED=1 npm run serve\""
}
}

앱 코드에서, 레코더가 활성화되어 있으면 API 기본 URL을 프록시로, 그렇지 않으면 실제 백엔드로 연결하세요. 프록시는 프로덕션에서 절대 실행되지 않습니다.

const API_BASE =
process.env.NODE_ENV === 'production' && !process.env.TEST_PROXY_RECORDER_ENABLED
? 'https://api.example.com'
: 'http://localhost:8100'; // 프록시 주소

TEST_PROXY_RECORDER_ENABLED는 위의 dev:proxy / serve:proxy 스크립트와 init이 생성한 스크립트가 설정합니다. 앱이 이미 API 기본 URL에 사용하는 환경 변수(예: API_URL, NEXT_PUBLIC_API_URL)를 그대로 사용하면 됩니다. 동일한 조건부가 적용됩니다.

서버 측 fetch 호출은 프록시가 어떤 테스트에 속하는지 알 수 있도록 기록 세션 헤더가 필요합니다. Playwright가 브라우저 내비게이션에 이미 설정해 두므로 id가 next/headers에 있습니다. 그 id를 나가는 SSR 요청에 붙이기만 하면 됩니다. 루트 레이아웃에 한 줄을 추가하세요(init이 대신 해 줍니다).

app/layout.tsx
import { registerProxyFetch } from 'test-proxy-recorder/nextjs';
registerProxyFetch(); // 프로덕션에서는 TEST_PROXY_RECORDER_ENABLED=true가 아니면 아무 동작도 하지 않음
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

이 방법은 Node Edge 런타임에서 동작합니다. axios 앱에서는 각 서버 측 인스턴스에 registerProxyAxios(instance)를 호출하고, 단일 fetch에는 createHeadersWithRecordingId(await headers())가 패치 없는 대안입니다. setNextProxyHeaders를 쓰는 proxy.ts/middleware.ts선택 사항입니다. id만 노출할 뿐 fetch에 태깅하지는 않습니다. 프로덕션 빌드(next build && next start)로 기록하세요. next dev가 아닙니다. 자세한 내용은 Next.js 통합을 참조하세요. 브라우저 전용 앱은 이 단계를 건너뛸 수 있습니다.

import { test, expect } from '@playwright/test';
import { playwrightProxy } from 'test-proxy-recorder';
// SSR 요청(서버 → 프록시)은 .mock.json에 기록됩니다.
// 프록시 URL로 가는 브라우저 요청도 함께 처리됩니다.
const CLIENT_SIDE_URL = /localhost:8100/;
// 기록을 갱신하려면 'record'로 변경하세요.
const MODE = 'replay' as const;
test.beforeEach(async ({ page }, testInfo) => {
await playwrightProxy.before(page, testInfo, MODE, { url: CLIENT_SIDE_URL });
});
test('homepage loads', async ({ page }) => {
await page.goto('/');
await expect(page.getByText('Welcome')).toBeVisible();
});
Terminal window
# 터미널 1
npm run serve:proxy
# 터미널 2 — .mock.json과 .har 파일이 자동으로 작성됩니다
npx playwright test
Terminal window
git add e2e/recordings/
git commit -m "add e2e recordings"

브라우저 전용 / SPA / 확장 프로그램

섹션 제목: “브라우저 전용 / SPA / 확장 프로그램”

모든 API 호출이 브라우저에서 오는 경우(SSR 없음)에는 HAR 메커니즘만 있으면 됩니다. 실제 기록에는 프록시 백엔드가 필요 없으며, 프록시 프로세스는 세션 관리만 제공합니다.

Terminal window
npm install --save-dev test-proxy-recorder

2. playwright.config.ts에 프록시 추가

섹션 제목: “2. playwright.config.ts에 프록시 추가”
import { defineConfig } from '@playwright/test';
export default defineConfig({
webServer: {
command: 'test-proxy-recorder https://api.example.com --port 8100 --dir ./e2e/recordings',
url: 'http://localhost:8100/__control',
reuseExistingServer: true,
},
});

프록시 대상(https://api.example.com)은 브라우저 전용 기록에서는 중요하지 않습니다. 서버 측(SSR) 요청도 프록시로 통과시켜야 하는 경우에만 사용됩니다. 세션 관리를 위해 /__control 엔드포인트를 사용할 수 있도록 프록시 프로세스가 실행 중이어야 합니다.

e2e/fixtures.ts
import { test as base, type Page, type BrowserContext } from '@playwright/test';
import { playwrightProxy } from 'test-proxy-recorder';
// 브라우저가 요청을 보내는 외부 API 도메인과 일치시키세요.
// 기록 모드에서는 이 요청들이 실제 API로 가서 저장됩니다.
// 재생 모드에서는 디스크에서 제공됩니다. 네트워크가 필요 없습니다.
const CLIENT_SIDE_URL = /api\.example\.com/;
// 실제 API를 호출해 기록을 갱신하려면 'record'로 변경하세요.
const MODE = 'replay' as const;
export const test = base.extend<{ page: Page }>({
page: async ({ context }, use, testInfo) => {
const page = await context.newPage();
await playwrightProxy.before(page, testInfo, MODE, { url: CLIENT_SIDE_URL });
await use(page);
},
});
e2e/my.test.ts
import { test, expect } from './fixtures';
test('homepage loads', async ({ page }) => {
await page.goto('https://myapp.com/');
await expect(page.getByText('Welcome')).toBeVisible();
});

5. 기록 — 실제 API를 대상으로 한 번 실행

섹션 제목: “5. 기록 — 실제 API를 대상으로 한 번 실행”
Terminal window
# fixtures.ts에서: const MODE = 'record' as const;
npx playwright test
# .har 파일이 e2e/recordings/에 자동으로 작성됩니다
Terminal window
# fixtures.ts에서: const MODE = 'replay' as const;
git add e2e/recordings/
git commit -m "add e2e recordings"

이제 CI는 네트워크 접근 없이 실행됩니다.

PR diff에서 큰 기록 파일을 접히게 하려면 .gitattributes에 이것을 추가하세요.

/e2e/recordings/** binary