테크

2026. 10. 27

에브리유니즈 E2E 자동화 QA 구축기

에이전트에게 테스트가 아닌 테스트 코드를 맡기기까지

에브리유니즈 E2E 자동화 QA 구축기에브리유니즈 E2E 자동화 QA 구축기

Z세대 전문 커머스 플랫폼 '에브리유니즈'를 만드는 커머스프로덕트팀의 개발자들은 프로젝트 하나를 유저에게 배포하기까지 늘 같은 과정을 반복합니다. 먼저 개발 서버에 배포한 뒤 QA를 하고, 운영 서버에 배포한 뒤 다시 한 번 QA를 합니다. 여기서 QA(Quality Assurance)는 '품질 보증'이라는 뜻으로, 기능이 기획 의도대로 동작하는지 직접 확인하는 과정을 말합니다.


특히 로그인·결제처럼 장애 한 번이 곧장 매출과 신뢰에 타격을 주는 핵심 도메인은, 관련 없는 기능을 배포할 때조차 매번 다시 확인해야 합니다.


문제는 그 비용이 점점 커지고 있다는 점이었습니다. AI가 개발 생산성에 큰 혁신을 가져온 만큼 팀원 개개인이 맡는 프로젝트도 늘었고, 프로젝트마다 다른 정책과 설정을 관리하는 일도 복잡해졌습니다. 더 많은 기능을 더 자주 배포할수록, 같은 플로우를 손으로 확인하는 시간도 늘어났습니다.


그래서 배포마다 핵심 플로우를 대신 검증하는 ‘자동화 QA 시스템’을 코드로 만들기로 했습니다.



1. 도구 선택 — E2E와 Playwright

"코드로 QA를 한다"는 건 결국 사람이 눈으로 하던 확인을 코드가 대신하게 만드는 일입니다.


1.1 에이전트에게 맡기면 안 될까?

요즘은 Vercel Agent Browser, Claude Chrome Extension처럼 AI 에이전트가 브라우저를 직접 조작하게 하는 선택지도 있습니다. 하지만 배포마다 돌리는 회귀 검증은 항상 똑같이, 빠르게, 싸게 반복돼야 합니다.


에이전트 방식은 느리고 비싸며, 같은 입력에도 결과가 매번 달라질 수 있고 느리고, 비쌉니다. 회귀 검증에는 실행할 때마다 같은 결과가 보장되는 결정론적인 방식, 즉 코드가 필요합니다.


1.2 우리에게 부족했던 건 플로우였다

코드로 하는 테스트는 검증 범위에 따라 여러 층으로 나뉩니다. 이를 잘 정리한 대표적인 모델이 Kent C. Dodds의 Testing Trophy입니다. 아래로 갈수록 싸고 빠르지만 좁은 범위만 검증해 확신이 상대적으로 낮고, 위로 갈수록 느리고 비싸지만 "실제로 동작한다"는 확신이 커집니다.

Kent C. Dodds의 Testing Trophy. 각 층의 넓이는 그 테스트에 들이는 비중을 뜻합니다.


"위로 올라갈수록 작성·실행 비용과 시간은 증가하지만, 실제 앱이 잘 동작한다는 확신은 높아진다." — Kent C. Dodds


에브리유니즈도 정적 분석(Static)과 단위 테스트(Unit)는 이미 어느 정도 갖추고 있었습니다.


단위 테스트는 컴포넌트·유틸·모듈을 하나씩 독립적으로 검증합니다. 하지만 각 단위 테스트가 통과해도, 그 부분들이 연결됐을 때 제대로 동작한다는 보장은 없습니다.


데이터 형식이 미묘하게 어긋나거나, 상태가 다음 화면으로 넘어오지 않거나, 특정 환경에서만 API 호출이 실패하는 등 예상치 못한 지점에서 오류가 발생할 수 있습니다.


부족했던 건 개별 기능의 정확성이 아니었습니다. 사용자가 실제로 밟는 플로우가 실제 환경에서 끝까지 동작한다는 확신이었습니다. 그래서 단위 테스트가 통과해도 결국 직접 QA를 해야 했습니다.


중간 층인 통합 테스트(Integration)도 있지만, 외부를 모킹한 채 일부만 이어 보기 때문에 실제 환경의 전체 흐름까지는 보장하지 못합니다.


그래서 곧장 E2E를 도입했습니다.


1.3 왜 Playwright였나

