sgkstudio.
엔지니어링

QA 자동화, 크론 잡 303개를 혼자 검수하지 못했다 — 줄인 건 검수량

QA 자동화로 1인 개발의 검수 병목을 풀려면 검사를 빨리 돌리기보다, 사람이 봐야 하는 양이 제품 수에 비례해 늘어나는 구조부터 끊어야 했습니다. 2026년 8월 21일 기준선에서 10월 7일 재측정까지 커밋은 4,612개에서 7,066개로, 크론 잡은 142개에서 303개로 늘었습니다. 늘어난 자동화를 사람 눈으로 다 확인하겠다는 계획은 처음부터 성립하지 않았고, 기계에 맡긴 판정도 검사기 자체를 검증하기 전까지는 믿을 수 없었습니다.

2026-10-08측정 조건 — 2026년 8월 21일 기준선 스냅샷과 10월 7일 재측정, 같은 항목(저장소·사람 작업 커밋·스킬·에이전트·룰·훅·스크립트·크론 잡)을 같은 방식으로 셌다처음 잰 숫자 — 저장소 42개, 커밋 4,612개, 훅 22개, 스크립트 210개, 크론 잡 142개 · 화면 시각 검증 설정 파일 0개, 비교 기준 이미지 0개반증 1 — 시각 비교 고정 임계 0.2%가 실측 노이즈 0.160%와 0.04%p 차이였다반증 2 — 양성 입력 5건만 돌린 검사기가 적대적 입력에서 거짓 통과 4건(the·Act·Law·Regulations)을 냈다재측정 — 저장소 48개(+6), 커밋 7,066개(+2,454), 훅 51개(+29), 스크립트 545개(+335), 크론 잡 303개(+161)남은 한계 — 코드 1,395,648줄은 기준선 셈법이 달라 비교하지 않았고, 자산 숫자는 검수 품질을 증명하지 않는다

1인 개발에서 QA 검수량은 왜 제품 수에 비례해 늘어나나?

QA 자동화를 붙이기 전, 혼자 여러 제품을 운영하며 부딪힌 문제는 검수 속도가 아니라, 검수해야 할 양이 제품 수에 비례해 늘어나는 구조였습니다. 화면 하나를 고치면 그 화면을 다시 봐야 하고, 같은 버튼을 쓰는 다른 제품도 다시 봐야 합니다. 검수량을 식으로 쓰면 「제품 × 화면 × 변경 횟수」입니다. 세 값이 모두 늘어나는 상황에서 사람 한 명이 이 곱을 감당할 수는 없습니다.

당시 활성 프로젝트는 13개였고, 제품마다 화면이 수십 개였습니다. 매번 변경할 때마다 그 곱만큼 확인해야 한다면 실제로는 안 보게 됩니다. 안 보는 QA는 없는 QA와 같습니다. 문제는 이 상황이 특별한 실수에서 오지 않고, 많이 시도하고 신호가 오는 곳에 집중하겠다는 운영 원칙에서 곧바로 나온다는 점이었습니다. 시도를 늘리라는 원칙과 검수량이 시도 수에 비례하는 현실이 정면으로 부딪혔습니다.

비용은 사람의 눈에서 나갔습니다. 한 번 내린 판정을 저장하지 않으면 다음 작업에서 같은 화면을 두고 같은 질문을 다시 하게 됩니다. 실패율로 보면 더 나빴습니다. 아무도 보지 않은 변경은 깨져도 아무도 모릅니다. 그래서 이 글의 질문은 「QA를 얼마나 빨리 돌리나」가 아니라 「사람이 봐야 하는 양의 지수를 어떻게 줄이나」입니다. 같은 기간 개발 자산이 얼마나 늘었는지 먼저 세어 둔 기록이 있어서, 그 숫자부터 적습니다. 자산 숫자를 처음 셌던 이야기는 개발자 생산성 측정 글에 따로 있습니다.

