Playwright CLI: AI 코딩 에이전트를 위한 Microsoft의 새로운 브라우저 자동화 도구

Playwright CLI: AI 코딩 에이전트를 위한 Microsoft의 새로운 브라우저 자동화 도구

AI 코딩 에이전트에게 브라우저를 맡기는 흐름이 더 빨라지고 있습니다. 이전에 Playwright MCP로 AI 에이전트가 MCP 서버를 통해 브라우저를 다루는 방법을 살펴봤고, Vercel Labs의 agent-browser 같은 CLI 기반 접근도 소개했었는데요. 이번에는 Playwright를 만든 Microsoft가 직접 내놓은 새 도구를 들고 왔습니다.

Playwright CLI는 그 이름 그대로 Playwright의 핵심 기능을 명령줄 인터페이스로 노출한 도구입니다. 흥미로운 점은 이게 단순한 playwright 패키지의 CLI 진입점이 아니라 처음부터 코딩 에이전트를 1순위 사용자로 잡고 설계되었다는 거예요. Claude Code나 GitHub Copilot 같은 에이전트가 Bash 도구만으로 브라우저를 열고 페이지를 탐색하고 요소를 클릭하고 스크린샷을 찍을 수 있게 해줍니다.

이 글에서는 Playwright CLI가 무엇이고, 왜 또 다른 도구가 필요했는지, 그리고 실제로 어떻게 쓰는지를 차근차근 풀어보겠습니다.

MCP가 있는데 왜 CLI일까?

Playwright 팀은 이미 Playwright MCP라는 잘 만들어진 MCP 서버를 가지고 있습니다. 그런데 굳이 별도의 CLI를 또 만든 이유가 뭘까요?

핵심은 토큰 효율성입니다. MCP는 도구 호출 단위로 JSON-RPC 메시지를 주고받고, 페이지 스냅샷 같은 큰 응답도 모두 LLM의 컨텍스트로 들어갑니다. 모델이 매번 페이지 전체 구조를 머릿속에 담고 있어야 다음 행동을 결정할 수 있는 구조예요. 컨텍스트 윈도우가 빠듯한 상황에서는 이 비용을 무시하기 어렵습니다.

CLI 방식은 좀 다릅니다. 에이전트가 playwright-cli snapshot 같은 명령어를 실행하면 결과는 일단 터미널 출력으로 나오지만, 그걸 통째로 컨텍스트에 끌어올릴지 일부만 보고 넘길지를 에이전트가 선택할 수 있어요. 페이지 일부만 grep으로 잘라서 봐도 되고, --filename 옵션으로 파일에 저장한 뒤 필요한 부분만 읽을 수도 있습니다. 모델이 “필요한 만큼만 보고 행동하는” 자유도가 훨씬 높아지는 거죠.

거기에다 CLI는 MCP 클라이언트가 없는 환경에서도 동작합니다. 쉘 접근만 가능하면 에이전트 종류를 가리지 않고 쓸 수 있어요. Claude Code, Codex CLI, Aider, 심지어 직접 만든 자동화 스크립트까지 모두 같은 명령어 인터페이스로 브라우저를 다룰 수 있습니다.

설치와 첫 실행

설치는 npm 전역 설치 한 줄로 끝납니다.

bun add -g @playwright/cli@latest
# 또는
npm install -g @playwright/cli@latest

Node.js 18 이상이 필요합니다. 설치가 끝나면 playwright-cli 명령어를 사용할 수 있어요.

다음으로 스킬을 함께 설치합니다.

playwright-cli install --skills

install --skills는 Chromium 같은 브라우저 바이너리뿐만 아니라 코딩 에이전트가 참고할 수 있는 스킬 정의도 함께 내려받습니다. Claude Code의 스킬 시스템이나 GitHub Copilot의 워크스페이스 설정에 연결되어서 에이전트가 “지금 이 환경에서 어떤 브라우저 작업을 할 수 있는지”를 자동으로 인식하게 해주는 역할을 합니다.

