
acomo의 테스트 전략: AI가 작성하는 코드를 받아내는 테스트 하네스
요약
AI 코딩 어시스턴트 도입으로 급증한 코드 변경량을 관리하기 위해 acomo가 재설계한 테스트 전략을 소개합니다. 인간과 AI 에이전트가 동일한 기준으로 검증할 수 있도록 테스트 하네스를 정비하고, 변경 유형에 따라 검증 계층을 선택적으로 실행하는 방식을 제안합니다.
핵심 포인트
- AI 도입으로 인한 코드 변경량 증가와 리뷰 병목 현상 해결 필요
- 인간과 AI 에이전트가 동일한 절차로 검증 가능한 테스트 환경 구축
- 속도와 안전성을 위해 변경 종류에 따라 테스트 계층을 선택적 실행
- 계약 계층부터 E2E까지 보호 대상에 따른 4가지 테스트 계층 운영
서론
acomo는 신청·승인 워크플로우를 API로 다룰 수 있는 헤드리스(Headless)형 워크플로우 SaaS입니다. 백엔드, 프론트엔드, API 사양, API 클라이언트를 하나의 리포지토리(Repository)에서 관리하고 있어, 한 곳의 변경이 다른 계층으로 파급되기 쉬운 구성입니다.
acomo 개발 팀에서는 AI 코딩 어시스턴트(AI Coding Assistant)를 사용한 개발이 완전히 정착되었습니다. 구현 속도는 올라간 반면, "이 변경으로 인해 아무것도 망가지지 않았다"를 확인하는 비용이 개발 전체의 병목(Bottleneck)으로 두드러지게 되었습니다.
본 기사에서는 이러한 상황에 맞춰 재설계한 acomo의 테스트 전략을 소개합니다. 도구의 사용법이나 개별 설정에 깊이 들어가기보다는, "무엇을·언제·왜 검증하는가"라는 설계의 사고방식을 중심으로 전달하겠습니다.
자동 테스트는 AI 이전부터 있었다
전제로, acomo에 자동 테스트가 없었던 것은 아닙니다. API 기반 플랫폼이라는 성격상, 실제 데이터베이스를 사용한 백엔드 통합 테스트(Integration Test)나 브라우저를 통한 E2E(End-to-End) 테스트는 인간 멤버들이 구현하고 리뷰하던 시절부터 쌓아왔습니다.
당시에는 "작성한 본인이 로컬에서 테스트를 돌리고, 리뷰어가 육안으로 보완한다"는 운용 방식으로 충분히 기능했습니다. 변경량이 인간이 작성할 수 있는 페이스 내에 있었고, 리뷰어가 변경 의도와 영향 범위를 파악할 수 있었기 때문입니다.
AI 코딩 어시스턴트가 개발의 주역이 되면서 이 전제가 무너졌습니다.
- 변경량이 늘어나, 한 번의 요청으로 프론트엔드부터 백엔드까지 가로지르는 차분(Diff)이 발생함
- 언뜻 올바른 것 같은 코드가 암묵적인 전제를 벗어나 있는 경우가 있음
- 리뷰가 차분의 타당성 확인에 쫓겨, 설계 판단에 사용할 시간이 줄어듦
게다가 acomo에서는 인간뿐만 아니라 AI 에이전트(AI Agent) 스스로가 구현부터 테스트 실행까지 담당하는 장면이 늘어났습니다. 인간이라면 "왠지 수상하니 좀 더 많이 확인해 두자"라고 판단할 수 있지만, 에이전트에게는 "무엇을 어디까지 검증해야 합격인가"를 기계적으로 판정할 수 있는 절차가 필요합니다.
즉, 과제는 "테스트를 늘리는 것"이 아니었습니다. 인간과 AI가 동일한 입구에서 동일하게 검증할 수 있고, 결과로부터 기계적으로 합격 여부를 판정할 수 있는 테스트 하네스(Test Harness)로서의 정비가 필요했던 것입니다.
방침: 필요충분한 검증을 자동으로 선택한다
재설계에 있어 다음 세 가지를 방침으로 세웠습니다.
- 입구를 일원화한다: 인간과 AI 에이전트가 동일한 절차로 동일하게 검증할 수 있는 상태로 만든다
- 변경 종류에 따라 선택한다: 모든 변경에 모든 테스트를 부과하는 것이 아니라, 필요한 것만 자동으로 선택한다
- 합격 여부를 기계로 판정한다: "아마 괜찮겠지"가 아니라, 게이트(Gate)를 통과했는지 여부로 판단한다
모든 E2E 테스트를 매번 실행하면 안전하겠지만, 대기 시간이 길어져 어렵게 올린 구현 속도를 상쇄해 버립니다. 속도와 안전성을 양립시키기 위해서는 검증을 계층으로 나누고, 변경 내용에 따라 나누어 실행할 필요가 있었습니다.
테스트의 전체상: 4가지 계층
acomo의 테스트는 보호 대상의 차이에 따라 4가지 계층으로 나뉩니다.
| 계층 | 보호 대상 | 주요 실행 타이밍 |
|---|---|---|
| 계약 계층 (Contract Layer) | API의 하위 호환성, 사양과 구현의 일치 | 백엔드를 건드렸을 때, 릴리스 전 |
| ... |
이 중 E2E 계층은 특히 비용이 높기 때문에, 더욱 3단계로 나누고 있습니다. 지금부터는 E2E의 단계 구분과 계약 계층의 체크를 차례로 살펴보겠습니다.
스모크 테스트: 전체의 생사를 최소 비용으로 확인한다
E2E의 최소 단위가 스모크 테스트(Smoke Test)입니다. 로그인하여 주요 화면에 도달할 수 있는지와 같은 몇 개의 시나리오만을 실행합니다.
확인하고 싶은 것은 업무 기능의 정확성이 아니라, 이 경로가 하나로 연결되어 있는지 여부입니다. 프론트엔드, API, 인증, 초기 데이터 중 하나라도 망가져 있다면 여기서 반드시 멈춥니다. 역으로 말하면, 스모크 테스트를 통과했다고 해서 업무 기능이 보장되는 것은 아닙니다. 역할을 "전체의 생사 확인"으로 한정함으로써, 모든 풀 리퀘스트(Pull Request)에 부과해도 견딜 수 있는 비용으로 억제하고 있습니다.
도메인별 E2E: 변경한 영역만을 겨냥한다
acomo의 E2E 시나리오는 사용자 관리, 워크플로우 모델, 인증 설정과 같은 업무 도메인 단위로 정리되어 있습니다. 전체가 40개가 넘기 때문에 매번 전부 실행하면 시간이 너무 많이 걸립니다.
그래서 풀 리퀘스트 (Pull Request) 단계에서는 전체를 실행하지 않고, 변경된 영역에 대응하는 도메인의 시나리오만 실행하는 규칙을 세웠습니다. 사용자 관리 화면을 수정했다면 사용자 관리 시나리오를, 모델 편집을 건드렸다면 모델 시나리오를 실행하는 식의 대응입니다.
이 방식에는 두 가지 이점이 있습니다. 하나는 실패했을 때 원인 탐색 범위가 처음부터 좁다는 것입니다. 다른 하나는 AI 에이전트 (AI Agent)가 광범위한 변경을 했을 때도, 건드린 도메인만큼만 검증을 추가하면 된다는 점입니다. 도메인이라는 구분이 그대로 검증량의 조절 다이얼 역할을 하고 있습니다.
API 계약 체크: 약속 위반과 커밋 누락을 기계적으로 찾아내기
acomo는 API 사양을 **신뢰할 수 있는 유일한 정보원 (SSOT, Single Source of Truth)**으로 취급합니다. 사양은 백엔드 코드로부터 자동 생성되어 리포지토리에 커밋되며, API 클라이언트 생성 및 문서화의 원천이 됩니다.
이 사양을 준수하기 위해, 계약 계층 (Contract Layer)에서는 두 종류의 체크를 자동으로 수행합니다.
- 하위 호환성 체크 (Backward Compatibility Check): 변경 전후의 사양을 비교하여, 기존 이용자를 망가뜨리는 변경(필드 삭제나 타입 변경 등)을 감지합니다.
- 드리프트 체크 (Drift Check): 구현으로부터 다시 생성한 사양과, 이미 커밋된 사양 사이의 차이를 감지합니다.
후자는 겉보기에는 사소해 보일 수 있지만, AI 개발에서는 특히 효과적입니다. AI가 입출력 타입과 처리를 한꺼번에 새로 작성했을 때, 생성된 사양 파일의 업데이트만 누락되는 실수가 발생하기 쉽기 때문입니다. 차분 리뷰 (Diff Review)에서 사람이 알아차리기 어려운 종류의 차이이므로, 사람의 눈과는 별개의 레이어에서 기계적으로 감지하도록 했습니다.
참고로, 실제 데이터베이스를 사용하는 통합 계층 (Integration Layer) 테스트는 준비가 늦어지기 쉬운데, 검증된 데이터베이스를 복제하여 재사용하는 메커니즘을 도입하여 준비 시간을 수 초 이내로 억제하고 있습니다. 계층을 늘리더라도 실행할 마음이 들 정도의 속도를 유지하는 것은 전략 전체의 전제 조건입니다.
CI: 변경을 분류하고 단계적인 게이트로 보호하기
지금까지의 검증을 CI (Continuous Integration)에서는 다음과 같은 흐름으로 조합합니다. 먼저 변경 내용을 자동으로 분류하여 어떤 계층을 건드렸는지 판정합니다. 그 결과에 따라 필요한 검증만 기동하며, 마지막으로 집약 게이트 (Aggregation Gate)가 모든 결과를 보고 합격 여부를 결정합니다.
평소의 기능 개발 풀 리퀘스트와 릴리스 풀 리퀘스트에서는 요구되는 보증 수준을 의도적으로 다르게 설정하고 있습니다.
| 기능 개발 풀 리퀘스트 | 릴리스 풀 리퀘스트 |
|---|---|
| 중시하는 점 | 속도 |
| ... | ... |
릴리스 풀 리퀘스트에는 차분을 분석하여 영향 범위와 권장 확인 사항을 코멘트하는 리포트도 자동으로 첨부됩니다. 릴리스 판단에 필요한 정보를 사람이 직접 모으지 않아도 갖춰져 있는 상태를 목표로 하고 있습니다.
도입 효과
운영해 본 결과, 효과는 다음과 같은 점에서 나타나고 있습니다.
- 대기 시간이 변경 내용에 부합함: 문서 수정만으로 무거운 검증을 기다릴 필요가 없어졌으며, 일반적인 풀 리퀘스트는 대체로 10분 전후로 판정이 나옵니다. 전체 E2E (End-to-End)를 실행하는 릴리스 시에도 30분 미만입니다.
- '연결되어 있음'을 항상 확인할 수 있음: 스모크 테스트 (Smoke Test) 덕분에 환경의 배선이 끊긴 채로 머지 (Merge)되는 사고를 방지할 수 있게 되었습니다.
- API 약속 위반을 리뷰 전에 발견: 호환성을 깨뜨리는 변경이나 커밋 누락을 사람이 차분을 읽기 전에 감지할 수 있습니다.
- 리뷰를 설계 판단에 활용 가능: 기계로 판정할 수 있는 것은 기계에 맡기고, 인간의 리뷰는 설계나 사양의 타당성에 집중할 수 있게 되었습니다.
그리고 무엇보다, AI 에이전트에게 구현을 맡길 때의 안심감이 달라졌습니다. "같은 입구에서 검증하고, 게이트를 통과하면 합격"이라는 프레임워크가 있기 때문에, 생성된 차분의 양에 위축되지 않고 맡길 수 있습니다.
요약
acomo의 테스트 전략은 단순히 "E2E 테스트를 늘렸다"는 이야기가 아닙니다. 이전부터 있었던 자동 테스트를 계층별로 정리하고, 변경 종류에 따라 필요 충분한 검증을 자동 선택하는 테스트 하네스 (Test Harness)로 재구성했다는 이야기입니다.
- 스모크 테스트로 전체의 생사 여부를 최소 비용으로 확인한다.
- 도메인별 E2E로 변경한 영역만을 검증한다.
- 계약 체크로 API의 약속과 커밋 누락을 기계적으로 보호한다.
- CI는 변경을 분류하여, 기능 개발은 빠르게, 릴리스는 안전하게 통과시킨다.
AI가 작성하는 코드의 양은 앞으로도 계속 늘어날 것입니다. 인간의 리뷰만으로 받아내는 것이 아니라, 기계적으로 합격 여부를 판정할 수 있는 검증 프레임워크를 미리 준비해 두는 것.
그것이 AI와 함께 개발 속도를 높이는 가장 빠른 지름길이라고 생각합니다. 마찬가지로 모노레포 (Monorepo)나 API 플랫폼을 키워나가고 있는 팀에게 참고가 되기를 바랍니다.
논의 (Discussion)

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