
AI 시각 QA의 '움직이는 것처럼 보이지만 움직이지 않는' 문제 — hidden tab의 rAF throttle과 JS state 과신
요약
AI를 활용한 웹 QA 과정에서 hidden tab의 rAF(requestAnimationFrame) 억제로 인해 애니메이션이 멈추는 현상과 JS 상태값만으로 동작을 오판하는 문제를 분석합니다. 이를 해결하기 위해 가시적 탭 사용과 실질적인 시각적 결과물 검증을 권장합니다.
핵심 포인트
- 비표시 탭(hidden tab)에서는 브라우저 절전 기능으로 인해 rAF가 중단됨
- JS 에러가 없더라도 canvas 묘화나 애니메이션은 실행되지 않을 수 있음
- 코드의 건전성(JS state)과 실제 기능 동작(Visual output)을 구분해야 함
- QA 시 visible tab 사용 및 스크린샷을 통한 실질적 묘화 확인 필수
AI에게 QA를 맡기던 시기, "모든 기능 정상, 합격입니다"라고 보고된 툴을 직접 열어보니 canvas에 아무것도 그려져 있지 않았던 적이 있습니다.
AI가 거짓말을 한 것은 아닙니다. AI가 보고 있던 환경에서는 정말로 "움직이는 것처럼 보였던" 것입니다.
다국어 Web 툴 그룹의 QA를 AI(Claude + Chrome MCP)에게 맡기는 운용 과정에서, 이 불일치의 원인은 두 가지로 좁혀졌습니다.
원인 1: hidden tab에서는 requestAnimationFrame이 멈춘다
Chrome MCP(Claude in Chrome)는 통상적으로 hidden tab(비표시 탭)에서 동작합니다. 그리고 브라우저는 절전(省電力)을 위해 비표시 탭의 requestAnimationFrame을 대폭 억제합니다.
이 환경에서 canvas 묘화나 애니메이션을 가진 툴을 QA하면, JS는 실행되고, 에러도 발생하지 않으며, 이벤트 핸들러도 발화합니다. 하지만 묘화는 0프레임으로 끝납니다. AI는 스크린샷과 JS의 실행 결과를 보고 "애니메이션 시작, 에러 없음, 합격"이라고 판정합니다. 실행된 것과 묘화된 것은 별개인데, hidden tab에서는 그 구분이 되지 않습니다.
공개 전 재현 시험(2026년 7월 10일)
"예전에는 그랬다"라는 식의 기사가 되지 않기 위해, 공개 직전에 실기(実機)로 확인했습니다. Chrome MCP로 탭을 열고, rAF 카운터를 돌린 결과:
| 항목 | 실측값 |
|---|---|
| document.visibilityState | hidden |
| ... |
rAF는 throttle(조절) 수준이 아니라, 완전히 멈춰 있었습니다.
게다가 setInterval도 약 1/8로 간소화되며, setTimeout 자체도 지연됩니다. 즉, rAF 기반의 애니메이션뿐만 아니라 타이머 구동 로직 전반이 hidden tab에서는 신뢰할 수 없습니다.
대책
- 탭을 열 때
active: true를 명시하여, visible tab에서 열기 - visible tab에서 조작을 트리거하고, 수 초 기다린 후 스크린샷으로 묘화물의 실재를 확인하기
- 어떻게든 hidden tab에서 판정해야 하는 경우에는, 보고에 "동적 묘화는 실시각(実視覚)으로 미관측"이라고 기재하기. 말없이 합격 처리하지 않기
원인 2: 「JS state의 건전성」과 「기능의 동작」의 혼동
또 다른 함정은 AI의 QA 보고에 자주 등장하는 이러한 종류의 합격 근거입니다.
onclick 배선 확인. JS 에러 0건. 라이브러리는 로드 완료. → 합격
이것들은 전부 코드 패스(code path)의 건전성일 뿐, 기능이 동작했다는 증거가 아닙니다. 배선이 올바르더라도 묘화되지 않을 수 있습니다(원인 1). 에러가 발생하지 않더라도 다운로드되는 파일이 비어 있을 수 있습니다.
대책으로서, 템플릿을 grep하여 동적 기능을 먼저 검출하고, 히트한 기능마다 실동작 체크를 의무화했습니다.
| 코드에 있는 것 | 필수 실동작 체크 |
|---|---|
<canvas> | visible tab에서 조작 → 수 초 후의 스크린샷에 묘화물이 있는가 |
<input type="file"> | 더미 파일을 upload → 프리뷰의 src가 비어 있지 않은가 |
download 속성 / toBlob | 버튼 클릭 → Blob 생성이 관측되는가 |
mousedown / touchstart | 이벤트 발화 → state/transform이 실제로 변화했는가 |
requestAnimationFrame | 시간 경과 후 transform 값이 변화하고 있는가 |
그리고 QA 보고에는 기능 커버리지 표를 필수로 지정하고, "코드상에는 존재하지만 실동작은 미확인"인 상태로 합격을 내는 것을 금지했습니다. 규칙으로는 그것뿐입니다. 그것만으로도 누락되는 사례는 눈에 띄게 줄었습니다.
덤: 스크린샷과 DOM의 모순 검출
시각 QA의 부수적인 효과로, 외관과 코드의 대조가 효과를 발휘합니다. "클래스는 text-secondary (시안색)인데 묘화는 회색"과 같은, CSS 오버라이트(overwrite)나 캐스케이드(cascade) 문제를 근거를 가지고 지적할 수 있습니다. 사람이 하면 "왠지 색이 다른 것 같다"에서 멈추기 쉬운 부분입니다.
제한 및 주의
hidden tab의 throttle은 브라우저의 절전 사양이기 때문에, Chrome 측의 변경으로 거동이 바뀔 가능성은 있습니다. 운용상의 원칙은 "hidden tab이니까 안 된다"가 아니라 "동적 묘화는 반드시 visible 상태에서 확인한다"에 두고 있습니다.
실제 동작 체크에는 시간과 토큰 비용이 발생합니다. 모든 도구 × 모든 기능에 적용하기에는 비용이 너무 크기 때문에, grep으로 동적 기능을 검출한 도구에만 적용하는 방식으로 운용하고 있습니다.
검증: 2026년 4~6월 운용 + 2026년 7월 10일 재현 시험 실시. 환경: Claude + Chrome MCP / Windows 11.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기