설치를 확인해볼게요.

playwright-cli --help

기본 명령어 목록과 각 카테고리가 출력됩니다. 헤드리스(headless)가 기본 모드여서 작업이 백그라운드에서 조용히 진행되고, 실제로 브라우저 창을 띄우고 싶으면 --headed 옵션을 추가하면 됩니다.

페이지 열고 탐색하기

가장 기본은 페이지를 여는 일이죠. 브라우저를 띄우고 URL로 이동합니다.

playwright-cli open https://playwright.dev

open은 새 세션을 시작하면서 URL로 바로 이동합니다. 이미 열린 세션에서 다른 페이지로 옮기고 싶다면 goto를 씁니다.

playwright-cli goto https://playwright.dev/docs/intro

브라우저의 뒤로 가기, 앞으로 가기, 새로고침도 명령어 한 줄이면 됩니다.

playwright-cli go-back
playwright-cli go-forward
playwright-cli reload

여기까지는 어떤 브라우저 자동화 도구든 비슷하지만, 진짜 흥미로운 부분은 페이지를 읽는 방식입니다.

스냅샷: 페이지를 텍스트로 읽기

snapshot 명령어는 현재 페이지의 접근성 트리(accessibility tree)를 YAML 형태로 출력합니다. CSS 셀렉터나 HTML 구조 대신, 사람이 페이지를 인식하는 방식과 비슷한 의미 구조로 페이지를 표현하는 거예요.

playwright-cli snapshot

출력은 대략 이런 모습입니다.

결과
- heading "Playwright" [ref=e1]
- navigation [ref=e2]:
  - link "Docs" [ref=e3]
  - link "API" [ref=e4]
- button "Get Started" [ref=e5]
- textbox "Search docs" [ref=e6]

각 요소 옆에 ref=e1, ref=e2 같은 참조 ID가 붙는 게 보이시나요? 이 참조를 활용하면 셀렉터를 잡느라 고생할 필요 없이 바로 요소를 지정할 수 있습니다.

playwright-cli click e5
playwright-cli fill e6 "playwright cli"

CSS 셀렉터는 페이지 마크업이 조금만 바뀌어도 깨지기 쉽지만, 스냅샷 참조는 현재 페이지 상태를 기준으로 즉시 부여된 ID라서 훨씬 안정적이에요. 에이전트 입장에서도 “5번 요소를 클릭해”라는 표현이 “button.btn-primary:nth-child(3)을 클릭해”보다 훨씬 다루기 편하고요.

스냅샷이 너무 길어서 컨텍스트에 부담이 되면 파일에 저장한 뒤 필요한 부분만 읽을 수 있습니다.

playwright-cli snapshot --filename=page.yaml

특정 요소 하위만 보고 싶다면 셀렉터를 함께 넘깁니다.

playwright-cli snapshot "#main-content"

Playwright 로케이터 문법도 그대로 통해서, 참조 ID 대신 getByRole이나 getByText를 써도 됩니다.

playwright-cli click "getByRole('button', { name: 'Get Started' })"

입력과 상호작용

요소와의 상호작용은 직관적입니다.

playwright-cli click e5
playwright-cli type "Hello, world"
playwright-cli fill e6 "검색어"
playwright-cli check e7
playwright-cli uncheck e7
playwright-cli press Enter

type은 현재 포커스가 있는 위치에 글자를 하나씩 입력하고, fill은 특정 요소의 기존 값을 지운 뒤 새 값을 한 번에 채웁니다. 폼 입력은 보통 fill이 깔끔하고, 자동완성을 트리거해야 하는 검색 입력 같은 곳에서는 type이 자연스러워요.

마우스와 키보드를 더 세밀하게 다뤄야 한다면 저수준 명령어도 준비되어 있습니다.