처음 잰 숫자: 2026년 8월 21일 기준선

기준선은 2026년 8월 21일에 찍은 스냅샷입니다. 개인 저장소는 42개, 사람이 한 작업으로 센 커밋은 4,612개였습니다. 커밋은 사람 작업으로 분류한 것만 셌습니다. 기계가 남긴 커밋까지 섞으면 사람이 실제로 얼마나 일했는지가 흐려지기 때문입니다. AI 작업 환경 쪽 자산은 스킬 60개, 에이전트 23개, 룰 29개, 훅 22개, 스크립트 210개, 크론 잡 142개였습니다. 같은 항목을 10월 7일에 같은 방식으로 다시 셌고, 그 차이가 이 글의 재측정입니다.

측정 방법의 핵심은 두 시점을 같은 셈법으로 세는 데 있습니다. 코드 줄 수도 함께 셌지만 이번에는 비교에서 뺐습니다. 기준선의 코드 줄 수는 git이 추적하지 않는 파일까지 센 옛 방식이었기 때문입니다. 셈법이 다른 두 숫자를 나란히 놓으면 증가인지 셈법 차이인지 가를 수 없습니다. 이 문제는 코드 라인 수 비교 글에서 자세히 다뤘습니다.

검수 쪽 기준선도 있습니다. 기준선 이틀 전인 2026년 8월 19일에 실측해 보니 백엔드 로직 테스트는 이미 수십 개가 있었는데, 프론트엔드 화면을 시각적으로 검증하는 인프라는 0이었습니다. 브라우저 자동화 설정 파일 0개, 비교 기준으로 삼을 승인된 화면 이미지 0개였습니다. 사람이 눈으로 확인하는 바로 그 층에만 자동화가 없었던 셈입니다.

표. 2026년 8월 21일 기준선 — 저장소 42, 사람 작업 커밋 4,612, 스킬 60, 에이전트 23, 룰 29, 훅 22, 스크립트 210, 크론 잡 142. 화면 시각 검증 설정 0, 기준 이미지 0
기준선 — 자동화는 이미 많았고, 화면 시각 검증은 0이었다

세운 가설: 기계가 통과시키면 사람은 안 봐도 된다

처음 세운 가설은 하나로 요약됩니다. 기계가 전수로 검사해 통과시켰다면 사람은 다시 보지 않아도 된다. 이 가설은 세 가지 구체적인 선택으로 이어졌습니다.

  • 화면 비교는 고정 임계로 판정한다 — 승인한 화면과 지금 화면의 픽셀 차이가 0.2%를 넘으면 변경, 넘지 않으면 같은 화면으로 본다
  • 기계 검사를 통과한 화면은 정상으로 본다 — 「어떤 경우에도 이건 아니다」라는 부정형 규칙(불변식)에 걸리지 않으면 사람에게 올리지 않는다
  • 새로 만든 검사기는 통과해야 할 입력을 넣어 보고 전부 통과하면 쓴다

세 선택 모두 그럴듯했고, 실제로 첫 실행에서 라이브 결함을 잡아내기도 했습니다. 그래서 더 의심하지 않았습니다. 세 선택은 각각 장점도 분명했습니다. 고정 임계는 구현이 쉽고, 불변식은 명세 없이도 돌고 모든 제품에 그대로 재사용됩니다. 양성 입력으로 검사기를 시험하는 방식은 대부분의 개발자가 처음 택합니다. 문제는 세 선택이 모두 「판정 도구는 이미 믿을 만하다」는 같은 전제 위에 서 있었다는 점이었습니다. 그 전제를 따로 확인한 적은 없었습니다.

가설은 어디서 틀렸나?

