AI 코드 생성이 엔지니어링의 엄격함을 대체할 수 없는 이유

방관적 개발의 오류

최근 Campfire를 Ruby on Rails에서 Rust와 Elixir로 변환하는 것과 같이 AI 에이전트를 사용하여 기존 애플리케이션을 전체적으로 재작성하는 추세는 AI가 생성한 코드가 엔지니어링적 판단을 대체할 수 없음을 보여줍니다. 개발자가 코드를 읽고 이해해야 할 책임을 포기하면, 성능, 메모리 사용량, 장애 모드와 관련하여 LLM이 내리는 일련의 동전 던지기식 결정들을 암묵적으로 수용하게 됩니다. 핵심은 프로그래밍이 여전히 트레이드오프의 학문이라는 점이며, AI 에이전트는 구체적이고 전문가 수준의 지침 없이는 이러한 트레이드오프를 탐색할 수 없다는 것입니다.

암묵적 결정의 숨겨진 비용

LLM이 재작성을 수행할 때, 프롬프트에 명시적으로 정의되지 않은 수천 개의 미세한 결정을 내려야 합니다. 여기에는 다음이 포함됩니다:

  • 하위 호환성: 기존 API 계약을 유지할지, 아니면 아키텍처 편의를 위해 이를 깰지(예: CSRF 토큰 제거)에 대한 결정.
  • 리소스 관리: 인프로세스 큐와 Redis와 같은 외부 서비스 중 선택.
  • 동시성 모델: 특정 언어 런타임의 제약 내에서 데이터베이스 작업과 잠금 메커니즘을 처리하는 방법 결정.

Campfire 재작성 사례에서 Rust 버전은 Elixir 버전과 다른 호환성 제약을 선택했으며, 이로 인해 언어 자체에 대한 직접적인 비교가 오해의 소지를 낳게 되었습니다. 이러한 차이는 언어 고유의 특성이 아니라 AI의 비지도적 구현 선택의 결과물이었습니다.

벤치마크가 종종 오해를 불러일으키는 이유

성능 벤치마크는 종종 한 언어나 구현이 다른 것보다 우월함을 정당화하는 데 사용되지만, 운영상의 현실을 완전히 포착하지 못하는 경우가 많습니다. 대부분의 "슬롭(slop)" 벤치마크는 폐쇄 루프 시스템에서의 처리량을 측정하며, 다음과 같은 중요한 요소를 무시합니다:

  • 배압(Backpressure) 처리: 시스템이 한계에 도달했을 때 어떻게 동작하는가.
  • 이벤트 전달 지연: 연결을 끊는 것(빠른 실패)과 이벤트를 무기한 대기열에 넣는 것(심각한 지연 스파이크 유발)의 차이.
  • 메모리 점유율: 지속적인 부하 상태에서 OOM(Out of Memory) 충돌 위험.

예를 들어, 이벤트 브로드캐스터의 Rust 구현은 초기에는 작은 채널 용량으로 제한되어 부하 시 메시지가 유실되었습니다. 이 용량을 늘리면 전달률은 개선되었지만, 동시에 지연 시간이 130초 이상으로 급증했습니다. 이는 성능 지표를 "수정"하는 것이 종종 더 심각한 새로운 운영 위험을 초래한다는 점을 강조합니다.

비판적 사고의 필요성

엔지니어링은 장애 모드를 관리하는 행위입니다. 지연 시간이 긴 클라이언트의 연결을 끊어 정상적으로 실패하는 시스템이 극심한 지연을 겪으며 이벤트를 처리하려는 시스템보다 나은 경우가 많습니다. 이러한 결정에는 무엇이 "올바른" 실패인지 정의할 사람이 필요합니다.

커뮤니티 토론에서 언급되었듯이, 위험은 AI를 도구가 아닌 "마법의 버튼"으로 취급하는 데 있습니다. AI는 코드 생산을 가속화할 수 있지만, 다음의 필요성을 대체할 수는 없습니다:

  • 적대적 테스트: AI를 사용하여 시스템의 가정을 시험하는 테스트 스위트 생성.
  • 코드 리뷰: 생성된 코드를 수동으로 감사하여 안티 패턴과 성능 병목 현상 식별.
  • 제약 조건 설정: AI가 준수해야 할 비기능적 요구 사항을 명시적으로 정의.

결국 소프트웨어 시스템의 품질은 그 시스템에 쏟는 관심에 비례합니다. 코드가 사람이 작성했든 AI가 작성했든, 그 신뢰성, 성능, 유지보수성에 대한 책임은 이를 배포하는 엔지니어에게 있습니다.

Sources

관련