playwright-cli mousemove 100 200
playwright-cli mousedown
playwright-cli mouseup
playwright-cli mousewheel 0 500
playwright-cli keydown Shift
playwright-cli keyup Shift

파일 업로드와 드래그 앤 드롭도 한 줄로 끝납니다.

playwright-cli drop e10 --path=./resume.pdf
playwright-cli drag e11 e12

자바스크립트 다이얼로그가 뜨는 페이지에서는 다이얼로그 응답도 명령어로 제어합니다.

playwright-cli dialog-accept
playwright-cli dialog-dismiss
playwright-cli dialog-accept "확인"

세션 관리: 동시에 여러 브라우저 다루기

Playwright CLI가 다른 CLI 도구와 차별화되는 지점 중 하나가 명명된 세션 기능입니다. -s 또는 --session 옵션으로 세션 이름을 붙이면 여러 브라우저 컨텍스트를 동시에 띄워두고 이름으로 골라 쓸 수 있어요.

playwright-cli -s=todo open https://demo.playwright.dev/todomvc/
playwright-cli -s=docs open https://playwright.dev

이제 두 세션이 독립적으로 살아 있습니다. 각 세션에 명령어를 보낼 때마다 세션 이름을 지정하면 됩니다.

playwright-cli -s=todo type "Buy groceries"
playwright-cli -s=todo press Enter

playwright-cli -s=docs goto https://playwright.dev/docs/intro

매번 -s를 붙이는 게 번거롭다면 환경 변수로 기본 세션을 설정할 수 있습니다.

export PLAYWRIGHT_CLI_SESSION=todo
playwright-cli type "Read book"
playwright-cli press Enter

세션 목록 확인과 정리도 명령어로 합니다.

playwright-cli list
playwright-cli close
playwright-cli close-all

--persistent 옵션을 함께 주면 세션 데이터가 디스크에 저장되어서, CLI를 껐다 켜도 로그인 상태나 쿠키가 유지됩니다.

playwright-cli -s=work open https://github.com --persistent

여러 사이트의 로그인 상태를 세션별로 유지해두면 에이전트가 매번 인증을 다시 할 필요가 없어집니다.

스토리지와 네트워크 다루기

쿠키, localStorage, sessionStorage를 모두 명령어로 조회하고 수정할 수 있습니다.

playwright-cli cookie-list
playwright-cli cookie-set name=session value=abc123 domain=example.com
playwright-cli cookie-delete name=session

playwright-cli localstorage-list
playwright-cli localstorage-set theme dark

네트워크 가로채기도 빠질 수 없죠. 특정 URL 패턴에 대해 가짜 응답을 돌려주거나 요청을 차단할 수 있습니다.

playwright-cli route "**/api/users" --body '{"users": []}'
playwright-cli route "**/ads/**" --abort
playwright-cli unroute "**/api/users"

페이지에서 어떤 요청이 오갔는지도 확인할 수 있습니다.

playwright-cli requests
playwright-cli requests --filter api
playwright-cli console

console은 페이지의 자바스크립트 콘솔 메시지를 보여주고, requests는 네트워크 요청 로그를 출력합니다. 에이전트가 페이지에서 발생한 에러를 디버깅할 때 곧바로 활용할 수 있는 정보예요.

시각화 도구: 스크린샷, 비디오, 트레이싱

페이지가 어떻게 보이는지 캡처하는 명령어도 풍부합니다.

playwright-cli screenshot
playwright-cli screenshot --filename=login.png
playwright-cli pdf --filename=report.pdf

스크린샷에 특정 요소만 담고 싶다면 참조를 넘깁니다.

playwright-cli screenshot e5

특정 요소를 시각적으로 강조하거나 Playwright 로케이터 코드를 자동으로 만들어내는 기능도 있습니다.

playwright-cli highlight e5
playwright-cli generate-locator e5