E2E는 실제 브라우저를 띄워, 진짜 사용자처럼 클릭하고 입력하며 서비스 전체를 관통하는 테스트입니다. 프론트·백엔드·DB·외부 연동이 하나로 엮여 돌아가는지를 사용자 시점에서 확인합니다. 사람이 하는 "직접 눌러보기"를 그대로 코드로 옮긴 것이 바로 E2E입니다.


E2E 프레임워크는 Playwright와 Cypress가 양대 축입니다.


최근 5년간 Cypress와 Playwright의 npm 다운로드 추이 (출처: npm trends)


Playwright는 점유율과 선호도가 꾸준히 오르고 있고, 병렬 실행에 추가 비용이 없으며, Safari·모바일까지 지원합니다. 네트워크 제어와 디버깅 도구(Trace Viewer)도 강력합니다. 그래서 E2E 프레임워크로 Playwright를 선택했습니다.



2. 어떻게 설계했나

테스팅은 개발 배포 후 · 운영 배포 후 · 주기적 감시 세 단계로 나누어 진행하며, 단계마다 검증 대상과 방식이 다릅니다.


2.1 개발 서버 — 넓은 도메인

개발 배포 후, GitLab CI가 테스트 대상 도메인을 E2E로 돌립니다. 각 테스트는 도메인 태그를 달아 두고, 검증할 도메인이 늘 때마다 태그를 더합니다 — @auth · @pay · @mno · @search · ….


이때 E2E는 모킹 데이터 대신 실제 개발 웹 URL과 백엔드 API를 브라우저로 직접 호출합니다. 배포된 환경을 그대로 관통해야 "실제로 동작하는가"를 확인할 수 있기 때문입니다.


다만 개발 웹·API는 공개돼 있지 않고 내부(internal ALB·사내망)에만 떠 있어, GitLab CI 서버가 개발 서버를 호출할 수 있도록 내부 접근을 허용해야 합니다.


2.2 운영 서버 — 핵심 도메인

운영 배포 후에도 GitLab CI가 E2E를 돌리되, 로그인·결제(@auth · @pay)처럼 매출과 신뢰로 이어지는 핵심 도메인만 테스트합니다.


운영 서버는 공개 도메인이기 때문에 개발 서버처럼 내부 접근을 따로 열어 줄 필요 없이, 실제 운영 URL과 API를 호출해 테스트를 진행합니다.


2.3 주기적 감시

AWS CloudWatch Synthetics에서 제공하는 Canary를 사용해, 배포와 무관하게 직접 지정한 주기(분·시간 단위)마다 실제 운영 환경에서 로그인·결제 같은 핵심 플로우를 실제 사용자처럼 자동으로 수행하고, 플로우를 이루는 스텝 중 하나라도 실패하면 곧바로 알림을 보냅니다.



3. 에이전트로 테스트 코드 작성하기

앞에서 다루었듯, 에이전트에게 테스팅을 직접 맡기는 방식은 같은 입력에도 결과가 매번 달라질 수 있습니다. 반면 한 번 작성된 테스트 코드는, 코드를 바꾸지 않는 한 언제 돌려도 같은 검증을 진행합니다.


문제는 그 코드의 양입니다. 프로젝트가 늘어난 만큼 관리해야 할 테스트 코드도 늘어납니다. E2E 테스팅에서 가장 큰 비용은 결국 "테스트 코드 작성"입니다.

그렇다면 이 테스트 코드를 어떻게 효율적으로 작성할 수 있을까요? 답은 다시 에이전트입니다. 이번엔 테스트가 아니라, 테스트 코드 작성을 맡깁니다.


3.1 맥락 없는 에이전트는 헤맨다

Playwright는 테스트 작성을 돕는 공식 에이전트 Planner, Generator, Healer를 제공합니다.



그렇다면 이 에이전트들만 있으면 효율적이고 효과적인 테스트 코드를 작성할 수 있을까요?


Playwright CLI로 Planner·Generator 에이전트를 붙여 테스트 코드를 생성해 봤지만, 기대만큼 효율적이지 않았습니다.


예를 들어 Planner가 코드베이스를 탐색해 계획서를 작성해도 기획서에 명시된 디테일이 누락되는 경우가 있었고, 테스트 코드를 생성할 때마다 E2E용 테스트 계정 정보를 매번 되물었습니다.


문제는 에이전트의 성능이 아니라 맥락의 부재였습니다. 그래서 에이전트가 의미 있는 테스트 코드를 만들도록 환경(하네스)을 먼저 구성해야 했습니다.


