광고비를 쓰려다가 대신 AI 에이전트가 29시간 동안 내 제품을 테스트하게 만들었습니다
요약
광고 집행 전 제품의 결함을 찾기 위해 AI 에이전트(Codex)를 활용하여 29시간 동안 자동 QA 테스트를 수행한 사례를 소개합니다. 프롬프트 엔지니어링을 통해 다양한 환경과 언어, 사용자 시나리오를 검증하며 치명적인 버그 없이 효율적인 품질 보증을 달성했습니다.
핵심 포인트
- AI 에이전트를 활용한 29시간 연속 자동 QA 테스트 수행
- 프롬프트의 구체성이 테스트의 깊이와 품질을 결정함
- 단순 정상 경로를 넘어 의도적 방해 및 다국어 환경 검증
- 이슈 발견부터 코드 수정 및 배포 후 검증까지 전 과정 자동화
8억 7,200만 토큰 처리 — 그 중 97.63%는 캐시된 입력 (cached inputs). 5,222번의 도구 호출 (tool calls). 88개의 이슈 해결. 제품을 만드는 내내 QA(품질 보증)를 진행하는 동안 치명적인 버그는 0개였으며, 몇 개의 높은 심각도 (high-severity) 버그를 발견했습니다.
시작하기 전에 한 가지 말씀드립니다. 이 설정에는 특별한 것이 없습니다. Hermes 하네스(harness)도, 커스텀 프레임워크도 없습니다. 그저 Codex와 긴 프롬프트(prompt)뿐입니다. 제대로 설정된 Hermes 실행이라면 이 모든 것을 훨씬 더 엄격하게 측정했을 것이라 확신합니다. 다만 아직 많은 사람이 그 단계에 도달하지 못했다고 생각하며, 저는 그것 없이도 이미 도달 가능한 것이 무엇인지 보여주고 싶었습니다.
이것은 실험으로 시작된 것이 아닙니다. 불안함에서 시작되었습니다.
저는 유료 광고를 집행할 준비를 하고 있었습니다. 일단 트래픽을 사기 시작하면, 화면이 깨질 때마다 돈이 낭비됩니다. 즉, 당신은 낯선 사람들을 당신의 최악의 버그로 안내하기 위해 비용을 지불하고 있는 셈입니다. 그리고 저에게는 특정한 두려움이 있었습니다. 제 제품은 여러 언어로 실행되는데, 저는 모든 언어에 똑같이 능숙하지 않다는 점입니다. 만약 특정 로케일 (locale)에서 무언가 조용히 고장 난다면, 저는 몇 주 동안 알아차리지 못할 수도 있습니다. 광고는 멈추지 않고 계속 돌아갈 것이고, 사람들을 고장 난 곳으로 완벽하게 안내하며 계속 작동할 것입니다.
그래서 오후 내내 클릭 몇 번 해보고 만족하는 대신, 저는 모든 것을 Codex에게 맡기고 더 이상 고장 날 것이 없을 때까지 멈추지 말라고 명령했습니다.
그렇게 30시간이 조금 안 되게 실행되었습니다.
지침 (The instructions)
프롬프트 (prompt)는 제가 예상했던 것보다 더 중요했습니다. 그래서 정리된 내용을 여기에 공개합니다. 프롬프트의 구체적인 내용 대부분은 모호한 지침이 모호한 테스트를 만들어내기 때문에 포함되었습니다.
목표 (Objective) 나는 곧 유료 광고를 시작할 예정이다. 낯선 사람들을 이 제품으로 보내기 위해 비용을 지불하기 전에, 그들이 어떤 부분에서 막히게 될지 찾아내라.
기본 규칙 (Ground rules)
깊이 (Depth) — 해피 패스 (Happy path, 정상 경로)는 결승선이 아니라 출발선이다. 반복하고, 상세히 파고들고 (double-click), 동시 요청 (concurrent requests)을 보내라. 흐름 중간에 새로고침, 탐색 (navigation), 로그아웃, 뒤로 가기를 통해 흐름을 방해하라. 세션 중간에 언어를 변경하고 상태가 유지되는지 확인하라. 의도적으로 단계를 중단시키고 복구 및 사용량 계정 (usage accounting)을 모두 검증하라. 모바일, 태블릿, 데스크톱을 모두 확인하라. 키보드 전용 조작, 포커스 (focus), 레이블 (labels), 대비 (contrast)를 확인하라. 그리고 개인정보 보호 경계 (privacy boundaries)를 확인하라 — 어떤 계정이라도 봐서는 안 될 것을 볼 수 있는가?
모든 이슈에 대해 (For every issue) 기록할 것: 사용자가 보게 될 화면, 정확한 재현 단계, 코드상의 근본 원인 (root cause), 심각도 (Critical / High / Medium / Low), 수정 사항, 이제 이를 커버하는 회귀 테스트 (regression test), 배포 후 검증.
프로세스 (Process): 먼저 문서를 읽어라. 진행하면서 작고 추적 가능한 커밋 (commits)으로 수정하라. 메인 (main) 브랜치에 배포하고 라이브 환경에서 다시 검증하라. 수정은 프로덕션 (production) 환경에서 확인될 때까지 완료된 것이 아니다.
출력 (Output): 언어별 별도 보고서와 심각도 순으로 정리된 하나의 통합 요약본.
규칙 4와 규칙 5는 실행 과정에서 발생한 일 때문에 추가되었습니다. 그 이야기는 나중에 하겠습니다.
루프 (The loop)
의도적으로 지루하게 구성했습니다:
관찰, 재현, 조사, 수정, 테스트, 검증, 반복.
차이를 만든 규칙은 단 한 번의 통과를 신뢰하지 않는 것이었습니다. 화면이 한 번 작동한다고 해서 거의 아무것도 증명되지 않습니다. 그래서 모든 흐름은 새로고침, 로그아웃, 재시작, 언어 변경, 반복 요청, 의도적인 실패를 거친 후, 마지막으로 배포 후에 다시 검토되었습니다.
수치 (The numbers)
| 지표 (Metric) | 결과 (Result) |
|---|---|
| 총 경과 시간 (Total elapsed time) | 29h 45m 49s |
| ... |
타입 체크 (Type checking), 린팅 (linting), 빌드 (builds), 그리고 최종 테스트 스위트 (test suites)가 모두 통과된 후에 종료를 선언했습니다. 그리고 "종료"란 마지막 커밋을 의미하는 것이 아니라, 배포되고, 라이브 환경에서 재확인되었으며, 메인 (main) 브랜치에 다시 동기화되었음을 의미합니다.
네, 8억 7,200만 토큰을 처리했습니다
여기 헤드라인 수치가 있고, 바로 옆에 있어야 할 곳에 주석(*)이 있습니다.
| 토큰 유형 | 개수 |
|---|---|
| 총 처리된 토큰 (Total processed tokens) | 872,027,184 |
| ... | |
| 8억 7,200만은 입 밖으로 내뱉기에 정말 즐거운 숫자입니다. 또한 이는 97.63%의 캐시된 입력 (cached input)입니다. |
이것이 장시간 실행되는 세션의 내부 모습입니다. 동일한 코드베이스, 동일한 보고서, 동일하게 누적된 대화가 매 턴마다 다시 처리됩니다. 누적 카운터는 이 모든 것을 충실히 계산합니다. 이것이 8억 7,200만 개의 새로운 토큰이 도입되었거나 새로운 사용량으로 청구되었다는 의미는 아닙니다.
실제 새로운 컨텍스트 (context)와 생성된 작업량을 설명하는 수치를 원하신다면, 캐시되지 않은 입력과 출력을 합쳐 대략 2,235만 개입니다.
저는 두 수치를 모두 공개합니다. 왜냐하면 거대한 AI 사용량 수치는 캐싱 구조 (caching structure)가 그 옆에 놓여 있을 때에만 의미를 갖기 때문입니다. 비율 없는 총량은 측정이 아니라 마케팅일 뿐입니다.
내가 개입해야 했던 부분
이틀이라는 시간은 주기적으로 확인하기에 충분히 긴 시간이었기에, 모든 커밋 (commit)을 검토하지는 않았지만, 화면이 지나가는 것을 지켜보며 내가 보고 있는 것이 맞는지 스스로에게 물으며 확인했습니다.
첫 번째 포착은 제가 했습니다. 단 하나의 언어를 제외한 모든 언어에서 특정 레코드가 올바르게 표시되었습니다. 하지만 그 한 가지 언어에서는 그렇지 않았습니다. 에이전트 (agent)는 해당 화면을 보고 수용 가능한 것으로 등록한 뒤 다음으로 넘어갔습니다. 저는 이를 수동으로 표시했습니다. 직접 지적하자마자 진단되었고 빠르게 수정되었습니다. 수정하는 것은 결코 어려운 부분이 아니었습니다. 알아차리는 것이 어려웠습니다.
이것이 혼자 작업하는 에이전트에게서 기대해야 할 정확한 실패 모드 (failure mode)입니다. 에이전트는 "이것이 에러를 발생시키는가"에는 매우 능숙하지만, "이것이 이전에 본 유사한 11번의 사례와 비교했을 때 잘못되어 보이는가"에는 훨씬 취약합니다. 위 프롬프트의 규칙 4번이 존재하는 이유가 바로 이것 때문입니다.
두 번째 포착은 실행이 이미 완료되었다고 선언된 후에 이루어졌습니다. 제가 직접 결과를 다시 훑어보던 중, 결제 완료를 기록하는 PostHog 이벤트가 제대로 발생하지 않는 것을 발견했습니다.
그것이 문맥상 무엇을 의미하는지 생각해 보십시오. 저는 이 모든 과정을 광고 캠페인을 준비하기 위해 수행하고 있었습니다. 광고가 효과가 있는지 판단하기 위해 사용했을 숫자가 고장 나 있었던 것입니다. 어떤 화면도 잘못되어 보이지 않았습니다. 어떤 테스트도 실패하지 않았습니다. 아무런 오류도 발생하지 않았습니다. 제가 돈을 쓰려고 했던 바로 그 일에서 가장 중요한 단 하나의 지표가, 영원히 조용히 잘못되어 있었을 것입니다.
그것이 바로 규칙 5번입니다. 화면 너머를 검증하십시오 (Verify past the screen). 이벤트를 발생시키지 않는 초록색 체크표시는 통과가 아닙니다.
실제로 변화된 점
88개의 추적된 이슈, 111개의 타겟 수정 커밋 (fix commits). 흥미로운 부분은 그 불일치입니다. 관찰된 하나의 문제에는 보통 여러 개의 독립적인 변경 사항이 필요했습니다. 단 하나의 불일치가 영구 저장된 데이터 (persisted data), 복구된 UI 상태 (restored UI state), 번역된 출력 (translated output), 실패 복구 (failure recovery), 그리고 테스트 커버리지 (test coverage)에 모두 영향을 미칠 수 있었습니다. 이를 몇 개의 커다란 커밋으로 뭉뚱그리는 대신, 모든 것을 작고 추적 가능한 단위로 나누었습니다.
수정 사항은 몇 가지 테마로 모였습니다:
- 워크플로 (workflow)로 돌아갈 때 더 신뢰할 수 있는 상태 복구 (state restoration)
- 반복되거나 동시적인 동작 (concurrent actions)에 대한 더 일관된 처리
- 작업이 도중에 중단되었을 때 더 나은 복구
- 더 강력한 파일 및 문서 경계 처리
- 언어 및 화면 크기에 따른 레이아웃 깨짐 현상 감소
- 의도치 않은 내부 데이터 노출에 대한 더 명확한 방어
- 이전에는 없었던 경로에 대한 새로운 자동화 테스트
변경 된 코드의 양이 핵심이 아닙니다. 핵심은 모든 수정 사항이 관찰된 동작, 재현 가능한 사례, 그리고 검증 단계로 거슬러 올라갈 수 있다는 점입니다.
실제로 저를 괴롭혔던 부분
치명적인 버그 (critical bugs)는 없었습니다. 다행입니다.
하지만 심각도가 높은 (high-severity) 버그들이 있었습니다. 그것도 여러 개였습니다. 제품을 만드는 '동안' 지속적으로 QA를 수행해 온 제품에서 말입니다.
그것이 제가 계속해서 되새기게 되는 발견이며, 위의 어떤 숫자들보다 더 유용합니다. 저는 부주의하지 않았습니다. 진행하면서 계속 확인해 왔습니다. 하지만 30시간의 혹독한 테스트를 거치고 나서야, 일반적인 개발 QA가 그대로 지나쳐 버렸던 여러 개의 심각도 높은 문제들이 드러났습니다.
스트레스 캠페인(stress campaign) 자체가 종료된 후, 제 눈으로 직접 확인하며 두 가지를 더 발견했습니다.
현재 AI가 이 모든 것을 처리할 수 있다는, 즉 좋은 모델을 코드베이스(codebase)에 연결하기만 하면 품질 문제는 해결된 것이라는 대중적인 생각이 있습니다. 이번 실행은 에이전트(agent)가 얼마나 발전했는지를 보여주는 강력한 증거인 동시에, 그 생각에 반대하는 똑같이 강력한 증거이기도 합니다. 개발 단계의 QA(Quality Assurance)는 문제들을 놓쳤습니다. 29시간 동안의 적대적 캠페인(adversarial campaign)은 대부분의 문제를 잡아냈지만, 주의를 기울인 인간이 찾아낸 문제들조차 놓쳤습니다. 따라서 정직한 결론은 "이제 깨끗하다"가 아닙니다. 정직한 결론은 다음과 같습니다.
그 안에는 거의 확실히 여전히 잠재적인 버그(latent bugs)가 존재한다.
저는 이것을 다시 실행할 것입니다. 지금 제 믿음은 심각도가 높은 문제는 남아있지 않다는 것입니다. '안다(know)'가 아니라 '믿는다(believe)'입니다. 이 차이가 바로 이 글을 쓰는 핵심 요지입니다.
이 작업을 수행하려는 사람에게 해주고 싶은 말
연속성(Continuity)이 바로 능력이지, 지능이 아니다. 일회성 프롬프트(prompt)는 눈에 보이는 버그를 수정합니다. 제품과 함께 계속 머무르는 에이전트는 재시도(retries), 현지화(localization), 생성된 파일, 그리고 세 단계 뒤에 다시 돌아온 사용자가 추가되었을 때 그 버그가 어떻게 작동하는지를 발견합니다.
브라우저 접근 권한과 코드 접근 권한은 결합되었을 때 훨씬 더 강력하다. 브라우저 자동화(browser automation)는 무언가 실패했다는 것을 알려줍니다. 소스 접근 권한은 무엇이 실패할 수 있는지를 알려줍니다. 오직 이 두 가지가 결합되어야만 증상을 보고, 구현 사항을 추적하며, 수정 사항을 적용하고, 다시 동일한 과정을 거쳐 확인하는 것이 가능해집니다.
회귀 테스트(regression test) 없는 수정은 완료된 것이 아니다. 화면이 더 좋아 보이는 것은 증거가 될 수 없습니다. 실질적으로 가능한 경우, 향후의 변경 사항이 조용히 문제를 되돌리지 못하도록 모든 수정된 동작에 대해 테스트를 작성했습니다.
"아마 괜찮을 것이다"라는 판단을 명시적으로 금지하라. 에이전트가 작은 이상 징후를 건너뛰는 이유는 피곤한 인간이 그러는 것과 같은 이유입니다. 당장 불이 난 상황이 아니기 때문입니다. 프롬프트에 규칙을 작성하십시오: 언어 간의 불일치는 단순한 느낌이 아니라 하나의 발견(finding)입니다.
UI를 넘어, 특히 분석(analytics) 데이터까지 검증하라. 이벤트(events), 이메일, 생성된 파일, 그리고 저장된 상태(stored state)는 침묵하는 실패(silent failures)가 숨어 있는 곳입니다. 이것들이 바로 성공적인 테스트 실행 후에도 살아남는 바로 그 버그들입니다.
루프 안에 머무르세요 (Stay in the loop). 에이전트는 나의 영향력을 엄청나게 확장해 주었습니다. 하지만 에이전트가 소유권을 가져간 것은 아닙니다. 두 번 모두 중요한 무언가가 놓쳤을 때, 그것을 잡아낸 것은 화면을 바라보며 '음, 이건 좀 이상한데.' 라고 생각하던 사람이었습니다.
질문을 바꿀 가치가 있는 지점
여기서 가장 유용한 결과물은 단 하나의 수정 사항이 아니었습니다. 그것은 에이전트가 30시간 동안 쉬지 않고 제품 안정화 사이클 (product-stabilization cycle) 전체를 수행하며, 탐색하고, 증거를 조사하고, 코드를 수정하고, 테스트를 실행하고, 변경 사항을 관리하고, 외부 프로세스를 기다리고, 다시 돌아와 검증하는 과정을 지켜보는 것이었습니다.
이는 우리가 코딩 에이전트 (coding agents)에게 다소 작은 질문만을 던져왔음을 의미합니다. 단순히 다음과 같은 질문 말입니다:
"이 기능을 구현할 수 있나요?"
그뿐만 아니라 다음과 같은 질문도 가능합니다:
"이 제품을 계속 테스트하면서, 무엇이 고장 나는지 조사하고, 근본 원인 (root causes)을 수정하며, 수정 사항이 유지되는지 증명하고, 검증 기준 (validation criteria)이 충족될 때까지 계속 진행할 수 있나요?"
이것은 완전히 다른 직무 기술서 (job description)입니다. 그리고 누군가가 여전히 지켜보고 있는 한, 이것은 현재 우리가 가질 수 있는 가장 실용적인 직무일지도 모릅니다.
원문은 Kanapp Notes에 게시되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기