TIL/Claude Code

[TIL][Claude Code] Playwright MCP 로 E2E 디버깅하기 — browser_snapshot 워크플로우

아람2 2026. 4. 2. 21:00
반응형

"저장" 버튼을 못 찾는다

FAILED - playwright._impl._errors.TimeoutError:
  Timeout 30000ms exceeded.
  Locator: get_by_role("button", name="저장")

로케이터가 틀렸나? 텍스트가 바뀌었나? 아니면 버튼이 아예 안 나오나?

에러 로그만 보고는 모른다

에러 로그만 보고 추측하면 생기는 일

에러: "저장" 버튼 Timeout
    ↓
추측: "텍스트가 바뀌었겠지" → name="Save" 로 변경
    ↓
실행 → 또 실패
    ↓
추측: "버튼이 아니라 link 겠지" → get_by_role("link") 로 변경
    ↓
실행 → 또 실패
    ↓
추측: "로딩이 느린가봐" → timeout 60초로 증가
    ↓
실행 → 또 실패 (60초 기다린 후)
    ↓
30분 소모

결국 browser_snapshot 찍어보니 모달이 버튼을 가리고 있었다

처음부터 스냅샷을 봤으면 3분이면 끝났다

browser_snapshot 먼저, 코드 수정은 나중에

디버깅 워크플로우 (4단계)

Step 1: 실패 재현
    ↓
Step 2: browser_snapshot → 실제 UI 상태 확인
    ↓
Step 3: "기대 상태" vs "실제 상태" 비교
    ↓
Step 4: 차이점 기반으로 코드 수정

Step 1: 실패 재현

pytest tests/step_definitions/test_bench_steps.py -k "저장" --headed -x

--headed 로 브라우저를 보면서, -x 로 첫 실패에서 멈춘다

Step 2: browser_snapshot

Claude Code 에 Playwright MCP 가 연결되어 있으면 실제 페이지를 볼 수 있다

> 지금 페이지 상태 확인해줘

Claude 가 browser_snapshot 을 호출하면 접근성 트리가 나온다

[dialog] 모달 제목
  [button] "닫기"
  [button] "확인"

[main]
  [button] "저장" (뒤에 가려져 있음)

여기서 바로 보인다 — dialog 가 main 위에 떠 있다

Step 3: 기대 vs 실제 비교

  기대 상태 실제 상태
모달 없음 Feature Release 모달 떠 있음
"저장" 버튼 보임 + 선택 가능 DOM 에 있지만 모달에 가려짐
Timeout 원인 버튼이 없어서 버튼은 있는데 선택 불가

이걸 먼저 정리해야 수정 방향이 나온다

Step 4: 코드 수정

# 원인: 모달이 버튼을 가림
# 수정: 저장 전에 모달 닫기
def click_save(self):
    self.dismiss_feature_release_modal()  # 모달 닫기 추가
    self.page.get_by_role("button", name="저장").click()

로케이터를 바꾸는 게 아니라 사전 조건을 추가하는 거였다

에러 로그만 보면 로케이터 문제로 착각한다

실제 사례 3가지

사례 1: 드롭다운이 안 열림

에러: get_by_role("option", name="Korean") Timeout
추측: option 텍스트가 바뀌었나?

snapshot 결과: 드롭다운이 열리지 않은 상태

option 이 없는 게 아니라 드롭다운을 먼저 열어야 했다

사례 2: 체크박스를 못 찾음

에러: get_by_role("checkbox") Timeout
추측: checkbox 가 아니라 switch 인가?

snapshot 결과: 체크박스가 스크롤 아래에 있어서 뷰포트 밖

scroll_into_view() 를 추가해서 해결

사례 3: 버튼이 비활성화

에러: click 후 아무 반응 없음 (Timeout 아님, 동작 안 함)
추측: 로케이터가 틀렸나?

snapshot 결과: 버튼이 disabled 상태

이전 Step 에서 필수 입력을 빠뜨려서 버튼이 활성화되지 않았다

스냅샷 vs 스크린샷

  browser_snapshot browser_take_screenshot
형태 접근성 트리 (텍스트) 이미지 (PNG)
정보량 요소 role, name, state 시각적 레이아웃
용도 로케이터 확인, 구조 파악 시각적 상태 확인
속도 빠름 느림

디버깅은 snapshot 으로 시작한다

스크린샷은 "눈으로 봐야 아는 것" (색상, 위치, 애니메이션) 에만 쓴다

MCP 연결 방법

# Playwright MCP 추가
claude mcp add --scope project playwright -- npx @anthropic-ai/mcp-server-playwright

연결하면 쓸 수 있는 도구들:

도구 용도
browser_navigate URL 로 이동
browser_snapshot 접근성 트리 확인
browser_click 요소 선택
browser_take_screenshot 스크린샷 저장

디버깅에서 가장 많이 쓰는 건 browser_snapshot 이다

사용법

# MCP 연결 확인
claude mcp list

# 디버깅 시 Claude Code 에서
> 검증 실패했어. 페이지 상태 확인해줘
# → Claude 가 browser_snapshot 호출
# → 접근성 트리 분석
# → 원인 파악 후 수정 제안

주의점

  • browser_snapshot접근성 트리 기반이다 — aria-hidden="true" 인 요소는 안 보인다
  • 확인 끝나면 바로 browser_close 해야 한다 — 열어둔 채로 코드 수정하면 세션이 꼬인다
  • pkill -f "Google Chrome" 은 절대 쓰면 안 된다 — 사용자의 일반 Chrome 까지 전부 죽는다
반응형