3.2 하네스와 커스텀 서브에이전트

AI 에이전트가 안전하고 일관되게 일할 수 있도록 그 주위의 시스템과 작업 환경을 설계하는 일을 하네스 엔지니어링이라고 합니다. 새로 합류한 작업자에게 온보딩 문서와 계정을 전달하듯, 에이전트에게도 같은 맥락을 전달해야 합니다.


아래 환경(문서, 헬퍼, MCP)을 구성해, 에이전트가 테스트 코드를 작성할 때 참조하도록 했습니다.

그리고 Playwright 공식 에이전트의 전체적인 흐름은 그대로 사용하되, 이 하네스를 참조하도록 커스텀한 서브에이전트를 구성했습니다.




위 이미지는 Planner를 커스텀한 에이전트의 일부이며, 다음과 같은 특징이 있습니다.



AI가 계획을 세우고, 사람이 검토하고, AI가 코드를 짓습니다. 환경만 구축되어 있으면 테스트 코드 작성은 자동화됩니다.


3.3 커스텀 서브에이전트 사용해 보기

최근 에브리유니즈에서 진행한 선차감 중고보상(새 제품을 살 때 쓰던 기기의 중고 보상 금액을 결제 금액에서 미리 차감해 주는 서비스) 프로젝트에서 ‘생년월일이 없는 사용자에게 본인인증을 요구’하는 추가 요청사항을 받아 테스트 코드를 생성한 예시입니다.


먼저 관련 링크를 전달하며 추가 요청사항에 대한 E2E 테스트 코드 작성을 요청하면, Planner 에이전트가 실행되어 교차검증을 하며 플랜을 작성합니다.



플랜을 작성하면서 실현 가능한(결정적) 테스트와 재현 불가 테스트를 분류하고, 최종 플랜이 완성되면 자동으로 Generator를 호출해 실제 테스트 코드를 작성합니다.



테스트 코드 파일을 생성하고, 테스트 실행 전 선별 과제가 있다면 관련 정보를 제공합니다. 아직 E2E 시스템을 도입한 지 얼마 되지 않아 테스트 계정이 부족했기에, 케이스별 테스트 계정을 추가해 테스트를 진행했습니다.



마지막으로 Playwright가 실제 브라우저에서 테스트를 실행하는 명령어를 제공합니다.



4. 오류를 추적하고 고치다

오류를 추적하고 고치는 일은 테스트 코드 작성만큼이나 비용이 큽니다. Playwright는 어디서 오류가 났는지 추적하는 도구(Trace Viewer)와, 어떻게 고칠지 도와주는 에이전트(Healer)를 제공합니다.


Playwright는 실행을 처음부터 끝까지 기록하며, 실패한 실행에만 기록을 남기는 설정도 있습니다. 기록에는 단계별 화면(스냅샷)과 네트워크 요청·응답, 콘솔 로그, 스크린샷, 비디오 등이 담깁니다.


이 기록은 Trace Viewer로 들여다봅니다. 타임라인을 앞뒤로 넘기며 각 단계의 화면·네트워크·콘솔을 그 순간의 브라우저를 다시 보듯 확인할 수 있어, 어느 단계에서 무엇을 못 찾았는지 바로 짚어낼 수 있습니다.



사람이 Trace Viewer로 오류를 추적하듯, 에이전트도 같은 정보가 담긴 파일을 받아 오류를 추적할 수 있습니다.


오류가 발생했을 때 추적 정보 파일을 읽고 오류를 수정하는 것이 Healer 에이전트입니다.



Healer는 다음과 같은 추적 정보 파일을 읽고 spec 코드와 대조해 원인을 하나로 좁힙니다.



Healer를 실행하면 오류를 찾아 원인을 알아서 분석해줍니다.



원인이 잡히면 고치고 → 그 테스트만 다시 돌려 → 통과할 때까지 반복합니다(최대 4회). 마지막엔 같은 파일을 한 번 더 돌려 옆 테스트를 깨뜨리지 않았는지 확인합니다. 사람에게 되묻지 않고, 실행 결과를 피드백 삼아 스스로 고쳐 나가는 '자가개선 루프(self-improvement loop)'입니다.



5. 배포 너머 — Synthetics Canary

지금까지의 E2E는 배포한 이후에 한 번만 실행됩니다. 하지만 장애는 배포 이후와 상관없이 평소에도 발생할 수 있습니다. 그래서 AWS Synthetics Canary로 핵심 플로우를 주기적으로 돌려 감시합니다.


