AI QA 에이전트가 "all features working, pass"라고 리포트를 올렸다. 직접 열어봤더니 캔버스가 텅 비어 있었다. dev.to에 공개된 이 실제 사례는 단순한 해프닝이 아니다. AI 도구가 워크플로우 깊숙이 들어온 지금, '에이전트가 통과시켰다'는 말이 '실제로 동작한다'는 말과 같지 않을 수 있다는 걸 가장 선명하게 보여주는 장면이다.
빈 화면을 '정상'으로 판정한 이유
Claude + Chrome MCP 기반 자동화 QA를 운영하던 개발자는 false positive의 원인을 두 가지로 좁혔다. 첫째는 hidden tab throttling이다. Chrome MCP는 대부분 백그라운드 탭에서 동작하는데, 브라우저는 전력 절약을 위해 숨겨진 탭의 requestAnimationFrame을 사실상 멈춰버린다. 실측 결과는 충격적이다. document.visibilityState가 hidden인 상태에서 3.37초 동안 rAF 실행 횟수는 정확히 0. setInterval도 예상 횟수의 1/8로 쪼그라들었다. JS는 에러 없이 실행되고, 이벤트 핸들러도 반응한다. 하지만 픽셀은 그려지지 않는다. AI는 스크린샷과 에러리스트만 보고 "애니메이션 시작, 에러 없음, 통과"라고 판정한다.
두 번째 함정은 "JS 상태가 건강하다"는 것과 "기능이 실제로 동작한다"는 것을 혼동하는 구조다. onclick 연결 확인, 라이브러리 로드 완료, JS 에러 없음—이 세 가지가 모두 사실이어도 캔버스는 비어 있을 수 있다. AI QA가 코드 경로의 건강 상태를 기능 동작의 증거로 오독하는 순간, false positive는 구조적으로 발생한다. 해결책은 단순하다. <canvas>, <input type="file">, requestAnimationFrame 등 동적 기능이 코드에서 발견되면, visible 탭에서 직접 상호작용 후 스크린샷으로 렌더링 결과를 확인하는 행동 검증을 필수로 요구해야 한다. "코드에 존재하지만 동작 미확인"은 절대 통과로 처리할 수 없다.
AI 자동화가 넓어질수록, 공격 표면도 넓어진다
AI 도구 신뢰 문제는 QA 정확도에만 그치지 않는다. GeekNews를 통해 확산된 사례에서 LinkedIn 채용 담당자를 사칭한 공격자는 정상적인 React/Web3 과제로 위장한 GitHub 저장소를 전달했다. 실행하면 tailwind.config.js 안에 숨겨진 27KB 난독화 코드가 활성화된다. ls -la로 보면 30,987바이트짜리 설정 파일이지만, 편집기에서는 고작 97줄만 보인다. 수천 개의 공백 뒤에 악성코드가 숨어있는 구조다.
1단계 드로퍼는 원격 서버에서 AES-256-CBC로 암호화된 2단계 페이로드를 내려받아 실행한다. 약 10분간의 동적 분석 결과 확인된 구성은 네 가지다. Socket.IO 기반 원격 제어 백도어(scdata), 브라우저·지갑 탈취기(ldata), 재귀 파일 스캐너, 클립보드 감시기. 포트 7646으로 2,588건의 파일 업로드가 발생했고 수집 대상에는 .env, SSH 키, ~/.aws, ~/.azure, 쉘 히스토리, 소스 코드까지 포함된다. 무서운 건 공격 진입점이 바로 설정 파일이었다는 점이다. 개발자들이 습관적으로 신뢰하는 tailwind.config.js가 실행 코드로 둔갑했다.
Zoviz MCP가 보여주는 자동화의 반대편
같은 시기, Claude + MCP 생태계에서는 다른 방향의 실험도 진행 중이다. Zoviz MCP 서버는 Claude Desktop에 브랜드 디자인 자동화를 붙인다. 로고, OG 이미지, 소셜 배너, 브랜드 가이드라인을 대화 한 번으로 생성한다. 프로토타이핑 속도를 끌어올리는 데는 분명히 유용하다. 사이드 프로젝트 런칭이나 해커톤 데모에서 "디자이너 없이 그럴듯한 브랜드"를 만드는 시간을 실질적으로 단축한다.
그런데 이 자동화 편의성이 바로 LinkedIn 악성코드 사례와 맞닿는 지점이다. MCP 서버를 연결한다는 것은 외부 엔드포인트가 에이전트를 통해 내 환경에 접근하는 통로를 여는 행위다. https://mcp.zoviz.com/mcp처럼 퍼블릭 MCP URL을 추가할 때, 해당 서버가 어떤 도구를 노출하고, 어떤 데이터를 어디로 보내는지 사전에 검토하는 습관이 반드시 필요하다. 자동화의 편의성과 보안 신뢰성은 함께 설계하지 않으면 한쪽이 다른 쪽을 잠식한다.
프론트엔드 개발자를 위한 세 가지 검증 원칙
이 세 사례가 하나의 질문으로 수렴된다. AI 도구가 '됐다'고 말할 때, 그걸 어떻게 믿을 것인가. 실무에서 지금 당장 적용할 수 있는 원칙을 세 가지로 정리한다.
첫째, AI QA에는 행동 검증 테이블을 강제하라. 코드에 동적 기능이 존재하면 반드시 visible 상태에서의 렌더링 확인을 요구한다. "존재하지만 미확인"은 통과가 아니다. 에이전트 리포트에 feature-coverage 테이블이 없으면 완료로 인정하지 않는 규칙을 팀 단위로 세워야 한다.
둘째, 낯선 저장소는 격리 환경에서만 실행하라. npm install이나 yarn start 전에 package.json, 수명 주기 스크립트, 설정 파일을 먼저 검토한다. 채용 과제든 오픈소스 레포든, 실제 SSH 키·브라우저 프로필·클라우드 자격증명이 없는 일회용 VM이나 컨테이너를 기본 실행 환경으로 삼는다.
셋째, MCP 연결은 도구 노출 범위와 데이터 흐름을 먼저 확인하라. 편의성이 높을수록 공격 표면도 넓어진다. 서드파티 MCP 서버를 연결하기 전에 어떤 툴을 제공하고, 어떤 데이터를 외부로 전송하는지 명시적으로 파악하는 것이 선행되어야 한다.
AI 도구는 믿어야 하지만, 맹목적으로 믿으면 안 된다
AI QA, AI 자동화 디자인, AI 기반 코드 생성—이 모든 도구가 생산성을 실질적으로 끌어올린다는 건 부정하기 어렵다. 빈 캔버스를 정상으로 판정하거나, 설정 파일에 백도어가 숨어 있거나, MCP 연결이 예상치 못한 범위로 확장될 수 있다는 사실이 AI 도구를 쓰지 말아야 한다는 결론으로 이어지지는 않는다. 하지만 "AI가 통과시켰다"는 말을 "실제로 동작한다"는 말과 동치로 쓰는 순간, 프로덕트 품질과 보안은 동시에 흔들린다.
빠른 실험과 검증을 반복하는 것, 그게 지금 프론트엔드 개발의 핵심 사이클이다. 그런데 그 사이클이 제대로 돌아가려면 AI의 출력을 무조건 신뢰하는 게 아니라, 어디서 검증이 끊기는지를 구조적으로 설계하는 것이 먼저다. AI가 됐다고 말할 때, 진짜 된 건지 확인하는 것—그게 지금 프론트엔드 개발자에게 가장 중요한 역량이 되고 있다.