generate-locator는 해당 요소에 가장 적합한 Playwright 로케이터를 추천해줘서 자동화 코드를 작성할 때 시간을 크게 줄여줍니다.

복잡한 시나리오를 분석하고 싶다면 트레이싱과 비디오 녹화도 시작할 수 있어요.

playwright-cli tracing-start
# ... 일련의 작업 ...
playwright-cli tracing-stop

playwright-cli video-start
# ... 일련의 작업 ...
playwright-cli video-stop

생성된 트레이스 파일은 Playwright Trace Viewer에서 열어볼 수 있어서 에이전트가 만든 자동화의 동작 과정을 사람이 사후에 추적하기에 좋습니다.

마지막으로 show 명령어가 있습니다.

playwright-cli show

이걸 실행하면 현재 떠 있는 모든 세션을 시각적으로 보여주는 대시보드가 브라우저에 뜹니다. 에이전트가 만든 여러 세션이 동시에 돌아가고 있을 때 사람이 한눈에 상태를 파악하기에 편리해요.

설정 파일

기본 동작을 바꾸고 싶으면 .playwright/cli.config.json 파일을 프로젝트 루트에 두면 됩니다.

.playwright/cli.config.json
{
  "browser": {
    "browserName": "chromium",
    "launchOptions": {
      "headless": false
    },
    "contextOptions": {
      "viewport": { "width": 1280, "height": 720 },
      "locale": "ko-KR"
    }
  },
  "outputDir": ".playwright/output",
  "timeouts": {
    "action": 5000,
    "navigation": 15000
  }
}

browser.browserName으로 chromium, firefox, webkit 중 선택할 수 있고, launchOptionscontextOptions는 Playwright의 동일한 API에 그대로 전달됩니다. outputDir는 스크린샷, PDF, 트레이스 같은 산출물의 저장 위치를 지정하고, timeouts로 액션과 네비게이션의 기본 타임아웃을 조절할 수 있어요.

환경 변수로도 같은 설정을 줄 수 있습니다. 자주 쓰이는 것 몇 가지를 보면, PLAYWRIGHT_MCP_BROWSER로 브라우저 종류를, PLAYWRIGHT_MCP_HEADLESS로 헤드리스 여부를, PLAYWRIGHT_MCP_USER_DATA_DIR로 사용자 데이터 디렉토리를 지정할 수 있어요. 이름에 MCP가 들어가는 건 내부적으로 Playwright MCP와 설정 체계를 공유하기 때문입니다.

Playwright MCP와 어떻게 다를까?

같은 팀에서 만든 도구라서 자연스레 비교가 됩니다.

Playwright MCP는 MCP 프로토콜을 통해 동작합니다. MCP 클라이언트(Claude Code, VS Code Copilot 등)가 서버에 도구 호출을 보내고, 서버가 브라우저를 조작한 결과를 다시 LLM 컨텍스트로 돌려주는 구조예요. 에이전트가 “버튼을 눌러줘”라고 말하면 클라이언트가 알아서 적절한 도구를 골라 호출합니다. 자연스러운 대화 흐름 안에서 브라우저 작업이 녹아드는 게 장점이죠.

Playwright CLI는 순수 명령줄 도구입니다. 에이전트가 Bash 도구로 직접 명령어를 실행하고 출력을 받아서 다음 행동을 결정합니다. 클라이언트가 MCP를 지원할 필요가 없고, 에이전트는 명령어를 조합해 자체 워크플로우를 만들 수 있어요. 더 중요한 차이는 컨텍스트 관리 권한이 에이전트 쪽에 있다는 점입니다. 페이지 스냅샷을 통째로 받아서 다 읽을지, 파일로 저장해두고 일부만 들춰볼지, grep으로 잘라낼지를 에이전트가 결정할 수 있어요.

