본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 02. 05:25

실제 사용자처럼 앱을 테스트하는 AI QA 에이전트를 일주일 만에 구축했습니다

요약

기존의 취약한 테스트 스크립트 방식 대신, 다양한 사용자 페르소나를 가진 AI 에이전트들이 실제 앱을 탐색하며 버그를 찾는 'Crawlix' 구축 사례를 소개합니다. 하드코딩된 셀렉터 없이 AI가 UI를 직접 이해하고 행동하며 예상치 못한 사용자 경로를 테스트합니다.

핵심 포인트

  • 다양한 페르소나(성급한 사용자, 적대적 에이전트 등)를 통한 실질적 테스트
  • 하드코딩된 셀렉터 없이 AI가 UI 요소를 직접 인식하고 의사결정
  • DOM 전체 대신 상호작용 가능한 요소만 추출하여 비용 및 속도 최적화
  • 테스트 결과에 대한 심각도 분류 및 자동화된 보고서 생성

저는 테스트 스크립트를 작성하는 것을 싫어합니다.

테스트가 중요하지 않기 때문이 아닙니다. 오히려 그 반대입니다. 저는 품질을 중요하게 생각합니다. 하지만 Playwright나 Cypress 테스트를 작성하기 위해 앉을 때마다, 누군가 CSS 클래스 이름을 바꾸는 순간 깨져버리는 셀렉터(Selector)와 싸우느라 세 시간을 허비합니다. 테스트는 유지보수가 필요한 두 번째 코드베이스가 되어버립니다. 그리고 가장 최악인 점은 무엇일까요? 테스트는 제가 이미 생각했던 경로만을 테스트한다는 것입니다.

진짜 버그는 당신이 생각한 경로에서 발생하지 않습니다. 잘못된 버튼을 가장 먼저 클릭하는 사용자, 안내 사항을 건너뛰는 사용자, 폼 필드에 예상치 못한 내용을 입력하는 사용자로부터 발생합니다. 상상하지 못한 행동에 대해서는 스크립트를 짤 수 없습니다.

그래서 저는 이 문제를 다르게 생각하기 시작했습니다.

스크립트를 작성하는 대신, 테스트하고 싶은 내용을 그냥 설명하기만 하면 어떨까요? 그리고 다른 무언가가 그것을 어떻게 테스트할지 찾아낸다면 말이죠?

그것이 제가 만든 것입니다. 이름은 Crawlix입니다.

실제로 작동하는 방식

URL과 목표를 입력합니다:

crawlix run --url https://myapp.com --goal "complete the signup flow"

Crawlix는 여러 개의 AI 에이전트(Agent)를 동시에 생성합니다. 각 에이전트는 고유한 성격, 즉 사고하고 행동하는 방식을 결정하는 행동 프로필(Behavioral profile)을 가지고 있습니다.

'처음 방문자(First-Timer)'가 있습니다. 당신의 앱을 본 적이 없으며, 아무것도 읽지 않고, 가장 명확해 보이는 것을 클릭합니다. 전문 용어에 혼란을 느낍니다. 큰 버튼을 먼저 눌러봅니다.

'성급한 사용자(Impatient user)'가 있습니다. 모든 안내 사항을 건너뜁니다. 폼을 다 채우기도 전에 제출합니다. 아무 일도 즉시 일어나지 않으면 제출 버튼을 세 번 클릭합니다.

'적대적 에이전트(Adversarial agent)'가 있습니다. 입력 필드에 SQL 인젝션(SQL injection)을 시도합니다. 잘못된 파일 형식을 업로드합니다. 다른 사용자의 데이터에 접근하기 위해 URL의 ID를 수정합니다.

그리고 세 명의 에이전트가 더 있습니다. '파워 유저(Power User)', '비원어민(Non-Native Speaker)', 그리고 '느린 네트워크 사용자(Slow Network user)'입니다.

각 에이전트는 실제 브라우저에서 당신의 앱을 열고, 화면의 실제 UI 요소를 읽으며, 자신의 성격에 따라 다음에 무엇을 할지 결정합니다. 하드코딩된 셀렉터는 없습니다. 미리 정의된 흐름도 없습니다. 그저 실제 사람과 같은 방식으로 의사결정을 내리는 AI 페르소나(Persona)가 있을 뿐입니다.

