글

라벨이 코드검증인 게시물 표시

사실 검증 조건: AI 검수자가 제안한 두 문장, 왜 다시 반려됐나

AI가 제안한 수정 문장도 원문과 다시 대조해야 한다. 출처가 존재하는지보다 그 출처의 조건이 실제 문장에 남아 있는지가 승인 기준이다. 2026년 10월 13일 검수 기록에는 이전 검수자가 제안한 문장 두 곳을 다시 FAIL로 돌린 사례가 남아 있다. AI의 설명을 문서나 안내문에 옮기는 개발자라면 이 차이가 중요하다. 검수 요청에 “사실을 확인해”만 적지 말고, 주장·출처·문장과 반려 조건을 같이 넘겨야 한다. 검수자의 문장도 왜 틀렸을까 해당 기록에서 형식 검사와 가독성 검사는 통과했다. 그런데 원고 A의 첫 답과 원고 B의 결론은 각 원고가 보관한 근거와 맞지 않았다. 두 문장 모두 앞선 검수자가 직접 제안했던 표현이었다. 한 문장은 적용 대상을 넓혔다. 다른 문장은 특정 선택지의 기한을 모든 선택지의 소멸로 바꿨다. 문장은 매끈했지만 출처가 허용한 범위보다 강했다. 이를 특정 모델의 우열로 해석하지 않는다. 확인된 것은 두 문장의 오류와 반려 이유다. 모델별 누락률이나 검수 정확도를 비교한 실험은 이 기록에 없다. 사례 A: 처음 계약의 조건이 빠졌다 원고 A는 계약을 중간에 끝낼 수 있는 조건을 설명했다. 검수 기록에 남은 전·후 문장은 다음과 같다. > 전: “해지 특약이 없다면 세입자 혼자 계약을 끝낼 수 없어서, 합의하지 못하면 만료일까지 월세를 내야 합니다.” > > 후: “처음 정한 계약기간 중이고 해지 특약이 없다면, 합의하지 못하는 한 만료일까지 월세를 내야 합니다.” ‘후’는 그다음 검수자가 새로 제시한 수정안이다. 이 기록만으로 수정 적용이나 최종 PASS까지 확인한 것은 아니다. 빠진 부분은 “처음 정한 계약기간 중”이다. 저장된 법령의 제6조의2는 묵시적으로 갱신된 계약에서 임차인이 언제든 해지를 통지할 수 있다고 정한다. 효력은 임대인이 통지를 받은 날부터 3개월이 지나면 생긴다. 제6조의3 제4항은 갱신요구권으로 갱신된 계약의 해지에도 제6조의2를 준용한다. 그래서 ‘특약이 없다’는 조건만으...

네이버 SmartEditor 붙여넣기: 성공 이벤트보다 본문 일치가 먼저다

이미지
답부터 말하면 붙여넣기 이벤트가 받아들여졌는지가 아니라, 편집기 본문이 넣으려던 전체 글과 같아졌는지를 완료 조건으로 삼아야 한다. 이벤트를 보내기 전에 변경 감시를 시작하고, 제한 시간 안에 정규화한 누적 본문이 정확히 일치할 때만 다음 단계로 넘어가는 방식이다. 2026년 9월 27일 한 번의 SmartEditor 자동화 기록에서 첫 구간은 48ms, 두 번째 구간은 239ms 뒤 반영됐다. 이후 다시 연 예약 글에서는 원고·주입 대상·편집기 본문이 각각 2800자로 일치했다. 그 예약은 이 실행이 아니라 동시에 돌던 다른 작업이 저장한 것이다. 48ms와 239ms는 속도 기준이나 성공률이 아니라 한 실행의 관찰값이다. 왜 paste 이벤트 성공만으로는 부족했나? 조사 중 합성 paste 이벤트는 defaultPrevented:true 를 반환했다. 그런데 직후 본문은 여전히 한 문단이었고, 조금 뒤에는 시험용 두 문단이 들어와 있었다. 문제는 이벤트 수락과 화면 반영이 같은 순간이 아니라는 점이다. dispatchEvent() 반환값, iframe 포커스, 즉시 읽은 문단 수는 모두 완료 조건이 아니었다. 선택 영역이 iframe 루트에 잡힌 관찰도 과거 60초 지연의 원인으로 확정할 수 없었다. 그렇다면 무엇을 기다려야 할까. 편집기가 실제로 만들어 낸 최종 상태를 기다려야 한다. 고정 sleep 대신 무엇을 기다렸나? 성공한 경로는 MutationObserver 를 붙여넣기 전에 등록했다. 그 다음 clipboard 이벤트를 보낸 뒤, 공백과 제로폭 문자를 정규화한 전체 본문을 매 변경마다 비교했다. 아래는 실제 코드를 줄인 형태다. const done = new Promise((resolve, reject) => { const timer = setTimeout(() => { observer.disconnect(); reject(new Error("paste timeout")); ...

테스트 113개 다 통과했는데 실제론 0개를 긁었다 — AI가 짠 수집기의 함정

이미지
AI에게 수집기(웹에서 데이터를 긁어오는 코드) 두 개를 맡겼더니, 테스트 113개를 전부 통과시켰다. 초록불. 그런데 실제로 돌려보니 한쪽은 0개를 긁었다. 전에 이 블로그에서 이 트렌드 수집 도구의 데이터 소스가 어떻게 죽는지 썼다. 이번엔 거기에 기능을 붙이다가 더 불편한 걸 배웠다. 테스트는 통과했는데 코드는 작동하지 않았다 — 이게 어떻게 동시에 참일 수 있나. 한 줄이면 이렇다. 추정한 입력에 맞춰 짠 테스트는 그 추정이 맞다는 것만 증명한다. 실제 세계가 추정과 같은지는 아무도 검증하지 않았다. 누가 읽으면 좋은가 AI(Claude·Cursor 등)에게 코드를 맡기고 테스트 초록불을 받아본 사람 특히 외부 API나 웹페이지를 긁는 코드를 AI에 시켜본 사람 “테스트 다 통과했으니 됐겠지”로 넘어간 적 있는 사람 113개 초록불, 라이브에선 0개 무슨 일이었나부터. 트렌드 도구에 “해외에서 잘나가는 신제품”을 자동으로 잡아낼 수집기 두 개를 붙이려 했다. 하나는 Show HN(해커뉴스 신제품 게시판), 하나는 Product Hunt(신제품 등록 사이트). 작업은 서브에이전트에 맡겼다. 테스트를 먼저 쓰고 구현하는 방식으로, 규칙도 빡빡하게 줬다. 에이전트는 코드와 테스트를 짜서 “113개 통과”를 보고했다. 여기서 멈췄으면 끝이었다. 초록불이니까. 그런데 안 믿고 실제로 돌렸다. Show HN은 실제 런칭 5건을 정확히 긁어왔다. Product Hunt는 0개였다. 대신 에러 하나 — “제품을 하나도 파싱하지 못함”. 테스트는 왜 통과했나 이게 핵심이다. 0개를 긁는 코드의 테스트가 어떻게 113개나 통과했나. 답은 단순했다. 에이전트는 Product Hunt의 실제 응답을 한 번도 본 적이 없다. 줄 수도 없었다. 그 응답은 실제로 한 번 긁어봐야 나온다. 그래서 “이렇게 생겼겠지” 하고 가짜 샘플을 만들었고, 그 샘플에 맞춰 파싱 코드를 짰고, 다시 그 샘플로 테스트를 돌렸다. 테스트는 “추정이 추정과 일치...