첫 번째로 무너진 곳은 고정 임계였습니다. 최초 구현은 차이 허용치를 0.2%로 고정했는데, 화면의 노이즈를 실측해 보니 0.160%였습니다. 두 값의 차이는 0.04%p에 불과했습니다. 애니메이션이나 시각 표시가 조금만 흔들려도 아무것도 안 바뀐 화면이 「변경됨」으로 올라올 수 있는 거리였습니다. 오탐 한 번이면 사람들은 그 경보를 무시하기 시작하고, 그때부터 이 인프라는 없는 셈이 됩니다.

수치 카드. 고정 임계 0.2%, 실측 노이즈 0.160%, 여유 0.04%p
고정 임계와 실측 노이즈의 거리 — 0.04%p

두 번째는 「통과 = 정상」이었습니다. 2026년 8월 19일 첫 실행에서 라이브 결함 3건을 잡았지만, 영어 페이지(/en) 첫 화면의 텍스트 잘림은 불변식을 전부 통과했습니다. 이 결함은 기계가 아니라, 위반·변경 화면을 한 장으로 모은 요약 이미지를 사람이 훑다가 찾았습니다. 통과는 「검사한 것 중 걸린 게 없다」는 뜻일 뿐이고, 불변식에 적지 않은 결함은 그대로 통과합니다.

세 번째는 검사기 시험 방식이었습니다. 2026년 8월 31일, 에이전트가 법령 인용을 확인하는 검사기를 새로 만들고 통과해야 할 입력 5건을 넣어 전부 통과하자 믿을 만하다고 보고했습니다. 「믿을 만해?」라는 되물음 한 번에 적대적 입력을 넣어 보니 거짓 통과가 4건 나왔습니다. 법 이름 자리에 the, Act, Law, Regulations 같은 일반어를 넣어도 전부 통과했습니다. 같은 작업에서 결론이 뒤집힌 7건 중 5건이 사람이 되물어야만 뒤집혔습니다.

막대 그래프. 법령 인용 검사기 — 양성 입력 5건 전부 통과, 적대적 입력 거짓 통과 4건. 뒤집힌 결론 7건 중 사람이 되물어서 뒤집힌 것 5건
검사기를 양성 입력으로만 시험하면 거짓 통과가 안 보인다

진짜 원인: 판정자를 검증하지 않고 판정을 맡겼다

세 실패의 공통점은 판정 도구가 맞는지 확인하지 않은 채 판정을 맡겼다는 데 있습니다. 고정 임계는 노이즈를 재기 전에 정한 숫자였고, 불변식 통과는 불변식이 다루는 범위 안에서만 의미가 있었고, 검사기는 제가 통과할 입력을 골라 시험했습니다. 통과 케이스만 골라 돌린 결과는 검사기가 작동한다는 증거가 아니라, 통과할 입력을 골랐다는 증거입니다.

판정을 다시 AI에게 맡기는 방법도 답이 되지 못했습니다. 참고한 연구들에서 LLM을 채점자로 쓸 때 전문가와의 동의율은 64-68% 수준이었습니다. 외부 신호 없이 「다시 확인해 봐」라고 시키는 자기 교정도 강한 모델일수록 위험했습니다. 정확도가 높은 모델의 자기 교정률은 16.7%로 약한 모델의 26.8%보다 낮았습니다. 사용자가 「이거 맞아?」라고 묻기만 해도 정답을 오답으로 뒤집는 비율은 58.19%, 한 번 뒤집은 답을 고수하는 비율은 78.5%로 보고됐습니다.

「이게 맞나」에는 기계가 답할 수 없다. 대신 「어떤 경우에도 이건 아니다」를 적는다. 부정형은 기계가 검사할 수 있고, 명세 없이도 돌고, 전 제품에 그대로 재사용된다.

그래서 결론은 두 갈래가 됐습니다. 하나는 검수량 자체를 구조적으로 줄이기, 다른 하나는 판정 도구를 쓰기 전에 거짓 통과를 일부러 찾아보기입니다. 판정은 결정론 엔진이 하고, LLM은 불변식과 시나리오를 쓰는 단계에만 씁니다. 매 실행이 같은 결과를 내야 경보를 믿을 수 있기 때문입니다.