에이전트들이 고장 나거나, 혼란스럽거나, 예상치 못한 것을 발견하면 이를 '발견 사항(finding)'으로 기록합니다. 심각도(Critical), 경고(Warning), 또는 정보(Info) 수준으로 분류됩니다. 마지막에는 AI가 에이전트 전반에 걸친 패턴, 제안된 수정 사항, 그리고 우선순위가 지정된 권장 사항을 포함한 전체 보고서를 생성합니다.

이를 구축하며 놀라웠던 점

가장 어려웠던 부분은 AI 통합이 아니었습니다. 에이전트가 실제로 페이지를 이해하도록 만드는 것이었습니다.

저의 첫 번째 접근 방식은 전체 DOM을 LLM에 전달하는 것이었습니다. 좋지 않은 생각이었습니다. 매 단계마다 50KB의 HTML을 처리해야 했기에 비용이 많이 들고 느렸습니다. 저는 대신 상호작용 가능한 요소들만 추출하여 깔끔한 번호 매기기 목록으로 만드는 방식으로 전환했습니다:

[01] button: "Sign Up"
[02] input: "Email" (email) name="email"
[03] input: "Password" (password) name="password"
...

이 방식은 약 2KB 정도입니다. LLM은 이를 읽고 무엇과 상호작용할지 결정한 뒤, JSON 액션(action)을 반환합니다. 어댑터(adapter)는 이를 Playwright에서 실행합니다. 이 과정을 반복(loop)합니다.

단순한 루프이지만, 이를 제대로 구현하는 데 일주일 중 대부분을 보냈습니다.

내 앱을 테스트하며 나온 보고서

제 개인 프로젝트에 실행해 보았는데, 제가 정말로 눈치채지 못했던 것을 찾아냈습니다.

z-index: 10을 가진 부모 div가 여러 버튼의 포인터 이벤트(pointer events)를 가로채고 있었습니다. 실제 사용자들은 그 버튼들을 클릭하고 있었지만 아무 일도 일어나지 않았고, 조용히 실패하고 있었습니다. 저는 앱을 수십 번 직접 테스트했지만, 어디를 클릭해야 하는지 알고 있었기 때문에 이를 한 번도 잡아내지 못했습니다. 앱에 대해 아무것도 모르는 적대적 에이전트(adversarial agent)는 단 14단계 만에 이를 찾아냈습니다.

이것이 바로 당신의 앱을 모르는 에이전트로 테스트할 때의 묘미입니다. 그들은 당신이 더 이상 보지 못하게 된 것을 찾아냅니다.

기술 스택 (The stack)

TypeScript, 브라우저 자동화를 위한 Playwright, CLI를 위한 Commander를 사용했습니다. Groq, Gemini, Cerebras, Mistral, OpenRouter, Ollama, OpenAI, Anthropic을 포함한 8개의 LLM 제공업체를 지원합니다.

현재 상태

v0.1 버전입니다. 작동합니다. DuckDuckGo를 포함한 여러 실제 앱에서 테스트를 마쳤으며, 탐색, 양식 채우기, 버튼 클릭, 보고서 생성을 정확하게 수행합니다. 하지만 아직 다듬어지지 않은 부분들이 있습니다. 적절한 접근성 속성 (accessibility attributes)이 없는 커스텀 컴포넌트를 사용하는 앱에서는 요소 식별 (Element resolution)이 가끔 실패합니다. 매우 긴 실행 시간 동안 발생하는 속도 제한 (Rate limiting) 문제도 여전히 발생할 수 있습니다.

저는 이를 공개적으로 개발하고 있습니다 (building in public). 웹 어댑터 (web adapter)는 완료되었습니다. 다음 단계는 UI 없이 REST 엔드포인트를 테스트하기 위한 API 어댑터 (API adapter)이며, 그 후에는 Appium을 통한 모바일 지원입니다.

직접 사용해 보시고 문제가 발견되면 GitHub 이슈를 생성해 주세요. 버그를 찾아내는 초기 사용자들은 어떤 오픈 소스 프로젝트에서도 가장 가치 있는 사람들입니다.

npm install -g crawlix
crawlix setup
crawlix run --url https://yourapp.com --goal "your goal here"

GitHub: github.com/m-taqii/crawlix

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0