본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 21. 12:31

AI가 느리게 느껴지나요? AI가 멍청한 게 아니라, 한 번에 하나씩만 처리하게 만들고 있는 것일지도 모릅니다

요약

AI 에이전트의 작업 속도를 높이기 위해 작업을 분할하여 여러 에이전트가 동시에 수행하는 병렬 처리 아키텍처 설계 방법을 소개합니다. 모델별 성능 차이를 활용하여 총괄, 계획, 실행 역할을 계층화하는 전략을 다룹니다.

핵심 포인트

  • 병렬 처리를 위해서는 느슨하게 결합된 깔끔한 소프트웨어 아키텍처가 필수적임
  • 모델 계층화(Tiering)를 통해 Opus(총괄), Sonnet(계획), Haiku(실행)로 역할을 분담
  • 동일한 토큰 사용량 대비 실제 작업 소요 시간(Wall-clock time)을 대폭 단축 가능
  • 잘 설계된 인터페이스와 모듈화가 병렬 에이전트 시스템의 전제 조건임

📖 원래 제 블로그에 게시되었습니다. Claude Code를 활용한 구축 시리즈의 일부입니다.

한동안 저는 AI가 작업하는 것을 지켜보며 속으로 투덜거리곤 했습니다. 꽤 큰 작업인데도, 다음 작업을 시작하기 전에 하나의 모듈을 끝내야 했고, 저는 그저 하나가 끝나고 다음 차례가 오기를 기다리며 앉아 있어야 했기 때문입니다. 작업 자체는 괜찮았습니다. 단지 느릴 뿐이었죠. 큐 (Queue)에 갇혀 있어서 느린 것이었습니다.

그러다 문득 깨달았습니다. 이 모듈들 중 상당수는 서로 아무런 상관이 없는데, 왜 굳이 하나씩 순차적으로 처리하게 만들까? 작업을 분할하여 여러 에이전트 (Agents)가 동시에 작업하게 하면 끝날 문제였습니다.

내가 원하는 것, 그리고 한계점

제가 원하는 것은 간단합니다. 거의 동일한 토큰 (Tokens)을 사용하면서, 동일한 작업을 수행하되 실제 소요 시간 (Wall-clock time)을 대폭 단축하는 것입니다.

하지만 미리 한계를 말씀드리겠습니다. 모든 작업을 이런 방식으로 분할할 수 있는 것은 아닙니다. 이것은 제가 스스로 터득한 접근 방식일 뿐이니, 유용한 부분만 취하시기 바랍니다.

전제 조건: 깔끔한 아키텍처 (Architecture)

여러 에이전트가 서로 방해하지 않고 동시에 작업하기 위한 전제 조건은 AI가 아니라, 바로 여러분의 **아키텍처 (Architecture)**입니다.

제 작업이 분할될 수 있었던 이유는 이미 여러 모듈로 나뉘어 있었고, 인터페이스 (Interfaces)를 통해 서로 통신하며, 내부 구현 (Internal implementations)이 서로에게 영향을 주지 않았기 때문입니다. 각 모듈이 인터페이스 계약 (Interface contract)을 준수하기만 한다면 독립적으로 구축될 수 있었습니다. 즉, 느슨하게 결합되고 (Loosely coupled), 응집도가 높았습니다 (Highly cohesive). 그리고 저는 코드를 한 줄 쓰기 전에 opus와 함께 그 설계를 확정했습니다. opus는 제가 생각을 정리하고 옵션을 제시하는 데 도움을 주지만, 결정하는 것은 바로 저입니다.

이 단계에서는 편법을 쓸 수 없습니다. 깔끔하게 분리되지 않은 아키텍처에 병렬성 (Parallelism)을 강제로 주입하는 것은, 엉킨 실타래를 몇 조각으로 자르는 것과 같습니다. 조각들이 여전히 매듭지어 연결되어 있어 상황만 더 엉망이 될 뿐입니다.

누가 주도하고, 누가 계획하며, 누가 작업을 수행하는가

설계가 결정되었다면, 이제 역할을 할당할 차례입니다. 제가 주로 사용하는 분할 방식은 다음과 같습니다:

  • opus가 전체를 총괄합니다—큰 그림을 유지하고, 업무를 배분하며, 최종 점검을 수행합니다.
  • sonnet이 TDD (테스트 주도 개발) 계획을 세웁니다—설계에 따라 각 모듈이 어떻게 테스트되고 구현될지 계획을 수립합니다.
  • haiku가 코드를 작성하고 테스트를 실행합니다—저렴하고 충분히 성능이 좋은 haiku에게 단순 반복 작업 (grunt work)을 맡깁니다.

