내 AI QA 에이전트는 "모든 기능 작동 중"이라고 했지만, 캔버스는 비어 있었습니다. 실제로 무엇을 보고 있었던 걸까요?
요약
AI QA 에이전트가 브라우저의 숨겨진 탭 환경에서 발생하는 렌더링 이슈를 제대로 감지하지 못해 발생하는 거짓 양성(false positive) 문제를 분석합니다. Chrome MCP 사용 시 rAF 제한과 JS 상태와 실제 기능 동작의 차이를 해결하기 위한 구체적인 가이드를 제공합니다.
핵심 포인트
- 숨겨진 탭에서는 rAF와 타이머가 제한되어 렌더링이 중단될 수 있음
- JS 에러가 없다고 해서 기능이 정상 작동하는 것은 아님
- 탭 가시성을 확보하거나 스크린샷을 통한 시각적 검증 필수
- 코드 경로 건전성과 실제 기능 동작을 구분하여 검증해야 함
처음으로 QA(Quality Assurance) 업무를 AI 에이전트에게 위임했을 때, 에이전트는 한 도구에 대해 "모든 기능 작동 중, 통과(pass)"라고 승인했습니다. 하지만 제가 직접 도구를 열어보니 캔버스는 비어 있었습니다.
AI는 거짓말을 한 것이 아니었습니다. AI가 바라보고 있던 환경에서는 도구가 정말로 작동하는 것처럼 보였습니다.
저는 Claude + Chrome MCP를 사용하여 대규모 웹 도구 플릿(fleet)에 대해 시각적 QA를 수행하고 있으며, 이러한 유형의 거짓 양성(false positive)은 정확히 두 가지 원인으로 거슬러 올라갑니다.
원인 1: 숨겨진 탭에서 requestAnimationFrame이 중단됨
Chrome MCP는 일반적으로 숨겨진(백그라운드) 탭에서 작동합니다. 그리고 브라우저는 전력을 아끼기 위해 숨겨진 탭에서 requestAnimationFrame (rAF)을 공격적으로 제한(throttle)합니다.
해당 환경에서 캔버스나 애니메이션 기능을 QA하면 다음과 같은 일이 발생합니다. JS(JavaScript)는 실행되고, 에러는 발생하지 않으며, 이벤트 핸들러(event handlers)는 응답하지만 — 렌더링은 0프레임에서 종료됩니다. AI는 스크린샷과 깨끗한 JS 결과값을 보고 "애니메이션 시작됨, 에러 없음, 통과"라고 결론을 내립니다. 코드가 실행되는 것과 픽셀이 렌더링되는 것은 서로 다른 이벤트이며, 숨겨진 탭은 이 차이를 지워버립니다.
게시 전 재현 테스트 (2026년 7월 10일)
이 글이 단순히 "옛날이야기"로 남는 것을 원치 않았기에, 게시 직전에 측정을 다시 수행했습니다. Chrome MCP를 통해 탭을 열고 rAF 카운터를 실행했습니다:
| 측정 항목 | 결과 |
|---|---|
| document.visibilityState | hidden |
| ... |
rAF는 제한(throttled)된 것이 아니었습니다. 중단(stopped)된 것이었습니다 — 0프레임이었습니다.
그리고 추가적인 발견 사항으로: setInterval은 예상 속도의 약 1/8로 급감했으며, 심지어 setTimeout조차 오차가 발생했습니다. 따라서 이는 단지 rAF 기반의 애니메이션만의 문제가 아닙니다. 숨겨진 탭에서는 일반적으로 타이머 기반 로직(timer-driven logic)을 신뢰할 수 없습니다.
해결 방법
- 탭을
active: true로 열어 가시성을 확보하세요. - 가시적인 탭에서 상호작용을 트리거하고, 몇 초간 기다린 다음, 스크린샷을 찍어 렌더링된 출력이 실제로 존재하는지 확인하세요.
- 반드시 숨겨진 탭에서 평가해야 한다면, 보고서에 "동적 렌더링이 시각적으로 관찰되지 않음"이라고 명시해야 합니다. 절대 조용히 통과시키지 마세요.
원인 2: "정상적인 JS 상태"를 "기능 작동"과 혼동함
두 번째 함정은 AI QA 보고서에서 다음과 같은 통과 근거(pass rationale)로 나타납니다:
onclick 연결 확인됨. JS 에러 없음. 라이브러리 로드됨. → 통과 (PASS)
이 모든 내용은 코드 경로(code-path)의 건전성을 설명할 뿐, 기능의 동작(feature behavior)을 설명하는 것이 아닙니다. 아무것도 렌더링되지 않는 상태에서도 연결(wiring)은 올바를 수 있습니다(원인 1). 다운로드된 파일이 비어 있어도 에러는 발생하지 않을 수 있습니다.
나의 해결책: 먼저 템플릿을 grep하여 동적 기능(dynamic features)을 찾은 다음, 검색된 모든 항목에 대해 동작 확인(behavior check)을 요구합니다.
| 코드에서 발견됨 | 요구되는 동작 확인 |
|---|---|
<canvas> | 보이는 탭에서 상호작용 → 일정 시간 지연 후 스크린샷을 찍어 렌더링된 콘텐츠 확인 |
| ... |
QA 보고서에는 반드시 기능 커버리지(feature-coverage) 테이블이 포함되어야 하며, "코드에는 존재하지만 동작이 검증되지 않음"은 절대 통과(pass)로 판정될 수 없습니다. 이것이 전체 규칙입니다.
이것만으로도 오탐(false positives)을 극적으로 줄일 수 있었습니다.
보너스: 스크린샷 vs DOM 모순 확인
시각적 QA(visual QA)의 부수적인 이점은 코드가 주장하는 바와 픽셀이 보여주는 바를 교차 검증하는 것입니다. "클래스는 text-secondary(청록색)이지만 회색으로 렌더링됨" — 이러한 캐스케이드(cascade) 및 오버라이드(override) 버그는 증거와 함께 포착됩니다. 인간은 "색감이 왠지 이상하다"라는 단계에서 머뭇거리는 경향이 있습니다.
한계 및 주의사항
숨겨진 탭 제한(Hidden-tab throttling)은 브라우저의 전력 절약 동작이므로, Chrome이 이를 변경할 수 있습니다. 나의 운영 원칙은 "숨겨진 탭은 나쁘다"가 아니라, "동적 렌더링은 반드시 보이는 상태에서 검증되어야 한다"입니다.
동작 확인은 시간과 토큰(tokens)을 소모합니다. 모든 도구의 모든 기능에 대해 이를 실행하는 것은 너무 무겁습니다. 나는 grep이 동적 기능을 찾아낸 도구에 대해서만 이를 요구합니다.
검증 완료: 2026년 4월~6월 운영 환경, 2026년 7월 10일 재현됨. 환경: Claude + Chrome MCP / Windows 11.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기