Expect는 AI 에이전트(Claude, Codex 등)가 코드 변경사항을 분석하여 "적대적(adversarial)" 테스트 계획을 자동 생성하고, 실제 브라우저(Playwright)에서 해당 테스트를 실행하여 통과/실패를 리포트하는 자동화 테스트 도구입니다.
일반 테스트는 "로그인이 잘 되는지" 확인합니다. Expect는 빈 값, SQL 인젝션 문자열, 1000자 입력, 연속 제출로 시스템을 공격합니다. 코드를 쓰는 AI와, 그 코드를 테스트하는 AI가 협업하는 새로운 개발 패러다임입니다.
Playwright 스크린샷과 스냅샷 비교로 테스트 과정을 추적하므로, 실패 시 "무슨 일이 일어났는지"를 단계별로 확인할 수 있습니다.
AI가 코드를 빠르게 생성하는 바이브코딩이 확산되면서, "AI가 작성한 코드의 품질을 어떻게 보장하지?"라는 질문이 커졌습니다. Playwright나 Cypress로 테스트를 작성하면 코드가 바뀔 때마다 테스트도 수동으로 고쳐야 합니다.
git diff만 있으면 AI가 무엇이 바뀌었는지 분석하여 그에 맞는 적대적 테스트 계획을 자동으로 만들어냅니다. 사람이 테스트 코드를 작성할 필요가 없습니다.
| 비교 대상 | Expect의 차별점 |
|---|---|
| Playwright 직접 작성 | 테스트 코드를 사람이 안 써도 됨. git diff만 있으면 AI가 자동 생성 |
| Cypress | E2E 프레임워크이지만 테스트 작성은 수동. Expect는 "변경→테스트"가 자동 |
| Copilot 테스트 생성 | 코드 레벨 유닛 테스트 생성 vs 실제 브라우저 UI 레벨 테스트 |
| browser-use | 브라우저 자동화 라이브러리 vs 테스트 특화 + 세션 녹화/리플레이 포함 |
핵심 혁신 4가지: 적대적 테스트 철학, 쿠키/인증 자동 주입, Playwright 스냅샷 비교, Claude Code 스킬 통합.
| 기술 | 버전 | 역할 |
|---|---|---|
| TypeScript | 5.7.0 | 메인 언어 (코드베이스 99.2%) |
| Node.js | v18.x 이상 | 런타임 (engines: '>=18'; @types/node v22.15.0은 타입 정의 버전) |
| 기술 | 버전 | 역할 |
|---|---|---|
| Effect | 4.0.0-beta.35 | 함수형 프로그래밍 프레임워크 (에러 핸들링, 의존성 주입, 동시성) |
| Playwright | 1.52.0 | 실제 브라우저 자동화 (Chromium/Firefox/WebKit) |
| rrweb | (@posthog/rrweb ^0.0.50) | 데모 웹사이트(apps/website)에서만 사용 — 코어 패키지 의존성 아님 |
| Zod | 4.3.6 | 런타임 스키마 검증 |
| 기술 | 역할 |
|---|---|
| @ai-sdk/provider (3.0.8) | AI 모델 프로바이더 추상화 (Vercel AI SDK) |
| Agent Client Protocol / ACP (0.16.1) | 에이전트 간 통신 프로토콜 |
| MCP SDK (1.27.1) | Model Context Protocol — Claude Code와 통합 |
| 기술 | 역할 |
|---|---|
| pnpm | 모노레포 패키지 매니저 (workspace 기반) |
| Turborepo | 모노레포 빌드 오케스트레이션 (동시성 20) |
| Vite | 번들링 & 개발 서버 |
Expect의 가장 독특한 기술적 선택은 Effect 라이브러리를 핵심 프레임워크로 사용한다는 점입니다. Effect는 TypeScript의 "ZIO" 같은 것으로, 에러 타입이 타입 시스템에 명시됩니다.
// Effect 패턴 — 에러 타입이 타입 시그니처에 명시됨
type BrowserResult = Effect.Effect<SnapshotResult, BrowserLaunchError | ActionTimeoutError>
// 의존성 주입이 타입 레벨에서 관리됨 — 테스트 시 쉽게 모킹 가능
try-catch에서는 어떤 에러가 발생하는지 함수 시그니처에 보이지 않습니다. Effect는 Effect<성공값, 에러타입, 의존성>으로 모든 것을 타입으로 추적합니다. Scala의 ZIO에서 영감을 받았습니다.detectAvailableAgents() 함수가 사용 가능한 에이전트를 자동 감지하고, AgentBackend 타입으로 추상화합니다.
Browser 패키지가 MCP 서버를 내장하여, Claude Code가 Expect를 도구(tool)로 직접 호출할 수 있습니다:
// MCP 서버 생성 — Claude Code가 이 도구를 호출 가능
const runtime = ManagedRuntime.make(
Layer.mergeAll(McpSession.layer, OverlayController.layer)
);
const server = createBrowserMcpServer(runtime);
// 호출 흐름: Claude Code → MCP 프로토콜 → Playwright 실행
Supervisor 패키지가 전체 워크플로우를 조율합니다: Git 모듈 → Agent 테스트 계획 → Browser 실행 → Reporter 결과 수집.
배울 것: TypeScript에서 "에러를 타입으로 추적"하는 혁신적 방식. try-catch의 한계를 넘어서는 함수형 에러 핸들링.
// 전통적 방식: 어떤 에러가 발생하는지 타입에서 안 보임
async function runTest(): Promise<Result> {
try { /* ... */ } catch (e) { /* e는 unknown */ }
}
// Effect 방식: 에러 타입이 시그니처에 명시
function runTest(): Effect.Effect<Result, BrowserLaunchError | ActionTimeoutError> {
// 컴파일러가 모든 에러 케이스 처리를 강제
}
배울 것: CDP(Chrome DevTools Protocol) 자동 발견, 스크린샷 비교(diffSnapshots), 스냅샷 기반 테스트.
// CDP 자동 발견 — 이미 실행 중인 Chrome에 연결
autoDiscoverCdp() // 개발 중인 앱의 브라우저에 바로 연결
배울 것: Claude Code의 도구를 확장하는 MCP 서버를 TypeScript로 구현하는 방법. Expect의 packages/browser/src/mcp/ 코드를 분석하면 완전한 MCP 서버 구현 패턴을 익힐 수 있습니다.
배울 것: DOM 변경사항을 이벤트로 캡처하여 "영상처럼" 리플레이하는 기술. 비디오가 아닌 DOM 이벤트 기반이라 파일 크기가 작습니다.
// 세션 이벤트 수집 → HTML 리플레이어 생성
const events = collectAllEvents(session);
const html = buildReplayViewerHtml(events);
// 브라우저에서 열면 테스트 과정을 그대로 재생
배울 것: 7개 패키지를 효율적으로 관리하는 모노레포 구성, 의존성 그래프 기반 빌드.
// turbo.json — 빌드 태스크 간 의존 관계 정의
{
"tasks": {
"build": { "dependsOn": ["^build"] }, // 의존 패키지 먼저 빌드
"test": { "dependsOn": ["^test"] }
}
}
| 항목 | 요구사항 |
|---|---|
| Node.js | v18.x 이상 (engines: '>=18') |
| 패키지 매니저 | pnpm (모노레포 workspace) |
| 브라우저 | Chromium (Playwright가 자동 설치) |
| OS | macOS, Linux, Windows (Playwright 지원 OS) |
| 메모리 | 최소 4GB (Playwright + AI 호출 동시 실행) |
| AI API 키 | Claude API 키 또는 Codex 접근 권한 |
| 네트워크 | AI API 호출을 위한 인터넷 연결 필요 |
CLI 워크플로우 이해 — 변경 스캔 → 계획 생성 → 실행 → 리포트.
"행복한 경로(happy path)" vs "적대적 테스트" 차이를 체감합니다.
expect-skill의 SKILL.md를 Claude Code에 등록하고, MCP 기반 도구 통합을 이해합니다. Claude Code에서 자연어로 "이 PR의 변경사항을 적대적으로 테스트해줘" 요청.
Expect의 Supervisor 패턴을 참고하여 미니 테스트 러너를 만들어봅니다. Effect 함수형 패턴 + Playwright + AI API 조합 실습.
import { Effect } from "effect";
import { chromium } from "playwright";
// 1. Git diff 파싱 → 변경 파일 목록
// 2. AI에게 테스트 계획 요청
// 3. Playwright로 브라우저에서 테스트 실행
// 4. 결과 리포트 출력
Expect의 createBrowserMcpServer() 패턴을 참고하여 자신만의 MCP 서버를 구현합니다. MCP 프로토콜의 서버/클라이언트 구조를 완전히 이해하는 것이 목표.
Playwright 공식 튜토리얼 완주(2~3일), TypeScript 고급 타입(제네릭, 조건부 타입, 매핑된 타입) 복습, Git diff 파싱 기초(simple-git 라이브러리).
Effect 공식 문서 "Getting Started" 완독. Effect<Success, Error, Requirements> 3가지 타입 파라미터 이해. pipe, map, flatMap, catchAll 패턴 실습. Expect의 에러 타입 계층 분석.
MCP 공식 스펙 문서 읽기, 간단한 MCP 서버 직접 구현(Node.js + TypeScript), Claude Code에서 커스텀 MCP 도구 연동 테스트. Expect의 packages/browser/src/mcp/ 코드 분석.
pnpm workspace 설정 방법 학습, Turborepo로 빌드 파이프라인 구성, Expect의 7-패키지 모노레포 구조를 참고한 미니 프로젝트 구성.
Vercel AI SDK(@ai-sdk/provider) 학습, ACP(Agent Client Protocol) 스펙 이해, 멀티 프로바이더 에이전트 시스템 직접 구현.
자신만의 "AI 기반 자동화 테스트 도구" 미니 버전 구현, Supervisor 패턴으로 워크플로우 오케스트레이션, rrweb 세션 녹화 + 리플레이 기능 추가, CI/CD 파이프라인 통합.
| 키워드 | 설명 |
|---|---|
| 적대적 테스트 | 정상 입력이 아닌 경계값, 악의적 입력, 비정상 조작으로 소프트웨어를 "공격"하는 테스트 방식. 해피 패스만 검증하는 기존 테스트의 한계를 보완 |
| Effect | TypeScript용 함수형 프로그래밍 프레임워크. 에러 타입을 시그니처에 명시하고, 의존성 주입/동시성을 타입 안전하게 관리. Scala의 ZIO에서 영감 |
| Playwright | Microsoft가 만든 브라우저 자동화 라이브러리. Chromium, Firefox, WebKit을 코드로 제어. E2E 테스트의 사실상 표준 |
| CDP | Chrome DevTools Protocol. Chrome 브라우저를 프로그래밍으로 제어하는 프로토콜. autoDiscoverCdp()는 이미 실행 중인 Chrome에 이 프로토콜로 연결 |
| MCP | Model Context Protocol. Anthropic이 만든 표준 프로토콜. AI 모델이 외부 도구를 호출할 수 있게 하는 인터페이스 |
| ACP | Agent Client Protocol. AI 에이전트 간 통신을 위한 프로토콜. 여러 AI 프로바이더를 통일된 인터페이스로 접근 |
| rrweb | "Record and Replay the Web" — 웹 페이지의 DOM 변경사항을 이벤트로 캡처하여 나중에 그대로 재생하는 라이브러리 |
| Turborepo | Vercel이 만든 모노레포 빌드 도구. 패키지 간 의존 관계를 파악하여 빌드 순서를 자동 결정하고, 캐싱으로 재빌드를 최소화 |
| Supervisor 패턴 | 여러 하위 작업(Git 분석, AI 호출, 브라우저 실행, 리포트)을 조율하는 상위 관리자. Erlang/OTP의 Supervisor에서 영감 |
| 스냅샷 비교 | 브라우저 상태의 이전/이후를 비교하여 변경 사항을 감지. diffSnapshots() 함수가 담당 |
| FSL-1.1-MIT | Functional Source License. 처음 일정 기간은 비상업적 사용만 가능하고, 이후 MIT로 자동 전환되는 라이선스 |