이러한 분할은 지난 포스트에서 언급한 "모델 계층화 (model tiering)"—칼날에는 좋은 강철을 사용하라—의 연장선에 있습니다. 다만 지난번의 핵심이 비용 절감이었다면, 이번에는 이러한 역할들이 어떻게 함께 작동하는가에 관한 것입니다.

Orchestration: opus runs the show on top, fanning independent modules out to sonnet (planning) and haiku (implementation + tests); within a module it can split work further; finished work comes back to opus for review

작업을 분산시키는 방법

실제로 저는 세 가지를 수행했습니다:

  1. 전역 CLAUDE.md 파일에 한 줄을 작성했습니다: "가능할 때 병렬화(Parallelize) 하세요." 이것은 모든 프로젝트에 적용되는 기본 규칙입니다.
  2. Claude 설정에서 최대 동시 하위 에이전트(subagents) 수를 설정했습니다—이것이 실제로 중요한 조절 밸브 역할을 합니다.
  3. 지시를 내릴 때마다 한 가지 주의 사항을 추가했습니다: "가능한 한 많이 병렬화하세요." 리더인 opus는 이미 스스로 업무를 분산시키지만, 가벼운 독려가 이를 궤도에 유지시켜 줍니다.

리더가 모듈을 전달하면, 모듈 내부에서 작업을 한 단계 더 분할할 수 있습니다. 층층이 쌓인 구조를 통해 전체 작업이 넓게 퍼져나갑니다.

건너뛰어서는 안 될 검토 단계

병렬로 빠르게 실행하면서 어떻게 품질을 유지할까요? 제 대답은 이렇습니다: 리더가 자신의 결과물을 직접 검토하게 하세요.

논리는 명확합니다: 리더가 업무를 배분했으므로, 각 하위 에이전트가 무엇을 수행해야 하는지 정확히 알고 있습니다. 따라서 리더가 검토를 수행하는 것이 자연스럽게 맞아떨어집니다. 별도의 전담 검토 에이전트를 설정해 보기도 했지만, 그 에이전트는 전체 작업을 처음부터 다시 이해해야만 했습니다. 이는 토큰을 추가로 소모하며 속도를 늦추는 결과를 초래했습니다. 리더가 직접 검토하게 하면 이러한 재이해(re-understanding)에 드는 오버헤드를 줄일 수 있으며, 더 빠르고 더 날카로운 검토가 가능합니다.

문제가 발생한 후에는 작은 디테일이 하나 있습니다. 리드(lead) 에이전트가 보통 저에게 이렇게 묻습니다. "이걸 직접 수정할까요, 아니면 다른 에이전트를 새로 띄워서 처리할까요?" 저는 거의 항상 "직접 수정하세요"라고 말합니다. 왜냐하면 결함을 방금 찾아낸 바로 그 에이전트가 문제가 어디에 있는지 가장 잘 알고 있으며, 그 에이전트가 직접 수정하는 것이 가장 직접적인 변화를 가져오기 때문입니다.

내가 빠졌던 두 가지 함정

첫 번째는 메모리(memory)였습니다. 초기에는 욕심을 부려 최대 병렬 처리 수(max concurrency)를 10으로 설정했습니다. 하지만 당시 다른 프로젝트들도 병렬로 실행 중이었고, 기계의 메모리가 완전히 바닥나 버렸습니다. 그래서 솔직히 5로 낮추었는데, 결과적으로는 더 좋았습니다. 이 작업 하나만 놓고 보면, 5개를 병렬로 돌리는 것은 직렬(serial) 실행보다 대략 5배 빠릅니다. 동시에 실행되는 다른 작업들까지 고려하면 전체적인 속도 향상(speedup)은 10배를 상회합니다. 만약 사용 중인 기계와 할당량(quota)이 버틸 수 있다면 숫자를 더 높이십시오. 그렇지 않다면 억지로 밀어붙이지 마세요.

