| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- CloudNative
- Java
- 데이터베이스
- 백엔드개발
- spring boot
- helm
- mysql
- DevOps
- 동시성제어
- 성능최적화
- monitoring
- Kubernetes
- JPA
- webflux
- grafana
- selector
- netty
- jvm
- redis
- 백엔드
- SpringBoot
- docker
- RDBMS
- Kotlin
- 성능 최적화
- 트랜잭션
- NIO
- prometheus
- kafka
- GitOps
- Today
- Total
유성
[AI-Native] 테스트 전략: 개발자에서 설계자로의 전환 본문
최근 Claude Code의 압도적인 성능을 경험하며, 이제 테스트는 더 이상 노동이 아닌 전략적 설계의 영역이 되었음을 확신했다.
이 글에서는 테스트 코드에 대한 관점과 견해에 대해서 설명하고자 한다.
1. 거장들이 말하는 AI시대의 테스팅 철학
우선 개발계의 유명한 분들의 생각을 먼저 보고 우리가 나아갈 좌표를 설정해보겠다.
Kent Beck "TDD는 설계 도구이지, 검증 도구가 아니다"
TDD의 창시자 Kent Beck은 AI가 코드를 짜주는 시대에도 TDD가 유효하다고 말한다.
다만, 이제는 우리가 직접 Red 단계를 구현하는 것이 아니라, AI에게 "이런 제약 조건을 만족하는 테스트를 짜줘" 라고 지시하는 '의도의 설계' 단계가 Red를 대신하게 된다고 한다.
필자가 생각하기에도 코드는 초기 뼈대가 중요하다.
물론 미래의 요구사항을 고려할 수 있는 코드를 작성한다는 것은 '신끼가 있는 개발자'가 아니라면 불가능한 일이다.
AI는 이런 부분에 있어서 코드를 부풀리는 역할의 비중이 다듬는 역할의 비중보다 크다.
그도 그럴것이 AI에게 "A 기능을 추가해줘" 라고 했을 때 "일단 코드가 복잡해서 구조를 다시잡고, 테스트 코드를 다시 작성해야합니다." 라고 답변하는 AI는 만들어질수도, 만든다고 사용하지도 않을 것이기 때문이다.
Gergely Orosz "코드 비대화를 경고하다"
Gergely는 실용주의를 강조한다.
AI는 1초 만에 1,000라인의 테스트를 만들 수 있지만, 그 코드는 고스란히 기술 부채가 된다.
커버리지 숫자를 채우기 위한 테스트는 시스템을 경직되게 만들 뿐이라고 한다.
필자도 Cluade를 이용해 테스트코드를 작성하고 Jacoco를 열어보면 "어? 테스트 커버리지 100%는 쉽겠는데?" 라고 생각이 든다.
그치만 단일 프로세스로 작동하는 서비스는 없고, 현실적으로 100%는 '유지보수의 어려움'으로 따라올 수 있다.
그렇지만 이마저도 시간이 지나면서 '회기 테스트에서 일회성 테스트 로의 전환' 이 될 가능성도 충분히 있어 보인다.
그렇게 되면 커버리지는 100%인 상태로 코드가 변경될 때마다 사용 불가능한 테스트 코드는 삭제되고, 신규 코드로 전환하는 방식이 될 것으로 보인다.
2. AI-Native 테스트 전략
과거에는 커버리지 80%가 "노력이 부족해서" 였다면, AI 시대의 80%는 '선택과 집중'의 결과여야 한다고 본다.
L1. AI기반의 자동화된 단위 테스트
"Low Value, High Volume, High Disposability"
이 계층은 코드의 가장 밑바닥을 지탱하는 '단순 반복'의 영역이다.
비즈니스 핵심 가치를 담고 있지는 않지만, 버그가 생기면 시스템 전체가 삐걱거린다.
테스트 수는 압도적으로 많지만, 테스트 코드 자체의 가독성이 비즈니스를 설명해주지 않는다.
- 대상: DTO 변환, 유틸리티 함수, 단순 도메인 로직
- AI의 역할: AI에게 "이 클래스의 모든 메서드에 대해 경계값 테스트를 포함한 100% 커버리지를 달성해줘" 라고 시킨다.
- 전략: 로직의 완결성을 확인한 직후 핵심 엣지 케이스만 남기고 나머지는 과감히 지운다.
AI를 충분히 사용한다는 것을 중점으로 개발자는 볼륨을 관리하는 것이다.
L2. 인간이 설계하는 통합 및 계약 테스트
"High Value, Mid Volume, High Persistence"
이 계층은 서비스와 서비스, 모듈과 모듈이 만나는 '연결' 영역이다.
비즈니스 핵심 가치를 담고 있다. AI는 이 사이의 미묘한 맥락이나 업무 규칙을 완전히 이해하지 못할때가 많다.
- 대상: Controller -> Service -> Repository로 이어지는 흐름의 규칙이나, 외부 API와의 규약
- 엔지니어의 역할: 엔지니어가 직접 '절대 깨져서는 안 되는 핵심 비즈니스 흐름'을 정의한다. 예를 들어 "주문이 완료되면 반드시 재고가 차감되고 결제 모듈이 호출되어야 한다"는 시나리오는 개발자가 설계해야 한다.
- AI의 역할: 설계를 전달하고 코드로 구현하는 반복 작업을 AI가 수행한다.
- 전략: 설계를 사람이 하고 코드는 AI가 작성한다. 이 테스트들은 절대 지우지 않고 프로젝트의 문서처럼 관리한다.
L3. 관측성 기반 인프라 테스트
"Extreme Value, Low Volume, Observability Driven"
코드 단위를 넘어 실제 운영 환경에서 검증하는 영역이다.
단순히 "코드가 에러 없이 실행되는가?"를 넘어 "시스템이 기대한 대로 반응하는가?"를 측정한다.
- 대상: Kubernetes의 HA, 예를 들어 서비스가 다운된 경우, 이후 처리에 대한 복구 프로세스가 정상 작동하는지
- 엔지니어의 역할: 장애 시나리오를 만들고 AI에게 "이런 장애 상황을 시뮬레이션할 수 있는 스크립트를 짜줘"라고 지시한다.
- AI의 역할: 테스트 결과로 나온 복잡한 메트릭 데이터를 AI가 분석하게 하여 "어디서 병목이 생겼는지" 리포트를 받는다.
3. Claude Code와 협업하는 워크플로우
단순히 "테스트 짜줘"라고 하면 AI는 기계적인 코드를 뱉는다. 아래와 같은 Step을 거처야 한다.
Step 1: 문맥 주입
단순히 코드만 주지 말고, 우리 프로젝트의 기술 스택과 도메인 지식을 먼저 동기화한다.
"우리 프로젝트는 Spring Boot 3.2와 Java 21을 사용해. 지금 @OrderService의 주문 생성 로직에 대해 테스트를 짜료 하는데, 이 서비스와 연결된 PaymentClient와 InventoryRepository의 구조를 먼저 분석하고, 어떤 식으로 모킹하는게 좋을지 제안해줘."
Step 2: 비판적 시나리오 도출
AI에게는 우리가 놓치기 쉬운 '예외 상황'을 찾아내라고 시킨다.
"정상적인 주문 성공 케이스 말고, 발생할 수 있는 가장 치명적인 예외 상황 5가지만 뽑아줘.
예를 들어 결제 API 호출 직후에 DB 커넥션 풀이 가득 차서 타임아웃이 발생하는 상황이나, 분산 락(Distributed Lock)이 풀리기 전에 중복 요청이 들어오는 케이스 같은 것들 위주로"
Step 3: 자율 실행 및 치유
이제 시나리오를 코드로 구현하게 한다. 여기서 핵심은 "성공할 때까지 지켜보게 하는 것"이다.
"방금 도출한 시나리오들을 JUnit 5와 AssertJ로 구현해줘. @DataJpaTest가 필요한지 아니면 단순 단위 테스트로 충분할지 판단해서 적절한 위치에 파일을 생성해. 그 다음 실제로 ./gradlew test를 돌려보고, 테스트가 깨지면 내 원본 로직의 문제인지 테스트 코드의 문제인지 분석해서 성공할 때까지 수정해줘"
4. AI-Native 기대 효과
AI-Native 테스트 전략을 도입한다는 것은 단순히 도구를 하나 더 쓰는 것을 넘어, 개발자의 '업무 정의'를 다시 내리는 과정이다.
'코드 작성'에서 '문제 해결'로의 중심 이동
더이상 코드 문법을 맞추고 Mock 객체를 설정하여 커버리지를 채우는데 시간을 소모하지 않게 된다.
개발자는 코드 작성을 잠시 멈추고, 테스트 코드를 토대로 도메인 로직의 모순을 찾고, 더 나은 아키텍처를 고민하는 본질에 집중하게 된다.
기술 부채 없는 안전한 전환
Gergely가 경고한 비대화된 테스트 코드는 리팩토링의 가장 큰 걸림돌이었다.
하지만 테스트 코드의 생명 주기가 더 가속화됨에 따라 AI에게 "바뀐 로직에 맞춰 새로 검증해줘" 라고 시키면 된다.
물론 아직은 이른감이 있지만, 테스트 코드가 자산이 아닌 '소모품'이 되면서 서비스는 훨씬 더 유연해질것이다.
심리적 안전감과 개발 속도의 조화
"내 코드가 돌아갈까?" 를 생각하기 전에 테스트를 먼저 수행하고 로직상의 공백을 채운다.
개발자는 숨겨진 정책을 발견하고, AI는 이를 성공할 때까지 치유하는 과정을 반복하며 성공을 전재로 한 개발의 속도가 증가한다.
5. 마치며
점점더 개발에 AI의 영향도는 커질 것으로 생각한다.
개발과 테스트에 대해서 AI의 비중이 커짐으로 인해 다양한 방식의 접근이 필요하고, 각 서비스에 따른 적합한 구조를 설계해야 할 것으로 예상된다.
그렇기에 더욱이 AI에게 새로운 작업들을 쥐어주고, 자동화가 가능한지 항상 고민해야 할 것으로 생각한다.
'테스트코드 & 정적분석' 카테고리의 다른 글
| IntelliJ Profiler로 보는 JVM 힙 & 스레드 덤프로 장애 상황 분석 (0) | 2026.01.30 |
|---|---|
| Spring Boot 3.4+에서 @MockBean이 @MockitoBean으로 대체된 이유 (0) | 2026.01.18 |
| 테스트 코드 작성 2편 동시성 이슈와 외부 의존성 제어 (0) | 2025.12.23 |
| 테스트 코드 작성 1편 테스트가 고통스럽다면, 설계를 의심하라 (feat. POJO & Time) (0) | 2025.12.22 |
| 테스트 코드, '작동'을 넘어 '지속 가능한 시스템'으로 (0) | 2025.12.22 |