본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 06. 21:40

생성형 AI (GenAI) 개발의 오류 #8: 더 많은 AI 에이전트가 더 높은 생산성을 의미할까?

요약

AI 에이전트의 수를 늘리는 것이 반드시 선형적인 생산성 향상으로 이어지지 않는다는 점을 지적합니다. 에이전트 간의 조정 오버헤드와 분산 시스템의 복잡성 문제를 통해 에이전트 기반 개발의 한계를 설명합니다.

핵심 포인트

  • 에이전트 증가는 선형적 생산성 향상을 보장하지 않음
  • 에이전트 간의 조정 오버헤드 및 충돌 발생 가능성
  • 에이전트 시스템은 일관성이 필요한 분산 시스템과 동일함
  • 확장을 위해서는 프로토콜과 합의 메커니즘이 필수적임

이 글은 생성형 AI (Generative AI)를 사용하여 구축할 때 팀들이 범하는 잘못된 가정에 관한 시리즈의 여덟 번째이자 마지막 게시물입니다. 이 시리즈는 AI 보조 개발에 대한 환멸의 계곡 (trough of disillusionment)이 도래했다는 관찰과 함께 시작되었습니다. 이는 AI가 쓸모없기 때문이 아니라, 여덟 가지 잘못된 가정이 그 계곡을 피할 수 없게 만들었기 때문입니다. 이 게시물은 마지막 가정을 다루며 시리즈를 마무리합니다.

오류

"하나의 AI 에이전트가 10배의 향상을 가져다준다면, 열 개의 에이전트는 100배의 향상을 가져다줄 것이다."

유혹적인 이유

산술적인 계산은 거부하기 힘들 정도로 매력적입니다. 하나의 에이전트는 백엔드 (backend) 코드를 생성합니다. 다른 에이전트는 프론트엔드 (frontend)를 생성합니다. 세 번째는 테스트 (tests)를 작성합니다. 네 번째는 데이터베이스 마이그레이션 (database migrations)을 처리합니다. 다섯 번째는 문서화 (documentation)를 생성합니다. 각 에이전트는 병렬로 작동합니다. 회의, 대기, 또는 조정 오버헤드 (coordination overhead)가 없습니다. 순수한 처리량 (throughput)뿐입니다.

리더십은 그 잠재력을 봅니다. 5명으로 구성된 팀이 50개의 에이전트를 보유하면, 5명 팀의 비용에 API 크레딧을 더한 비용으로 50명 팀의 결과물을 낼 수 있습니다. 확장은 선형적 (linear)입니다. 경제성은 혁신적입니다.

그리고 초기 결과가 이를 확인해 줍니다. 각 에이전트는 독립적으로 작동하며 인상적인 결과물을 만들어냅니다. 백엔드 에이전트는 Go 코드를 생성합니다. 프론트엔드 에이전트는 React 컴포넌트를 생성합니다. 테스트 에이전트는 테스트 스위트 (test suites)를 생성합니다. 각 에이전트는 고립된 상태에서 10배의 생산성을 가진 개발자처럼 보입니다.

틀린 이유

당신은 이 문제를 전에 본 적이 있을 것입니다. 이것에는 이름이 있습니다. 바로 분산 시스템 (distributed systems)이라고 불립니다.

분산 시스템은 일관된 결과를 생성하기 위해 반드시 조정(coordinate)해야 하는 독립적인 행위자 (actors)들의 집합입니다. 각 행위자는 로컬에서 결정을 내립니다. 시스템의 정확성은 이러한 로컬 결정들이 전역적으로 (globally) 호환되는지에 달려 있습니다. 만약 호환되지 않는다면, 불일치 (inconsistency), 충돌 (conflicts), 데이터 손상 (data corruption), 그리고 연쇄적인 장애 (cascading failures)가 발생하게 됩니다.