두 번째는, 단순히 나누기 위해 나누지 말라는 것입니다. 어떤 모듈들은 서로 밀접하게 결합(tightly coupled)되어 있어 순서대로 처리되어야 합니다. 만약 병렬화를 위해 이들을 억지로 분리하면, 에이전트들이 서로 간섭하게 되어 품질이 완전히 망가집니다. 그래서 작업을 넘기기 전에 다음과 같은 구체적인 주의 사항을 추가합니다: "이 모듈들은 결합되어 있으니, 억지로 분리하지 마세요." 다행히 많은 AI가 이를 스스로 인식하여 억지로 분리하지 않습니다. 진정으로 분리할 수 없는 작업이라면, 그냥 하나의 에이전트에게 직렬로 처리하게 하거나 리드 에이전트가 해당 스레드(thread)를 처음부터 끝까지 실행하도록 하십시오.

직관에 반하는 수학적 사실

많은 사람이 "5개의 에이전트가 동시에 돌아간다"는 말을 들으면 가장 먼저 이렇게 반응합니다: "토큰(token) 소모량이 배로 늘어나지 않을까요?"

제가 계산하는 방식으로는 그렇지 않습니다. 직렬로 수행했을 때와 동일한 양의 작업은 대략 비슷한 양의 토큰을 소모합니다. 읽어야 할 것은 여전히 읽어야 하고, 써야 할 것은 여전히 써야 합니다. 병렬화가 추가적인 작업을 만들어내지는 않습니다. 병렬화가 실제로 바꾸는 것은 비용이 아니라 **실제 소요 시간(wall-clock time)**입니다. 예전에는 대기열(queue)에서 차례를 기다려야 했던 시간들이 이제는 같은 시간대 안에 동시에 실행됩니다. 아주 약간의 추가 토큰 비용으로 시간 비용을 크게 낮출 수 있으니, 이는 매우 훌륭한 거래입니다.

Serial vs parallel: the same work, total tokens roughly equal, but parallel cuts the wall-clock to about 1/5—what you save is time, not spend

따라서 진정으로 분할할 수 없는 것들을 제외하고는, 요즘 저는 기본적으로 분할 가능한 모든 것을 병렬화 (parallelize) 합니다.

요약: 바로 실행할 세 가지 사항

첫째, 클린 아키텍처 (clean architecture)를 먼저 구축한 다음 병렬화를 논하세요. 느슨한 결합 (loosely coupled), 높은 응집도 (highly cohesive), 인터페이스 계약 (interface contracts)을 통한 통신—이러한 토대 없이는 분할 작업이 재앙이 될 수 있습니다. 설계 단계에서 AI와 함께 이를 확실히 다져놓으세요.

둘째, 가능한 모든 것을 병렬화하되, 상한선 (ceiling)을 설정하세요. 크다고 해서 무조건 좋은 것은 아닙니다. 사용 중인 머신의 메모리와 AI 할당량 (quota)에 맞춰 크기를 조절하세요. 저는 메모리 문제로 인해 10개에서 다시 5개로 줄였습니다.

셋째, 빠른 병렬화에는 검토가 필요합니다. 그리고 검토자는 반드시 해당 작업을 실제로 이해하고 있어야 합니다. 작업을 할당했던 리드 (lead)가 확인하도록 하세요. 이것이 가장 저렴하고 예리한 방법입니다. 문제가 발견되면, 그 리드가 직접 수정하도록 하세요.

오늘 바로 할 수 있는 한 가지: 전역 CLAUDE.md 파일을 열고 "가능할 때 병렬화할 것 (parallelize when you can)"을 추가한 다음, 설정으로 가서 최대 동시 서브에이전트 (max concurrent subagents) 수를 머신이 처리할 수 있는 숫자로 높이세요. 다음에 분할 가능한 작업을 맡기면, 작업이 대기열 (queuing)에 쌓이지 않는 것을 느낄 수 있을 것입니다.

다음 포스트에서는 이 문제 바로 뒤를 잇는 문제에 대해 다뤄보고 싶습니다. 여러 에이전트가 동시에 코드를 수정할 때, 서로의 작업을 망치지 않게(clobbering) 하는 방법은 무엇일까요? 그 답은 git worktree입니다. 각 에이전트에게 독립된 작업 공간을 부여하여, 각자 자신의 복사본에서 작업하게 함으로써 누구도 타인의 작업을 방해하지 않도록 하는 것입니다. 관심이 있다면 댓글로 알려주세요.

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0