우와한 개발자

[Harness] Harness란 무엇인가 — AI 검증, 품질 보증, Test Harness, Vibe Coding, CI/CD

by 우와한개발자

AI

1. Harness가 왜 필요한가

AI가 코드를 작성하는 시대가 왔다. 자연어로 요구사항을 설명하면 AI가 전체 구현을 해주는 Vibe Coding이 확산되면서 개발 속도는 비약적으로 빨라졌다. 하지만 빠른 것이 곧 좋은 것은 아니다. AI가 생성한 코드에는 우리가 예상하지 못한 문제들이 숨어있을 수 있다.

  • 취약한 인증 로직이나 SQL 인젝션 같은 보안 취약점은 직접 코드를 열어보지 않으면 알기 어렵다
  • N+1 쿼리나 메모리 누수 같은 성능 문제는 트래픽이 늘어야 비로소 드러난다
  • 엣지 케이스 처리 누락은 예상치 못한 입력이 들어왔을 때 런타임 오류로 이어진다
  • 존재하지 않는 API나 잘못된 라이브러리를 사실처럼 생성하는 Hallucination은 배포 후에야 발견되는 경우도 많다

 

개발 패러다임도 함께 바뀌고 있다. 코드를 직접 작성하는 Write에서 의도를 명확히 기술하는 Generate로, 단순 테스트를 넘어 AI 출력을 종합적으로 판단하는 Evaluate로, 버그를 수정하는 Debug에서 AI가 생성한 코드의 논리와 아키텍처를 검토하는 Review로 개발자의 역할이 전환되고 있다.

  • Write → Generate : 코드를 직접 작성하지 않고 의도를 자연어로 기술한다
  • Test → Evaluate : 단순 통과 여부가 아니라 AI 출력을 종합적으로 판단한다
  • Debug → Review : 버그 수정 대신 AI가 만든 논리와 아키텍처 자체를 검토한다

이 변화 속에서 핵심 질문이 하나 등장한다. AI가 만든 코드는 누가 검증하는가.

 

1) Harness의 정의

Harness는 AI가 생성한 코드와 결과물을 자동으로 검증하는 품질 보증 프레임워크다. 사람이 직접 확인하지 않아도 AI의 출력이 정확하고 안전한지 판단할 수 있도록 도와주는 시스템이다.

  • 검증 없이 배포하는 것은 충돌 시험 없이 도로에 나서는 자동차와 같다
  • AI 코드의 충돌 시험 역할을 하며, 통과한 코드만 배포 파이프라인으로 진입한다

 

2. Harness의 핵심 기능 4가지

Harness는 4단계의 파이프라인으로 구성된다. 각 단계는 서로 연결되어 AI 출력물을 체계적으로 검증한다.

Execute(샌드박스 실행) → Collect(출력·상태 수집) → Evaluate(다차원 평가) → Log(기록·리포트)

1) Execute — 샌드박스에서 실행한다

생성된 코드를 샌드박스 환경에서 안전하게 실행한다. 외부 시스템에 영향을 주지 않고 동작을 검증할 수 있도록 격리된 환경을 제공하는 것이 핵심이다.

  • 격리 환경 : 실제 프로덕션 시스템과 분리해 부작용을 차단한다
  • 자동 입력 전송 : 테스트 입력을 자동으로 전송하고 실행 결과를 수집한다

 

2) Collect — 출력과 상태를 수집한다

Execute 단계에서 실행된 코드의 모든 산출물을 체계적으로 모으는 단계다. 단순히 실행 결과만 보는 것이 아니라 실행 과정에서 발생한 모든 변화를 기록하기 때문에 이후 평가와 분석의 기반이 된다.

  • 출력 수집 : 최종 응답값과 반환 결과를 그대로 저장한다
  • Trace 수집 : 실행 중 호출된 함수와 처리 흐름을 추적한다
  • 상태 변화 수집 : 실행 전후 시스템·데이터 상태 변화를 기록한다

 

3) Evaluate — 다차원 기준으로 평가한다

수집된 결과를 정확성, 보안, 예외처리, 응답품질, 부작용까지 다차원 기준에 따라 정량적으로 판정한다. 단순히 동작하는가를 보는 것을 넘어 기준에 맞게 동작하는가를 측정하는 단계다.

  • 정확성 : 기대 출력과 실제 출력이 일치하는지 확인한다
  • 보안·예외처리 : 취약점 존재 여부와 예외 상황 대응력을 함께 판단한다
  • 부작용 : 의도하지 않은 데이터 변경이나 리소스 사용이 없는지 검증한다

 

4) Log — 기록하고 리포트를 생성한다

모든 실행 결과와 오류 정보를 구조화된 로그로 기록한다. 이 기록이 축적되면 AI 출력의 품질을 지속적으로 개선하는 데이터가 된다.

  • 구조화 로그 : 실행 결과와 오류 정보를 일관된 형식으로 남긴다
  • 리포트 생성 : 로그를 기반으로 추적과 디버깅이 가능한 리포트를 만든다

 