동일한 코드베이스(codebase)에서 작업하는 AI 에이전트(AI agents)들은 하나의 분산 시스템 (distributed system)입니다. 각 에이전트는 변수 이름, 에러 처리 전략 (error handling strategies), 재시도 정책 (retry policies), 데이터 형식 (data formats), 추상화 수준 (abstraction levels), 의존성 선택 (dependency choices)과 같은 의사결정을 내립니다. 각 결정은 하나의 프롬프트 (prompt), 하나의 파일, 하나의 작업이라는 맥락 속에서 로컬하게 이루어집니다. 어떤 에이전트도 전체 그림을 보지 못합니다. 어떤 에이전트도 다른 에이전트와 협력하지 않습니다. 각 에이전트의 결정은 다른 에이전트들에게 보이지 않습니다.

분산 시스템 엔지니어들은 노드 (nodes)를 더 추가한다고 해서 분산 시스템을 확장할 수 없다는 사실을 배우는 데 40년을 보냈습니다. 시스템은 프로토콜 (protocols) — 합의 메커니즘 (consensus mechanisms), 순서 보장 (ordering guarantees), 충돌 해결 규칙 (conflict resolution rules), 인터페이스 계약 (interface contracts) — 을 추가함으로써만 확장할 수 있습니다. 프로토콜 없이는 노드가 많아질수록 처리량 (throughput)이 늘어나는 것이 아니라 더 많은 충돌 (conflicts)이 발생할 뿐입니다.

AI 에이전트에게도 동일한 원리가 적용됩니다. 명세 (specifications) 없는 더 많은 에이전트는 더 많은 보이지 않는 결정, 더 많은 불일치 (inconsistency), 더 많은 인지적 파편화 (cognitive fragmentation)를 의미할 뿐, 더 높은 생산성을 의미하지 않습니다.

붐 (The boom)

1-2개월 차: 병렬 스프린트 (The parallel sprint). 다섯 명의 에이전트가 시스템의 서로 다른 부분에서 동시에 작업합니다. 각 에이전트는 잘 구조화된 코드를 생성합니다. 모든 방향에서 PR (Pull Requests)이 쏟아져 들어옵니다. 팀은 이를 빠르게 병합 (merge)합니다. 시스템은 누구의 예상보다 빠르게 형태를 갖추어 갑니다.

3-4개월 차: 통합의 균열 (The integration cracks). 백엔드 (backend) 에이전트는 JSON 필드 이름으로 camelCase를 선택했습니다. 프론트엔드 (frontend) 에이전트는 snake_case를 예상했습니다. 데이터베이스 마이그레이션 (database migration) 에이전트는 컬럼 이름에 PascalCase를 사용했습니다. 그 누구도 다른 에이전트의 선택을 알지 못했습니다. 각각의 선택은 고립된 상태에서는 합리적이었습니다. 통합은 소리 없이 실패합니다 — 데이터는 흐르지만 필드 매핑 (field mappings)이 잘못되어 있습니다. 버그는 "UI에 잘못된 값이 표시됨"으로 나타나며, 세 개의 레이어(layers)에 걸친 명명 불일치 (naming mismatch)를 추적하는 데 이틀이 걸립니다.

5-6개월 차: 모순되는 패턴들. 백엔드 에이전트(backend agent)는 지수 백오프(exponential backoff)와 지터(jitter)를 적용한 재시도(retries) 로직을 구현했습니다. API 게이트웨이 에이전트(API gateway agent)는 3초의 고정 지연 시간을 가진 재시도 로직을 구현했습니다. 두 방식 모두 유효한 재시도 전략(retry strategies)입니다. 하지만 두 방식은 서로 다른 학습 데이터 패턴(training data patterns)으로부터 생성되었습니다. 다운스트림 서비스(downstream service)가 느려지면, 백엔드는 지연 시간을 늘리며 재시도하는 반면 게이트웨이는 매 3초마다 재시도합니다. 이는 이미 느려진 서비스를 압도하는 천둥 치는 들소(thundering herd) 현상을 만들어냅니다. 에이전트들의 패턴이 서로 충돌한 것입니다. 어느 쪽도 상대방의 존재를 알지 못했습니다.