조치: 검수량의 지수를 어떻게 줄였나?

첫째 지렛대로 시간 축을 없앴습니다. 같은 화면을 두 번 보지 않습니다. 사람이 한 번 승인한 화면은 비교 기준 이미지로 동결하고, 그 뒤로는 기준과 달라진 것만 올라옵니다. 검수량이 「제품 × 화면 × 변경」에서 「제품 × 화면」으로 줄어듭니다. 이 단계에서 가장 흔한 실패가 승인을 기록하지 않고 작업을 끝내는 경우라서, 화면을 보고 승인한 그 턴에 기준 동결 명령을 실행하도록 규칙으로 묶었습니다.

둘째 지렛대로 제품 축을 없앴고, 효과는 이쪽이 가장 큽니다. 열 개 제품이 같은 버튼·카드·폼을 쓰면 그 버튼은 평생 한 번만 검수합니다. 제품별로 볼 것은 부품이 아니라 부품의 조합입니다. 공유 디자인 시스템과 공통 템플릿을 쓸수록 개발 속도뿐 아니라 검수 속도도 빨라집니다. 반대로 제품마다 화면을 새로 그리면 검수량이 제품 수만큼 늘어납니다.

셋째 지렛대는 선별입니다. 기계가 전 화면을 훑고 위반·변경분만 요약 이미지 한 장으로 합칩니다. 사람이 여는 파일은 화면 수와 상관없이 언제나 1개입니다. 이 순회는 매일 오전 8시 35분 크론 잡으로 돌고, 승인된 것은 신호에 뜨지 않습니다. 빨간불이 계속 켜져 있다면 진짜로 안 고쳤다는 뜻입니다.

표. QA 티어 — T0 기본값: 불변식만, 사람 확인 0, 셋업 2~3초 / T1 방문·문의 신호: 시각 기준 추가, 최초 승인 1회, 셋업 +5분 / T2 매출 발생: 결제·데이터 여정 추가, 셋업 +30분
QA 투자는 제품의 생존 증거에 비례한다

투자 수준은 제품이 살아남았다는 증거에 맞췄습니다. 방금 만든 제품은 예외 없이 T0으로 시작해 불변식만 검사하고, 셋업은 2~3초, 사람이 볼 것은 0입니다. 방문이나 문의 같은 실제 신호가 생기면 T1로 올려 시각 기준을 더하고(셋업 +5분, 최초 승인 1회), 매출이 생기면 T2로 올려 결제·데이터 흐름까지 검사합니다(셋업 +30분). 대부분의 제품은 죽기 때문에, 죽을 제품에 기준 이미지를 쌓으면 낭비입니다. 제품이 죽으면 대상 설정 한 줄을 지우면 끝납니다.

판정 도구 쪽 조치도 같이 넣었습니다. 노이즈 바닥을 자동으로 측정해 임계를 정하고, 오탐이 나오면 임계부터 만지지 않고 원인(애니메이션·시각 표시·무작위 콘텐츠)을 먼저 봅니다. 새 검사기·훅·판정 스크립트는 거짓 통과를 찾는 시험을 최소 3종 넣기 전에는 믿을 만하다고 말하지 않습니다.

  • 일반어·짧은 입력 — the, Act처럼 의미 없는 말이 통과하는지
  • 인접 분야의 정답 — 다른 범주의 올바른 값을 엉뚱한 자리에 넣었을 때 잡는지
  • 부정 문맥 — 「아니다」가 붙은 문장을 긍정으로 읽지 않는지

