line

AI 시대의 개발 능력은 검증력으로 결정된다, Flava API Gateway 개발 중 배운 빠른 검증과 로컬 환경 구성 전략 (새 탭에서 열림)

코딩 에이전트는 빠르게 코드를 생성하지만, 설계 불명확성·출력 비결정성·검증 지연 때문에 신뢰할 수 없는 결과를 만들 수 있다. LY Corporation의 Flava API Gateway 팀은 이를 해결하기 위해 스펙 주도 개발, 검증 자동화, 빠르고 독립적인 로컬 환경을 구축했다. 결론적으로 AI의 생산성을 활용하려면 개발자의 전문성과 테스트·린터·사전 설계를 오히려 더 강화해야 한다.

코딩 에이전트가 만드는 개발 병목

  • 에이전트의 코드 생성 속도에 비해 CI 대기, 환경 프로비저닝, 원격 테스트 같은 단계는 느리다.
  • 에이전트는 다음과 같은 오류를 반복적으로 만들 수 있다.
    • 컴파일되지 않는 코드
    • 존재하지 않는 API 참조
    • 명시되지 않은 설계 결정을 임의로 선택
  • 동일한 프롬프트라도 실행마다 결과가 달라질 수 있어 출력의 일관성과 역량을 일반화하기 어렵다.
  • AI가 개발자의 리뷰 속도보다 빠르게 코드를 생성하면, 검토되지 않은 코드가 누적될 위험이 있다.
  • 따라서 AI 활용의 핵심은 단순한 생성 속도가 아니라, 잘못된 결과를 빠르게 발견하고 수정하는 개발 시스템이다.

Flava API Gateway와 세 가지 대응책

  • Flava API Gateway는 LY Corporation의 사내 프라이빗 클라우드 Flava에서 API를 생성·배포·모니터링하는 제품이다.
  • Kong이 데이터 플레인을 담당하고, 컨트롤 플레인은 각 팀이 독립적으로 API를 관리할 수 있는 다중 테넌트 REST API를 제공한다.
  • 팀은 다음 세 가지 원칙을 채택했다.
    • 코드 작성 전 설계와 요구사항을 확정하는 스펙 주도 개발
    • 테스트와 린터로 에이전트가 스스로 오류를 찾도록 하는 검증 자동화
    • CI를 기다리지 않고 전체 검증 루프를 돌리는 빠른 로컬 환경

스펙 주도 개발로 구현 방향 고정

  • 에이전트가 설계가 정해지기 전에 구현을 시작하면, 에이전트가 임의로 설계 결정을 내리면서 비결정성이 커진다.
  • Flava 팀은 먼저 OpenAPI 스펙으로 컨트롤 플레인의 전체 설계를 정의했다.
  • OpenAPI 스펙은 다음 역할을 한다.
    • 에이전트가 따라야 할 명시적 기준
    • 구현 결과가 설계에서 벗어났는지 판단하는 검증 기준
    • API 동작 계약의 문서화
  • 이후 기능을 작은 단위로 나누고 OpenSpec을 사용해 각 기능을 구현했다.

Nickel을 활용한 OpenAPI 관리

  • 원본 OpenAPI YAML은 반복적이고 장황해 수작업 유지보수가 어렵다.
  • 스펙과 실제 구현이 어긋나면 에이전트를 통제하는 기준으로서의 가치가 떨어진다.
  • 팀은 Nickel을 사용해 API 리소스를 선언적으로 정의하고, 이를 전체 CRUD 엔드포인트 스펙으로 변환했다.
  • 예를 들어 리소스 정의만으로 다음 요소를 일관되게 생성할 수 있다.
    • 목록·생성·조회·삭제 엔드포인트
    • 페이지네이션과 정렬
    • 정확히 일치하는 필터와 부분 문자열 필터
    • ETag 기반 낙관적 잠금
    • 공통 오류 응답
  • 이 방식은 반복적인 YAML 작성량을 줄이고, API 설계 규칙을 생성기에 집중시킨다.

OpenSpec 기반의 협업 워크플로

OpenSpec은 에이전트가 구현 전에 행동 계약에 합의하도록 다음 네 가지 산출물을 요구한다.

  • 제안(Proposal): 무엇을, 왜 변경하는지 설명
  • 설계(Design): 기술적 결정과 트레이드오프 정리
  • 델타 스펙(Delta Specs): 변경되는 요구사항을 Given-When-Then 시나리오로 정의
  • 작업 목록(Task List): 구현 단계를 체크리스트로 분해