7-8개월 차: 아키텍처 드리프트 (architectural drift). 수개월 동안 서로 다른 작업이 주어지면서 각 에이전트는 서로 다른 내부 패턴을 진화시켰습니다. 백엔드 에이전트는 에러 핸들링(error handling)을 위해 결과 타입(result types)을 사용하기 시작했습니다. 프론트엔드 에이전트(frontend agent)는 예외(exceptions)를 사용합니다. 테스트 에이전트(test agent)는 어떤 프롬프트(prompt)를 받았느냐에 따라 두 방식을 혼용합니다. 코드베이스에는 세 가지 에러 핸들링 철학이 존재하며, 각각은 국소적으로는 일관적이지만 전역적으로는 일관성이 없습니다(globally incoherent). 새로운 개발자가 코드베이스를 열었을 때, 세 가지 패턴이 모두 프로덕션(production) 환경에 존재하기 때문에 어떤 패턴이 올바른지 판단할 수 없습니다.

9-10개월 차: 편집 전쟁 (the edit war). 에이전트 A가 성능 향상을 위해 공유 유틸리티 함수(shared utility function)를 리팩터링(refactors)합니다. 에이전트 B는 별도의 작업에서 가독성을 위해 동일한 함수를 리팩터링합니다. 에이전트 A의 변경 사항이 먼저 병합(merge)됩니다. 에이전트 B의 변경 사항이 A의 최적화 내용을 덮어씁니다. 어느 에이전트도 상대방이 해당 파일을 건드렸다는 사실을 모릅니다. 팀은 두 번의 리팩터링에 대한 토큰 비용(token cost)을 지불하지만, 결과물은 어느 쪽도 얻지 못합니다. Google의 Adam Bender는 이를 부르는 명칭이 있습니다. 그는 그의 강연 _Software Engineering at the Tipping Point_에서 이를 '에이전트적 편집 전쟁(agentic edit war)'이라고 부릅니다. 즉, 두 에이전트가 서로 다른 목표를 향해 동일한 파일을 리팩터링하면서, 회사는 양쪽의 토큰 비용을 지불하는 동안 시스템을 라이브락(livelock) 상태로 만드는 현상을 말합니다.

더 나쁜 것은, 패턴 명세(pattern specification)가 없다면 이 사이클이 반복된다는 점입니다. 에이전트 A는 최적화되지 않은 코드를 보고 성능을 위해 다시 리팩터링(refactor)합니다. 에이전트 B는 읽기 어려운 코드를 보고 가독성을 위해 다시 리팩터링합니다. 에이전트들은 두 개의 유효하지만 모순되는 목표 사이에서 코드를 계속 주고받으며 무한히 토큰을 소비합니다. 분산 시스템(distributed systems)에서는 이를 라이브락(livelock)이라고 부릅니다. 시스템은 활성화되어 있지만 진전이 없는 상태를 말합니다. AI 개발에서는 이를 여러분의 API 청구서라고 부릅니다.

11-12개월 차: 조정의 붕괴. 팀은 아키텍처 변경, 즉 REST에서 gRPC로의 마이그레이션(migration)을 수행해야 합니다. 각 에이전트에게 개별적으로 지시를 내려야 합니다. 각 에이전트는 마이그레이션 프롬프트(prompt)를 서로 다르게 해석합니다. 백엔드 에이전트는 gRPC 서버 코드를 생성합니다. 프론트엔드 에이전트는 프롬프트가 업데이트되지 않았기 때문에 계속해서 REST 클라이언트 호출을 생성합니다. 테스트 에이전트는 코드베이스에서 두 프로토콜을 모두 발견하기 때문에 두 프로토콜 모두에 대한 테스트를 생성합니다. 모든 에이전트가 서로 반대되는 작업을 수행하고 있기 때문에, 일주일이면 끝날 마이그레이션이 두 달이 걸리게 됩니다.

팀은 분산 시스템이 요구하는 프로토콜 없이 분산 시스템을 관리해 왔다는 사실을 깨닫습니다. 각 에이전트는 하나의 노드(node)입니다. 각 노드는 의사결정을 내리고 있습니다. 아무도 합의 계층(consensus layer)을 구축하지 않았습니다.

분산 시스템이 이미 해결한 문제들

두 시스템을 나란히 놓고 비교해 보겠습니다:

