# Harness 엔지니어링: AI 에이전트가 레거시 모노레포에서 프로덕션 코드 작성하기
Harness 엔지니어링에서는 인간이 아키텍처 경계, 테스트 시나리오, 결과 검토를 정의하고, AI 에이전트가 모든 프로덕션 코드를 생성합니다. Scala/Java로 31만 줄 규모의 레거시 모노레포 실험에서 모듈 추출 같은 일반 작업이 동작 변경 없이 성공적으로 수행됐습니다. 엔지니어의 역할은 맥락과 프로세스 관리로 옮겨가고, 에이전트가 기계적 노동을 맡습니다.
모노레포: 25개 SBT 모듈, 8년 역사, 고부하 시스템. 작업: Channel X 웹훅 처리 추출해 독립 서비스로 분리, 기존 어댑터 패턴 따름.
실험 설정과 역할
인간은 프로덕션 코드를 작성하지 않습니다. 역할이 명확히 분리됩니다:
- 인간: 아키텍처 경계, 작업 분해, 요구사항, 테스트, 검토, 최종 검증.
- 에이전트: 코드 생성/변경, 컴포넌트 이동, 시나리오 기반 테스트 실행, 인프라 설정, 버그 수정.
전형적 작업: 배선과 의존성 적응을 동반한 기계적 추출, 비즈니스 로직 리팩토링 없음. 단위 및 E2E 테스트로 검증 가능.
맥락 준비: 문서화가 제어 인터페이스
문서화가 핵심 도구가 됩니다: ADR로 옵션 제시, 계획으로 단계 정의. 에이전트는 주어진 프레임에 충실, 추측 없음.
예제 ADR:
# ADR-42: 모놀리스에서 Channel X 웹훅 처리 추출
## 맥락
Channel X는 현재 코어 내부에서 처리됩니다. 다른 채널들은 메시지 브로커 뒤 별도 서비스로 운영 중입니다.
## 옵션
1. 얇은 래퍼: 기존 코드 최소 수정(패키지, 배선)으로 이동.
2. 다른 스택으로 핸들러 완전 재작성.
3. 현상 유지.
## 결정
옵션 1: 추출 시 암묵적 동작 손실 최소화; 다른 채널과 아키텍처 일치.
## 결과
+ 모든 채널 패턴 일관성
− 일시적 코드 중복; 별도 작업으로 리팩토링
단계별 계획으로 오류 감소: 스켈레톤부터 완전 E2E 루프까지.
단계와 프롬프트: 단계별 에이전트 제어
단계 분해로 감독 보장. 프롬프트 예제:
- 아키텍처 청사진:
Channel A와 B 어댑터 작동 방식 분석: 브로커 구독 및 이벤트 발행 과정.
모놀리스에서 Channel X 웹훅 처리 위치 파악.
세 옵션 ADR 작성: 래퍼 / 재작성 / 코어 유지. 래퍼 추천하고 결과 상세 설명.
architecture/adr/에 파일 배치, 코드 untouched.
- 테스트를 계약으로:
WebhookHandler 클래스에 채팅 타입 분기 있음. 이를 순수 함수 routeEvent(...)로 추출.
동작 개선 말고 브랜치 그대로 복사. 단위 테스트 작성: 프라이빗 채팅, 그룹, 알 수 없는 타입, 빈 바디.
성공: 해당 모듈 `sbt test` 녹색 통과.
- 신규 모듈:
ADR-42 SPEC 따라 sbt 모듈 channel-x-adapter 생성.
모놀리스에서 나열한 파일 복사; `dependsOn(core)` 없이 깨끗한 컴파일 위해 패키지, import, deps만 변경.
규칙: 이 단계에서 비즈니스 로직 리팩토링 금지.
- E2E 루프:
e2e/ 디렉토리 추가, pytest + testcontainers: 브로커 컨테이너, PostgreSQL, 별도 포트 외부 API 목.
하나 테스트 작성: "ping" 텍스트 웹훅 POST → 브로커가 예상 주제에 이벤트 수신, text=ping.
테스트가 에이전트를 구동: 녹색 sbt test 또는 pytest 목표.
에이전트 강점: 통제된 루틴 작업
에이전트가 빛나는 영역:
- 코드 추출 및 적응.
- 예제 패턴 복제.
- 보일러플레이트 생성.
- 테스트 인프라 구축.
- 유사 편집 배치 처리.
pytest + testcontainers E2E 테스트 예제:
# 픽스처: 브로커 컨테이너, 어댑터, 외부 HTTP API 목
def test_incoming_webhook_publishes_to_broker(e2e):
e2e.http.post("/webhook/channel-x", json={"message": {"text": "hello", "chat": {"id": 42}}})
msg = e2e.broker.await_message("inbound.channel-x", timeout_s=5)
assert msg["text"] == "hello"
assert msg["chat_id"] == 42
def test_outgoing_command_reaches_external_api(e2e):
e2e.broker.publish("outbound.channel-x", {"chat_id": "42", "text": "hi"})
calls = e2e.external_mock.wait_for_requests(method="POST", path_contains="sendMessage")
assert any(b"hi" in c.body for c in calls)
컴파일뿐 아니라 통합 동작 검증: 브로커, DB, API 목.
한계와 경계
에이전트는 아키텍처 결정을 대체하지 않고 기계적 부분 가속화. 위험: 숨겨진 회귀(녹색 테스트가 문제 은폐), 엄격한 경계 필요. 패턴 있는 레거시 적합, 그린필드나 R&D는 아님.
개발자 의견 분분: 루틴 절약 vs 맥락 오버헤드.
핵심 요약
- Harness 엔지니어링: 규칙, 도구, 피드백으로 통제된 에이전트 환경.
- 레거시 프로젝트 코드 추출/적응 및 테스트 인프라에서 승리.
- 테스트: 의식 아닌 핵심 제어 인터페이스.
- 경계: 예제 있는 루틴 작업, 아키텍처 혁신 아님.
- 산업: Anthropic(90% AI 코드), Meta, Amazon—AI 네이티브 개발로 전환 중.
— Editorial Team
아직 댓글이 없습니다.