에이전트 쪽 훅도 같은 원칙으로 맞췄습니다. 훅이 실제로 막으려면 종료 코드 2를 내야 하고, 종료 코드 1은 경고만 남기고 통과시킵니다. 에이전트가 같은 시도를 되풀이하는 상황도 사람이 지켜보지 않고 기계가 잡게 했습니다. 반복 실패 감지는 같은 에러 메시지 3회만 세지 않고, 도구 이름과 결과 앞 500자로 만든 지문이 3회 같으면 멈춥니다. 공개 사례에서 지문이 같은 도구 호출이 58회나 감지 없이 반복된 적이 있기 때문입니다.

코드. 도구 이름과 결과 앞 500자로 지문을 만들고 3회 이상이면 exit 2로 차단하는 훅 예시
반복 감지 훅 — 경고가 아니라 차단하려면 exit 2

재측정 결과: 2026년 10월 7일

10월 7일에 같은 항목을 같은 방식으로 다시 셌습니다. 저장소는 42개에서 48개로 6개 늘었고, 사람 작업 커밋은 4,612개에서 7,066개로 2,454개 늘었습니다. AI 작업 환경 자산은 스킬 60개에서 71개(+11), 에이전트 23개에서 28개(+5), 룰 29개에서 32개(+3), 훅 22개에서 51개(+29), 스크립트 210개에서 545개(+335), 크론 잡 142개에서 303개(+161)가 됐습니다.

막대 그래프. 2026년 8월 21일 → 10월 7일. 스킬 60→71, 에이전트 23→28, 룰 29→32, 훅 22→51, 스크립트 210→545, 크론 잡 142→303
사람이 읽는 규칙은 3개 늘었고, 기계가 도는 자산은 두 배를 넘었다

눈에 띄는 대목은 증가의 방향입니다. 사람이 읽고 따라야 하는 룰은 3개 늘었을 뿐인데, 기계가 스스로 실행하는 훅·스크립트·크론 잡은 두 배를 넘게 늘었습니다. 크론 잡만 해도 하루에 정해진 시각마다 303개가 돕니다. 이 규모를 사람 눈으로 매번 확인하겠다는 계획은 이제 산수로도 불가능합니다. 검수량의 지수를 먼저 줄여 두지 않았다면 늘어난 자동화는 그대로 확인 안 된 자동화로 남았을 겁니다.

같은 기간 저장소 6개가 새로 생겼고 13개가 자랐습니다. 성장한 저장소 수가 처음 문제를 셀 때의 활성 프로젝트 수와 같은 13개라는 점도 눈여겨볼 만합니다. 검수량 식의 「제품」 자리에 들어가는 숫자가 줄지 않았다는 뜻입니다. 기준 동결과 부품 단위 검수가 없었다면 이 13개 저장소의 변경이 모두 사람 눈 앞으로 왔을 겁니다.

재측정 결과: 2026년 10월 7일
저장소기준선 커밋재측정 커밋증가
b2b-consulting1,4102,915+1,505
threads-loop187476+289
trading1,3051,438+133
tradestudio255370+115
sgkstudio-ai171238+67
imgpull2477+53
daily-saas-radar3871+33
claude-os2545+20
sales2541+16
rag3645+9
faceswap-wrapper3136+5
detail-factory3842+4
sdr2528+3

늘어난 커밋은 어디에 몰렸나?

커밋 증가분 2,454개 중 1,505개가 사업 운영 저장소(b2b-consulting) 한 곳에서 나왔습니다. 절반이 넘는 몫입니다. 이 저장소에는 홈페이지, 콘텐츠 발행, 영업 자료가 함께 있어서 화면과 자동화가 가장 많이 바뀌는 곳이기도 합니다. 검수량 식으로 보면 「변경 횟수」가 가장 크게 늘어난 자리이고, 시간 축을 없앤 기준 동결이 가장 크게 효과를 내야 하는 자리입니다.

