출시·고도화 중
Next.js 안내서 · 5/6
Next.js 애플리케이션은 보통 두 층으로 테스트합니다. 컴포넌트와 함수 하나하나를 빠르게 확인하는 단위 테스트에는 Vitest나 Jest와 React Testing Library를, 실제 브라우저로 페이지를 열어 사용자 흐름을 확인하는 E2E(종단 간) 테스트에는 Playwright나 Cypress를 씁니다. 이 장에서는 Vitest와 Playwright를 중심으로 설정과 작성 방법을 살펴봅니다.
| 대상 | 권장 도구 | 이유 |
|---|---|---|
| 순수 함수, 검증 로직, 데이터 변환 | Vitest · Jest | 브라우저 없이 빠르게 실행됩니다 |
| Client Component, 동기 Server Component | Vitest · Jest + React Testing Library | 렌더링 결과와 상호작용을 확인합니다 |
async Server Component, 라우팅, Server Action 흐름 | Playwright · Cypress | 실제 서버와 브라우저에서 전체 동작을 확인합니다 |
async Server Component는 비교적 새로운 기능이라 Vitest나 Jest 같은 단위 테스트 도구가 아직 제대로 렌더링하지 못합니다. 그래서 공식 문서도 이런 컴포넌트는 E2E 테스트로 확인하도록 권합니다. 대신 컴포넌트 안의 데이터 처리 로직을 일반 함수로 분리해 두면 그 부분은 단위 테스트로 충분히 다룰 수 있습니다.
필요한 패키지를 개발 의존성으로 설치합니다. vite-tsconfig-paths는 @/ 같은 경로 별칭을 테스트에서도 쓰게 해 줍니다.
npm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom vite-tsconfig-paths프로젝트 루트에 설정 파일을 만들고, package.json에 "test": "vitest" 스크립트를 추가합니다.
// vitest.config.mts
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [tsconfigPaths(), react()],
test: {
environment: "jsdom",
},
});create-next-app --example with-vitest처럼 공식 예제로 시작하면 이 설정이 이미 들어 있는 프로젝트를 받을 수 있습니다. Jest를 선호한다면 Next.js가 제공하는 next/jest 도우미가 SWC 변환, CSS · 이미지 가져오기 처리, 환경 변수 로드를 자동으로 설정해 줍니다.
앞 장의 LikeButton 같은 Client Component를 렌더링하고, 사용자처럼 클릭한 뒤 결과를 확인합니다. React Testing Library는 내부 구현 대신 화면에 보이는 역할과 글자로 요소를 찾도록 권합니다.
// app/ui/like-button.test.tsx
import { describe, expect, it } from "vitest";
import { fireEvent, render, screen } from "@testing-library/react";
import { LikeButton } from "./like-button";
describe("LikeButton", () => {
it("누를 때마다 숫자가 하나씩 늘어난다", () => {
render(<LikeButton initial={3} />);
const button = screen.getByRole("button");
fireEvent.click(button);
expect(button.textContent).toContain("4");
});
});useRouter, usePathname 같은 next/navigation 훅을 쓰는 컴포넌트는 테스트 환경에 Next.js 라우터가 없으므로 모의(mock) 객체로 바꿔 줍니다.
import { vi } from "vitest";
vi.mock("next/navigation", () => ({
useRouter: () => ({ push: vi.fn(), refresh: vi.fn() }),
usePathname: () => "/dashboard",
useSearchParams: () => new URLSearchParams("q=next"),
}));Playwright는 Chromium, Firefox, WebKit을 하나의 API로 자동화합니다. 설치 마법사가 설정 파일과 예제 테스트를 만들어 줍니다.
npm init playwrightwebServer 설정을 쓰면 테스트를 시작하기 전에 Next.js 서버를 띄우고 준비될 때까지 기다립니다. 운영 환경과 가깝게 확인하려면 개발 서버 대신 빌드한 결과를 next start로 실행해 테스트하는 것이 좋습니다.
// playwright.config.ts
import { defineConfig } from "@playwright/test";
export default defineConfig({
testDir: "./e2e",
use: { baseURL: "http://localhost:3000" },
webServer: {
command: "npm run build && npm run start",
url: "http://localhost:3000",
reuseExistingServer: !process.env.CI,
},
});// e2e/navigation.spec.ts
import { expect, test } from "@playwright/test";
test("첫 화면에서 소개 페이지로 이동한다", async ({ page }) => {
await page.goto("/");
await page.getByRole("link", { name: "소개" }).click();
await expect(page).toHaveURL("/about");
await expect(page.getByRole("heading", { level: 1 })).toHaveText("소개");
});E2E 테스트는 npx playwright test로 실행하고, npx playwright test --ui로 실행 과정을 화면에서 하나씩 살펴볼 수 있습니다. 폼 제출처럼 Server Action이 개입하는 흐름도 이 방법으로 실제와 같은 조건에서 확인합니다.
CI에서는 보통 린트, 타입 검사, 단위 테스트, 빌드, E2E 테스트 순으로 실행합니다. 타입 검사는 npx tsc --noEmit으로 따로 돌릴 수 있고, next build도 빌드 중에 타입 오류를 검사합니다. 빠른 단계를 앞에 두면 실패를 일찍 발견할 수 있습니다.
async Server Component와 전체 사용자 흐름은 Playwright 같은 E2E 도구로 확인합니다.next/navigation 훅은 단위 테스트에서 모의 객체로 바꿉니다.next build 후 next start로 띄운 서버를 대상으로 실행하면 운영 환경에 더 가깝습니다.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.
첫 댓글을 남겨 보세요.