상황
코딩 에이전트가 스스로 버그를 고치는 장면은 이제 익숙하다. 타입 에러를 내면 시그니처를 고치고, 테스트가 빨간불이면 로직을 수정하고, 서버가 500을 뱉으면 스택 트레이스를 따라간다. 이 능력의 정체는 지능이라기보다 **폐루프(closed loop)**다.
실행 → 에러/실패 신호 → 수정 → 재실행
루프가 돌려면 가운데 단계, 즉 기계가 읽을 수 있는 실패 신호가 반드시 있어야 한다. 컴파일러 에러, 테스트 assertion, HTTP 상태 코드는 모두 텍스트로 된 명시적 신호다. 에이전트가 잘 고치는 결함과 못 고치는 결함의 경계선은 정확히 이 신호의 유무를 따라 그어진다.
문제
문제는 신호가 구조적으로 부재한 결함 영역이 존재한다는 것이다. 코드는 틀렸는데 콘솔은 조용한 경우들이다.
- CSS·렌더링:
z-index스태킹 컨텍스트가 붕괴해 모달이 헤더 뒤에 깔려도, 이미지 로드가 레이아웃을 밀어내 CLS가 치솟아도, 에러는 한 줄도 발생하지 않는다. 브라우저는 "잘못된 화면"을 성공적으로 렌더링한다. - 접근성:
aria-expanded가 실제 상태와 반대로 박혀 있어도 스크린 리더 사용자만 길을 잃을 뿐, 어떤 런타임도 예외를 던지지 않는다. - 실기기 성능: 개발 머신에서는 매끄러운 인터랙션이 저사양 안드로이드에서는 수백 ms씩 버벅여도, 로컬 개발 환경에는 그 사실을 알려줄 것이 아무것도 없다.
신호가 없으면 루프가 돌지 않는다. 에이전트는 이 결함들을 못 고치는 게 아니라, 고쳐야 한다는 사실 자체를 알 수 없다.
flowchart LR
subgraph loop["자기수정 루프가 도는 영역"]
A[타입 에러] --> S1[명시적 실패 신호]
B[테스트 실패] --> S1
C[HTTP 500] --> S1
S1 --> FIX[에이전트 수정] --> RERUN[재실행] --> S1
end
subgraph blind["콘솔이 조용한 사각지대"]
D[스태킹 컨텍스트 붕괴]
E[CLS / INP 저하]
F[잘못된 aria 상태]
D & E & F --> S0[신호 없음 → 루프 정지]
end
"스크린샷을 찍어 VLM에게 보여주면 되지 않나"
가장 흔한 반론이다. 에이전트가 헤드리스 브라우저로 스크린샷을 찍고 비전 모델이 판정하면 시각 결함도 폐루프에 들어오지 않느냐는 것이다.
부분적으로만 맞다. 스크린샷 한 장은 특정 뷰포트 × 특정 폰트 환경 × 특정 시점의 표본 하나일 뿐이다. 표본 밖에 있는 것들:
- 저사양 안드로이드 기기의 서브픽셀 렌더링 차이
- 다크모드에서만 무너지는 명도 대비
- 장문 한글 텍스트가 특정 폭에서만 일으키는 줄바꿈 겹침
- 스크롤·인터랙션 중에만 발생하는 레이아웃 시프트
VLM 검증은 사각지대를 좁히지만 없애지 못한다. 표본 추출 방식의 검증은 표본 설계가 커버하는 만큼만 본다.
성능 진단은 아예 훈련 데이터 밖이다
성능 사각지대는 한 층 더 깊다. P75 INP 같은 필드 지표는 실사용자 기기에서 수집되어 자사 RUM 대시보드에만 존재한다. 웹에 공개된 적이 없으니 어떤 모델도 학습할 수 없고, 앞으로도 학습할 수 없다. 이것은 일시적 한계가 아니라 데이터 소유권에서 오는 구조적 해자다.
그리고 이커머스는 이 지표가 돈과 직결되는 것이 정량화된 드문 도메인이다 — 업계에서 반복 인용되는 수치로, 모바일에서 0.1초 개선이 전환율 약 8% 상승과 상관을 보인다. 신호가 없어서 에이전트가 못 보는 영역이, 하필 비즈니스 임팩트가 가장 선명한 영역과 겹친다.
접근과 판단
사각지대의 원인이 "신호 부재"라면, 처방은 결함 유형별 대응이 아니라 하나로 수렴한다. 사각지대에 기계가 읽을 수 있는 실패 신호 — 테스트 이론의 용어로 오라클(oracle) — 를 공급하는 것.
에이전트를 더 똑똑하게 만드는 방향이 아니라, 환경이 신호를 내도록 만드는 방향이다. AI 생성 코드가 흐르는 파이프라인에 세 개의 관문을 CI로 묶는다.
columns: 3
items:
- icon: "👁"
title: 시각 회귀 테스트
desc: 기준 스크린샷 대비 픽셀 diff가 임계값을 넘으면 실패. 스태킹 붕괴·줄바꿈 겹침이 빨간불이라는 텍스트 신호로 변환된다
- icon: "⏱"
title: 성능 임계값 게이트
desc: Lighthouse CI 등으로 INP·LCP p75 예산을 강제. 필드 RUM 데이터로 임계값을 보정해 실기기 저하를 사전 차단
- icon: "🧭"
title: E2E 행동 검증
desc: "모달이 열리고 포커스가 이동하는가"를 assertion으로. aria 상태 불일치가 접근성 셀렉터 기반 테스트 실패로 드러난다
세 관문의 공통점은 콘솔이 조용하던 결함을 exit code 1로 번역한다는 것이다. 일단 실패 신호가 텍스트로 존재하면, 에이전트의 자기수정 루프는 타입 에러를 고칠 때와 동일한 메커니즘으로 돌기 시작한다. 사람이 매번 눈으로 검수하는 대신, 사람은 오라클을 설계하고 임계값을 보정하는 층으로 올라간다.
구현
관문 설계 시의 판단 기준:
- 시각 회귀: 표본 매트릭스를 사각지대에 맞춰 설계한다 — 최소 뷰포트 2종(모바일/데스크톱) × 컬러 스킴 2종(라이트/다크) × 장문 텍스트 케이스. VLM 단발 검증이 놓치던 축들을 표본 축으로 승격시키는 것이 핵심이다.
- 성능 예산: 랩 지표(Lighthouse)만으로 시작하되, 임계값의 근거는 자사 RUM의 p75 분포에서 가져온다. 랩 지표는 회귀 감지용, 필드 지표는 임계값 보정용으로 역할을 나눈다.
- E2E: 구현 세부가 아니라 사용자 행동 단위로 작성한다.
getByRole같은 접근성 트리 기반 셀렉터를 쓰면 기능 검증과 aria 검증이 한 테스트에서 동시에 이루어진다.
결과
이 분석에서 커리어 층위의 결론이 하나 따라 나온다. '스택'과 '플랫폼'을 구분해야 한다.
프레임워크 API 지식은 공개 문서와 코드가 대량으로 존재하므로 AI가 가장 빨리 흡수하는, 감가상각이 가장 가파른 자산이다. 반면 이 글이 다룬 사각지대의 기반 — 렌더링 파이프라인, 스태킹 컨텍스트와 CSSOM, 성능 계측과 RUM — 은 프레임워크가 교체되어도 살아남는 플랫폼 층이고, 하필 AI의 폐루프가 닿지 못하는 층과 정확히 겹친다. 오라클을 설계하려면 결함이 어느 층에서 발생하는지 알아야 하므로, 플랫폼 층 이해는 오라클 설계 능력의 전제 조건이기도 하다.
배운 것
- 에이전트의 능력 경계는 모델 성능이 아니라 피드백 루프의 폐쇄 여부가 결정한다. "AI가 이걸 고칠 수 있나"라는 질문은 "이 결함은 기계가 읽을 수 있는 실패 신호를 내는가"로 바꿔 물어야 한다.
- 신호가 없는 영역을 만나면 처방은 항상 같다: 오라클을 공급하라. 에러 신호가 구조적으로 부재한 결함 영역(상황) → 시각 회귀·성능 임계값·E2E를 CI 관문으로 공급(기법) → 자기수정 루프가 돌기 시작(결과). 이 패턴은 프로젝트와 프레임워크에 무관하게 재사용된다.
- 필드 성능 데이터처럼 자사에만 존재하는 데이터에 묶인 판단은 AI가 원천적으로 학습할 수 없다. 무엇이 자동화될지 예측할 때는 기술 난이도보다 데이터 소유권을 먼저 봐야 한다.