새로 생긴 저장소 6개는 규모가 제각각이었습니다. 9월 29일에 시작한 people-library는 커밋 112개·4,189줄로 가장 컸고, 10월 2일에 시작한 wp-motion-sample은 커밋 1개·140줄이었습니다. 8월 21일에 시작한 regcheck는 커밋 4개인데 코드는 1,534줄이었습니다. 신규 저장소는 모두 T0에서 출발합니다. 새로 만든 제품이 셋업 2~3초짜리 불변식 검사만 받는 이유는, 이 중 어느 것이 살아남을지 아직 모르기 때문입니다.

늘어난 커밋은 어디에 몰렸나?
신규 저장소시작일커밋코드 줄 수
people-library2026-09-291124,189
ai-course2026-09-16413,025
mobile-jarvis2026-09-0623671
masters-db2026-08-2621623
regcheck2026-08-2141,534
wp-motion-sample2026-10-021140

커밋이 많다고 검수 대상이 많지는 않습니다. regcheck처럼 커밋은 적어도 코드가 큰 저장소가 있고, people-library처럼 짧은 기간에 커밋이 몰린 저장소도 있습니다. 검수 대상은 커밋 수가 아니라 사람이 실제로 쓰는 화면과 흐름이고, 그래서 티어 승격 조건을 커밋이 아니라 방문·문의·매출 신호에 걸었습니다.

남는 한계: 자산 숫자는 검수 품질을 증명하지 않는다

이번 재측정은 자산이 얼마나 늘었는지를 보여 줄 뿐, 그 사이 QA가 결함을 몇 건 잡았는지는 이 기록에 없습니다. 첫 실행의 라이브 결함 3건 이후 기간의 검출 수는 따로 세지 않았습니다. 「훅이 29개 늘었다」는 숫자도 그 훅들이 제대로 막는지까지 말해 주지 않습니다. 다음 재측정에서는 자산 개수 옆에 검출 건수와 오탐 건수를 같이 세야 합니다. 기준선과 재측정의 셈법을 맞춰 둔 것처럼, 검출 건수도 처음부터 같은 방식으로 셀 수 있게 기록 형식을 고정해 두는 편이 낫습니다. 자산 개수는 git과 파일 목록에서 언제든 다시 셀 수 있지만, 지나간 기간의 검출 건수는 기록이 없으면 다시 만들 수 없기 때문입니다.

코드 줄 수는 이번에도 비교하지 못했습니다. 재측정 시점의 코드는 1,395,648줄이지만, 기준선이 git 추적 밖 파일까지 센 옛 방식이라 차이를 계산하지 않았습니다. 다음 기준선부터는 같은 셈법으로 찍혀 있어야 비교가 가능합니다.

기계 검사로는 잡을 수 없는 영역도 남습니다. 접근성은 기계로 57%만 잡힙니다. 대체 텍스트가 실제로 설명적인지, 에러 메시지가 도움이 되는지 같은 의미 판단은 검사하지 않고, 검사한 척도 하지 않습니다. T1 이상 제품에 사람 눈이 최초 1회 들어가는 이유도 영어 페이지 텍스트 잘림처럼 불변식 밖의 결함이 실제로 있었기 때문입니다.

마지막으로, 검사기를 적대적으로 시험하라는 규칙도 규칙일 뿐입니다. 8월 31일 사례에서 거짓 통과를 드러낸 것은 결국 사람의 되물음이었습니다. 그 되물음 없이도 거짓 통과 시험이 매번 실행되는지는 아직 재지 않았습니다. 여러 제품의 검수 구조를 함께 설계해야 하는 상황이라면 상담에서 이야기를 나눌 수 있습니다.

같은 방식으로 우리 업무를 재보고 싶다면

이 글에 쓴 계측·판정·자동화는 저희가 실제로 매일 돌리는 방식 그대로입니다. 어떤 작업을 자동화할 수 있고 어디를 사람이 잡아야 하는지, 현재 업무 흐름을 놓고 같이 짚어 드립니다.

새 글이 올라오면 알려 드립니다

이런 계측 기록을 새로 쓰면 메일로 한 통 보냅니다. 광고나 판촉은 보내지 않습니다.