분산 컴퓨팅 (Distributed Computing, 1990년대):           분산 AI 개발 (Distributed AI Development, 2020년대):
───────────────────────────              ──────────────────────────────────
여러 노드 상의 여러 프로세스                     하나의 코드베이스 상의 여러 에이전트
...

분산 컴퓨팅은 프로토콜을 통해 이 문제를 해결했습니다:

프로토콜 (Protocol)            해결하는 문제                AI 대응 방식
────────────────────        ────────────────────        ──────────────────────
합의 (Consensus, Paxos, Raft) 공유 상태에 대한 합의         공유 명세 저장소 (Shared specification repo)
...

왼쪽 열의 모든 프로토콜은 오른쪽 열에서 AI 개발에 상응하는 개념을 가지고 있습니다. 해결책은 존재합니다. 그것들은 명세 (specifications), 계약 (contracts), 그리고 강제 게이트 (enforcement gates)라고 불립니다. 이것들은 프로세스 대신 에이전트 (agents)에 적용된 동일한 조정 메커니즘 (coordination mechanisms)입니다.

다섯 가지 조정 실패와 그 해결책

1. 명명 불일치 (Naming inconsistency) → 컨벤션 명세 (Convention specification)

문제: 각 에이전트가 자신만의 명명 규칙 (naming conventions)을 선택함.
해결: 모든 에이전트에게 컨텍스트 (context)로 제공되는 컨벤션 명세.
       "JSON 필드: camelCase. 데이터베이스 컬럼: snake_case.
...

2. 패턴 모순 (Pattern contradictions) → 아키텍처 결정 기록 (Architectural decision records, ADR)

문제: 각 에이전트가 동일한 관심사 (concern)에 대해 서로 다른 패턴을 구현함.
해결: 횡단 관심사 (cross-cutting concern)당 하나의 ADR.
       "ADR-007: 재시도 전략 (Retry strategy)은 지터 (jitter)를 포함한 지수 백오프 (exponential backoff),
...

3. 수정 충돌 (Edit conflicts) → 소유권 경계 (Ownership boundaries)

문제: 두 에이전트가 상충하는 목표를 가지고 동일한 파일을 수정함.
해결: CODEOWNERS + 모듈 경계 (module boundaries).
       각 모듈은 하나의 소유자 (인간 또는 에이전트)를 가짐. 모듈 간
...

4. 에러 처리 분산 (Error handling divergence) → 인터페이스 계약 (Interface contracts)

문제: 코드베이스 내에 세 가지의 에러 처리 철학이 공존함.
해결: 하나의 인터페이스 계약: "모든 공개 함수는 (result, error)를 반환한다.
       예외 (exceptions) 없음. 패닉 (panics) 없음. 센티널 값 (sentinel values) 없음."
...

5. 마이그레이션 비일관성 (Migration incoherence) → 변경 명세 (Change specifications)

문제: 아키텍처 마이그레이션 (architectural migration)이 에이전트마다 다르게 해석됨.
해결: 마이그레이션 명세: "1단계: REST와 병행하여 gRPC 엔드포인트 추가.
       2단계: 클라이언트를 gRPC로 마이그레이션. 3단계: REST 제거.
...

각 해결책은 작습니다. 각각은 몇 줄의 텍스트에 불과합니다. 각각은 에이전트에게 컨텍스트 (context)로 제공되는 동시에 CI에 의해 기계적으로 강제 (enforced)됩니다. 컨텍스트는 에이전트가 올바른 결정을 내리도록 돕습니다. 강제 메커니즘은 에이전트가 올바른 결정을 내리지 못할 때 이를 잡아냅니다.

원칙: 명세는 에이전트를 위한 프로토콜이다

분산 컴퓨팅 (Distributed computing)에서 프로토콜 (Protocols)은 모든 노드 (Node)가 다른 모든 노드를 이해할 필요 없이 협업할 수 있도록 돕습니다. 노드 A는 노드 B의 구현 (Implementation) 방식을 알 필요가 없습니다. 노드 B의 인터페이스 계약 (Interface contract)만 알면 됩니다. 두 노드가 프로토콜을 준수한다면, 얼마나 많은 노드를 추가하든 시스템은 일관성 (Consistent)을 유지합니다.