대규모 코드베이스를 다루거나 컨텍스트 윈도우가 빠듯한 상황, 그리고 여러 에이전트를 같은 환경에서 돌려야 하는 경우라면 Playwright CLI 쪽이 더 잘 맞습니다. 반대로 MCP 클라이언트가 이미 일상 도구로 자리 잡았고 자연어 흐름 안에서 매끄럽게 브라우저를 다루고 싶다면 Playwright MCP가 자연스럽고요.

같은 영역에 agent-browserchrome-devtools-mcp 같은 도구도 있는데, 각자 강점이 조금씩 다릅니다. Vercel의 agent-browser는 Rust 바이너리 기반이라 시작 속도가 빠르고, Chrome DevTools MCP는 Lighthouse 감사나 성능 프로파일링까지 묶어 제공해요. Playwright CLI의 강점은 Playwright의 성숙한 브라우저 추상화와 명명된 세션 관리, 그리고 코딩 에이전트를 1순위로 잡고 다듬어진 명령어 체계입니다.

코딩 에이전트와 함께 쓰는 워크플로우

마지막으로 실제 흐름을 한번 그려보겠습니다. Claude Code 같은 에이전트에게 “todomvc 데모를 열고 항목을 세 개 추가해줘”라고 부탁한다고 생각해볼게요.

에이전트가 실행할 명령어 흐름은 대략 이렇게 됩니다.

playwright-cli -s=todo open https://demo.playwright.dev/todomvc/ --headed
playwright-cli -s=todo snapshot --filename=todo.yaml

스냅샷 파일을 읽어서 입력창의 참조 ID를 확인한 다음, 항목을 추가합니다.

playwright-cli -s=todo fill e3 "Read book"
playwright-cli -s=todo press Enter

playwright-cli -s=todo fill e3 "Buy groceries"
playwright-cli -s=todo press Enter

playwright-cli -s=todo fill e3 "Reply to email"
playwright-cli -s=todo press Enter

작업 결과를 확인하기 위해 스크린샷을 찍고 세션을 정리합니다.

playwright-cli -s=todo screenshot --filename=result.png
playwright-cli -s=todo close

여기서 핵심은 에이전트가 매 단계마다 페이지 전체를 컨텍스트에 끌어올리지 않는다는 점입니다. 필요한 정보만 골라보고, 다음 명령어를 결정하고, 결과는 파일로 떨어뜨려서 사람이 사후에 확인할 수 있게 합니다. 토큰을 아끼면서도 안정적인 자동화가 가능해지는 거죠.

마치며

Playwright CLI는 코딩 에이전트가 브라우저를 다루는 방식을 한 단계 정돈한 도구입니다. Playwright의 성숙한 브라우저 추상화 위에 명명된 세션, 토큰 효율적인 출력, 그리고 에이전트가 직접 컨텍스트를 제어할 수 있는 자유도를 얹었어요. 같은 팀이 만든 Playwright MCP와 경쟁한다기보다는, 코딩 에이전트가 동작하는 환경의 폭을 더 넓게 커버하는 보완재로 봐도 좋겠습니다.

지금은 0.x 버전대라서 명령어 표면이 더 다듬어질 여지가 있긴 하지만, Playwright 팀이 직접 만들고 유지보수한다는 점은 큰 신뢰 요소입니다. 평소 Playwright로 E2E 테스트를 작성하던 분이라면 거의 같은 모델로 에이전트 자동화를 시작할 수 있고, 새 도구를 처음 만나는 분이라도 --help만 보고도 빠르게 입문할 수 있게 만들어져 있어요.

브라우저 자동화를 LLM이 자연어로 직접 운전하는 접근이 더 궁금하다면 browser-use도 같이 살펴볼 만합니다. 더 자세한 명령어 레퍼런스와 최신 변경 사항은 Playwright CLI 공식 저장소에서 확인할 수 있습니다.

This work is licensed under CC BY 4.0 CC BY

개발자를 위한 뉴스레터

달레가 정리한 AI 개발 트렌드와 직접 만든 콘텐츠를 전해드립니다.

Discord