워크플로는 다음 순서로 진행된다.

  • 개발자와 에이전트가 기능, 세부사항, 에지 케이스를 함께 검토한다.
  • 에이전트가 네 가지 산출물을 작성한다.
  • 에이전트가 작업 목록을 단계적으로 실행하며 구현한다.
  • 완료 후 변경 사항을 아카이브하고 델타 스펙을 메인 스펙에 병합한다.
  • 축적된 델타 스펙은 시간이 지나면서 시스템 전체의 “살아 있는 스펙”이 된다.

검증 자동화로 에이전트의 오류 수정 유도

  • 프롬프트에 주의사항을 계속 추가하는 방식은 효과가 제한적이며, 제약이 많아질수록 출력 품질이 낮아질 가능성도 있다.
  • 대신 테스트와 린터가 오류를 구체적으로 드러내도록 구성했다.
  • 에이전트는 다음과 같은 반복 루프를 수행한다.
    • 코드를 작성한다.
    • 테스트·린터·포매터를 실행한다.
    • 실패 원인을 확인한다.
    • 코드를 수정한다.
    • 다시 검증하고 다음 오류로 넘어간다.
  • 모든 요구사항을 처음부터 프롬프트에 주입하는 대신, 필요한 제약을 실패 시점에 점진적으로 제공하는 방식이다.
  • 프로젝트별 스킬에 테스트, 린터, 포매터를 묶고 AGENTS.md를 통해 언제 해당 스킬을 사용할지 안내했다.
  • 검사 지침을 매 턴마다 전달하지 않고 필요할 때만 로드해 에이전트의 불필요한 컨텍스트 부담도 줄였다.

세 계층 테스트와 완전한 로컬 검증

전체 테스트 모음은 2,754개이며 다음 세 계층으로 구성된다.

  • 단위 테스트
    • 비즈니스 로직을 분리해 검증
  • 통합 테스트
    • 실제 PostgreSQL 사용
    • 제약 조건, 트리거, 소프트 삭제 연쇄, 트랜잭션 검증
    • 전체 인프로세스 HTTP 스택 검증
    • 모든 응답의 OpenAPI 준수 여부 확인
  • E2E 테스트
    • 실제 Athenz 인증
    • Kong 데이터 플레인
    • API 키 적용
    • 멀티 테넌트 격리
    • 전체 시스템 동작 검증

CI 의존성을 줄인 빠른 개발 환경

  • 개발자가 직접 작성할 때는 CI 왕복을 줄이기 위해 어느 정도 완성된 코드를 먼저 제출할 수 있지만, 에이전트는 짧은 간격으로 수많은 시도를 반복한다.
  • 모든 시도를 원격 CI로 보내면 다음 문제가 생긴다.
    • 긴 대기 시간
    • 반복 과정에서 에이전트가 컨텍스트를 잃을 가능성
    • 원격 환경의 로그와 상태를 조사하기 어려움
  • 완전한 로컬 환경을 구축하면 에이전트가 즉각적인 피드백을 받고 현재 작업 흐름을 유지할 수 있다.
  • 로컬 의존성의 로그와 상태를 직접 확인할 수 있어 실패 원인 분석도 쉬워진다.
  • 전체 테스트는 개발자 기기에서 약 15초 안에 실행되도록 최적화했다.
  • 이를 위해 테스트를 병렬화하고 테스트 간 격리를 강화했다. 공유 테이블을 매번 삭제하는 방식보다 각 테스트 패키지가 독립적으로 생성한 데이터를 사용해 실행 간 충돌을 줄이는 방향을 택했다.

실용적인 적용 권장사항

AI 코딩 에이전트를 도입할 때는 프롬프트를 복잡하게 만드는 것보다 먼저 API·행동 스펙을 문서화하고, 테스트·린터·포매터를 자동 실행하며, 핵심 검증을 로컬에서 빠르게 끝낼 수 있게 만드는 것이 효과적이다. 에이전트의 성능을 높이는 가장 현실적인 방법은 더 많은 일을 맡기는 것이 아니라, 실패를 즉시 알려 주고 스스로 수정할 수 있는 짧은 피드백 루프를 구축하는 것이다.