동일한 원칙이 AI 에이전트 (AI agents)에도 적용됩니다. 에이전트 A는 에이전트 B의 프롬프트 (Prompt)를 알 필요가 없습니다. 자신이 작업 중인 모듈을 규정하는 명세 (Specification)를 알면 됩니다. 모든 에이전트가 명세를 준수한다면, 얼마나 많은 에이전트를 추가하든 코드베이스 (Codebase)는 일관성을 유지합니다.

분산 컴퓨팅 (Distributed computing):     프로토콜이 노드 간의 협업을 가능하게 함
분산 AI 개발 (Distributed AI dev):        명세가 에이전트 간의 협업을 가능하게 함

...

에이전트를 확장하는 것은 분산 시스템 (Distributed system)을 확장하는 것과 같습니다. 메커니즘은 동일합니다. 교훈도 동일합니다. 해결책도 동일합니다.

시리즈 완결

여덟 가지 오류. 하나의 메타 패턴 (Meta-pattern).

오류 #1: 더 빠른 생성 = 더 빠른 엔지니어링
            → 선행 서브 시스템이 뒤처지는 시스템보다 앞서 나감

...

모든 오류는 하나의 근본적인 가정에서 비롯됩니다: 결과물을 생성하는 것이 어려운 부분이다.

이 가정은 틀렸습니다. 결과물을 이해하고, 검증하며, 유지 관리하고, 이를 생성하는 행위자들을 조율하며, 왜 결과물이 이런 형태로 만들어졌는지에 대한 근거 (Rationale)를 보존하는 것 — 이것들이 바로 어려운 부분입니다. 그것들은 언제나 그러했습니다. AI는 쉬운 부분을 더 빠르게 만들었을 뿐입니다. 어려운 부분은 변하지 않았습니다.

Peter Deutsch의 '분산 컴퓨팅의 오류 (Distributed Computing Fallacies)'가 효과적이었던 이유는 모든 개발자가 가졌던 가정, 그리고 그것이 틀렸음을 깨닫고 운영 환경에서 대가를 치르게 된 가정들을 명명했기 때문입니다. 네트워크는 신뢰할 수 없습니다. 지연 시간 (Latency)은 0이 아닙니다. 대역폭 (Bandwidth)은 무한하지 않습니다.

'생성형 AI (GenAI) 개발의 오류'도 같은 방식으로 작동합니다. 생성은 엔지니어링이 아닙니다. 그럴듯함 (Plausible)이 정답 (Correct)은 아닙니다. 더 많은 에이전트가 더 높은 생산성을 의미하지 않습니다. 각 가정은 모두 사실처럼 들립니다. 하지만 각각은 실패로 이어집니다. 그리고 각각은 먼저 교훈을 얻은 분야에서 이미 해결된 문제들입니다.

여덟 가지 오류에 대한 해결책

모든 오류, 모든 도메인, 모든 시대에 걸쳐 해결책은 동일합니다.

시스템에 이미 존재하는 사양 (specifications) — 타입 (types), 계약 (contracts), 스키마 (schemas), 경계 (boundaries) (오류 #7) — 을 인식하십시오. 모든 변경 사항에 대해 기계의 속도로 이를 기계적으로 강제 (enforce) 하십시오 (오류 #1, #3, #4). 단순히 입력 품질뿐만 아니라, 선언된 속성에 따라 출력을 검증 (verify) 하십시오 (오류 #2, #5). 생성된 코드가 아니라 검증된 속성 (properties verified) 을 측정하십시오 (오류 #6). 에이전트 간의 조율 프로토콜로서 사양을 사용 (use specifications as coordination protocols) 하십시오 (오류 #8).

하나의 아키텍처 원칙, 여덟 가지 적용 사례입니다. 이를 가장 먼저 채택하는 팀은 환멸의 골짜기 (trough of disillusionment)에서 누구보다 앞서 벗어날 것입니다. 채택하지 않는 팀은 분산 시스템 개발자들이 한 번의 운영 사고를 겪을 때마다 Deutsch의 오류를 깨달았던 것과 똑같은 방식으로

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0