3. Test Harness 구성요소

Harness를 실제로 구현할 때는 세 가지 핵심 구성요소가 필요하다. 각 요소는 테스트 실행의 서로 다른 책임을 담당한다.

 

1) Test Case

테스트할 입력값과 기대 결과를 사전에 정의한 명세서다. 단순히 케이스를 분류하는 것으로 끝나면 안 되고, 정상, 경계, 예외 케이스 각각에 대해 실제로 어떤 입력이 들어가고 어떤 출력이 나와야 하는지를 구체적인 값으로 정의해야 비로소 검증 가능한 명세서가 된다.

  • 정상 케이스 : 기대하는 입력이 들어올 때 올바른 출력이 나오는지 검증한다. 가장 빈번하게 발생하는 케이스이므로 반드시 포함해야 한다
  • 경계 케이스 : 처리 가능한 범위의 극단값, 예를 들어 빈 입력이나 최대 길이 입력에서 올바르게 동작하는지 검증한다. 경계에서 버그가 숨어있는 경우가 많다
  • 예외 케이스 : 손상된 파일이나 비정상적인 형식처럼 처리 불가능한 입력에 대해 에러를 올바르게 반환하는지 검증한다

 

2) Runner

테스트 코드를 실제 실행하고 결과를 수집하는 실행 엔진이다.

  • 순차·병렬 실행 : 정의된 테스트 케이스를 순서대로 또는 병렬로 실행한다
  • 결과 취합 : 각각의 실행 결과를 모아 다음 단계인 Validator로 전달한다

 

3) Validator

실행 결과와 기대값을 비교해 Pass/Fail을 판정하는 검증기다.

  • 다차원 기준 적용 : 단순한 값 비교를 넘어 기능별 판정 기준, 보안 기준, 성능 기준까지 함께 검사한다
  • 판정 근거 기록 : Pass/Fail 결과와 함께 판정 사유를 남겨 추후 분석에 활용한다

 

4. 테스트 유형

Test Harness에서 활용하는 테스트 유형은 목적에 따라 구분된다.

1) 단위 테스트 (Unit Test)

함수 또는 메서드 하나를 격리된 환경에서 검증하는 가장 기초적인 테스트 유형이다. 외부 의존성을 Mock으로 대체해 순수한 로직만 테스트한다. AAA 패턴이 표준 구조다.

  • Arrange : 테스트에 필요한 데이터와 환경을 준비한다
  • Act : 테스트 대상 함수나 메서드를 실행한다
  • Assert : 실행 결과가 기대값과 일치하는지 확인한다

 

2) 통합 테스트 (Integration Test)

여러 모듈이나 컴포넌트가 함께 올바르게 상호작용하는지 검증한다. Mock을 최소화하고 실제 의존성을 사용하는 것이 특징이다.

  • 인터페이스 검증 : API 호출, 데이터베이스 연동처럼 단위 테스트가 놓칠 수 있는 오류를 발견한다
  • 실제 의존성 사용 : Mock 대신 실제 컴포넌트를 연동해 데이터 흐름 문제를 확인한다

 

3) 회귀 테스트 (Regression Test)

코드 변경 후 기존 기능이 정상적으로 유지되는지 확인하는 테스트다. AI 생성 코드가 반복적으로 수정될 때 특히 중요하다.

  • 자동화 필수 : 매 변경마다 수동 실행이 불가능하므로 CI 파이프라인에 통합해야 한다
  • 테스트 스위트 유지 : 새로운 버그가 발견되면 해당 케이스를 즉시 추가해야 한다
  • 빠른 피드백 : 실패 시 즉시 알림을 받아야 대응 시간을 줄일 수 있다

 

5. PyTest와 CI/CD 연동

PyTest는 Python 생태계에서 가장 널리 쓰이는 테스트 프레임워크다.

  • assert 문만으로 테스트를 구현할 수 있어 코드가 단순하다
  • @pytest.mark.parametrize 데코레이터로 다양한 입력에 대한 테스트를 자동으로 생성할 수 있다
  • Fixture 시스템으로 테스트 전후 처리를 재사용 가능한 함수로 관리한다
  • coverage, asyncio, mock 등 풍부한 플러그인 생태계를 갖추고 있다

CI/CD 파이프라인에 통합하면 코드 변경이 배포되기 전 자동으로 검증된다. 결함 있는 코드가 프로덕션에 도달하는 것을 구조적으로 방지한다.

Commit → Build → Test(Harness 실행) → Deploy
  • Test 단계 실패 시 파이프라인이 즉시 중단되어 결함 코드의 배포를 차단한다

Harness 없이 배포하면 빠른 시작은 가능하지만 기술 부채가 빠르게 누적된다. AI가 코드를 빠르게 만들어내는 시대일수록 그 코드를 검증하는 구조가 더 중요해진다. Harness는 선택이 아니라 필수 인프라다.

블로그의 정보

우와한개발자 님의 블로그

우와한개발자

활동하기