예를 들어 로그인 플로우를 Canary 스크립트로 옮기면, 설정한 시각이나 주기마다 실제 운영 URL에서 로그인을 끝까지 한 번 수행합니다. Canary가 한 번이라도 실패하면, CloudWatch 알람이 성공률이 임계치 아래로 떨어진 것을 감지해 기존 알림 채널로 알립니다. 이를 통해 예상하지 못한 사이드 이펙트로 핵심 기능에 오류가 생기더라도, 선제적으로 알림을 받아 빠르게 대응할 수 있습니다.

1시간마다 실행되고 있는 Canary 캡처 화면


Synthetics는 실행 1회당 $0.0012로 과금됩니다. 실행 주기만 정하면 월 실행 비용이 바로 나옵니다.


여기에 스크린샷·trace를 담는 S3 저장과 CloudWatch 메트릭·알람 비용이 더해지지만, 주기와 무관하게 대체로 소액입니다. 결국 감시 민감도와 비용 사이의 트레이드오프를 고려해 주기를 정하면 됩니다.



6. 안정화를 위한 추후 과제

E2E 시스템의 토대는 마련됐지만, 테스트를 더 안정적으로 운영하기 위해 남은 과제들이 있습니다.


1️⃣ 핵심 도메인 선별 기준의 정립

지금 운영 E2E와 Synthetics Canary는 로그인과 결제 두 가지 도메인만 핵심으로 보고 있지만, 어느 도메인까지 운영 E2E로 테스트할지, 어느 도메인까지 Synthetics Canary로 주기적으로 감시할지 기준이 필요합니다.


도메인을 너무 넓히면 실행 비용과 유지보수 부담이 커지고, 너무 좁히면 사각지대가 생깁니다. 현재는 ‘**실패 시 매출·데이터·신뢰에 미치는 영향’**만을 기준으로 도메인을 분류했는데, 이 외에도 도메인을 선별하는 기준을 고도화하는 것이 과제입니다.


2️⃣ Synthetics Canary와 프론트엔드의 동기화

카나리 스크립트는 프론트 로그인 화면의 셀렉터와 문구에 의존합니다. UI가 바뀌면 카나리도 함께 고쳐야 하는데, 지금은 ’프론트 변경 시 카나리도 확인’이라는 수동 체크리스트에 기대고 있습니다.


둘이 어긋나면 멀쩡한 서비스에 거짓 경보가 뜰 수 있으므로, 공용 셀렉터·헬퍼로 의존을 줄이거나 어긋남을 자동 감지하는 장치가 필요합니다.


3️⃣ QA 시스템 자체의 지표화

이 시스템이 실제로 신뢰를 지키고 있는지는 아직 판단하기 이릅니다. E2E 통과율, 간헐적 실패(flaky) 비율, 실패한 뒤 다시 통과되기까지 걸린 시간 같은 지표가 없기 때문입니다.


지표가 없으면 테스트가 늘어날 때 그게 신뢰를 키우는지, 유지보수 부담만 키우는지 판단할 수 없습니다. 통과율·flaky율·복구 시간을 지속적으로 추적하는 체계를 세워, QA 시스템의 건강 자체를 측정하는 것이 과제입니다.


-


처음 고민은 단순했습니다. 배포할 때마다 로그인과 결제를 손으로 다시 확인하는 시간을 어떻게 줄일 수 있을까.


그 답으로 E2E를 도입했고, 배포 단계별로 검증 범위를 나누고, 배포 너머는 Canary로 감시하도록 설계했습니다. 그리고 가장 큰 비용이었던 테스트 코드 작성과 수정은 다시 에이전트에게 맡겼습니다.


돌아보면 핵심은 역할을 나누는 일이었습니다. 검증은 매번 같은 결과를 내는 코드가, 코드 작성은 맥락을 갖춘 에이전트가, 무엇을 검증할지는 사람이 결정합니다. 사람은 같은 플로우를 반복해서 누르는 대신, 계획서를 검토하는 데 시간을 씁니다.


아직 풀어야 할 과제는 남아 있지만, 이제 핵심 플로우는 배포할 때마다, 그리고 배포와 상관없이도 꾸준히 검증되고 있습니다.



Written by 김정식 | 커머스프로덕트팀 소프트웨어 엔지니어

기술을 수단으로, 사용자 가치를 목적으로 두는 엔지니어입니다.