병렬화는 직관적으로 매력적입니다. 할 일이 여덟 개고 에이전트를 여덟 개 띄울 수 있다면, 안 할 이유가 없어 보입니다.

그런데 이 계산에는 세 가지 비용이 빠져 있습니다. 나누는 비용, 공유 자원을 기다리는 비용, 그리고 합치는 비용입니다. 셋을 더하면 결과가 자주 뒤집힙니다.

1. 나눌 수 있는 일의 조건

기준은 하나입니다. 서로의 결과를 안 봐도 되는가.

이 저장소의 콘텐츠 작업을 그 기준으로 갈라보면 이렇게 나옵니다.

주제 선정 8개 주제는 서로 겹치면 안 된다 → 3번 주제를 정하려면 1·2번이 뭔지 알아야 한다 → 항목끼리 의존한다. 나눌 수 없다. 각 글 집필 3번 글을 쓰는 데 5번 글의 내용이 필요하지 않다 → 항목끼리 독립적이다. 나눌 수 있다. 빌드·커밋 작업 트리가 하나, 브랜치가 하나 → 공유 자원. 나눠도 줄을 선다.

주제 선정이 겉보기에 가장 병렬화하기 좋아 보이는 단계인데 실제로는 정반대입니다. "각자 좋은 주제를 하나씩 골라와"라고 하면 비슷한 주제가 여러 개 나옵니다. 각 에이전트가 같은 기존 글 목록을 보고 같은 빈칸을 찾아내기 때문입니다.

독립적으로 보이는 판단이 사실은 같은 입력을 공유하고 있을 때, 병렬화는 다양성이 아니라 중복을 만듭니다.

2. 공유 자원은 병렬화되지 않는다

집필은 나눌 수 있다고 했는데, 여기에도 조건이 붙습니다. 글을 쓰는 것과 커밋하는 것은 다른 일입니다.

여덟 에이전트가 같은 작업 트리에서 동시에 파일을 만들고 각자 빌드를 돌리면, 서로가 만든 중간 상태를 보게 됩니다. A 가 빌드를 돌리는 순간 B 가 아직 ko 만 만들어놨다면 그 빌드는 실패합니다. ko/en 대칭 검사에 B 의 미완성 작업이 걸립니다.

A 의 잘못이 아닌데 A 가 실패합니다. 그리고 A 는 왜 실패했는지 알 수 없습니다 — 자기가 만들지 않은 파일 이야기가 에러에 나오니까요.

해결 방식 두 가지 격리: 에이전트마다 독립된 작업 공간을 준다 → 간섭은 없어지지만 합칠 때 충돌을 처리해야 한다 직렬화: 쓰는 건 병렬, 빌드·커밋은 한 줄로 → 단순하지만 병목이 남는다

이 작업에서는 두 번째를 골랐습니다. 글 여덟 편의 빌드는 각각 1초 미만이라 병목이 사실상 없기 때문입니다. 격리 환경을 만들고 나중에 합치는 비용이 훨씬 큽니다.

판단 기준은 공유 자원을 붙잡는 시간이 실제로 긴가 입니다. 빌드가 10분 걸린다면 답이 달라집니다.

3. 합치는 비용이 가장 자주 잊힌다

병렬 작업의 결과는 누군가 읽고 판단해야 합니다. 이 단계가 계산에서 늘 빠집니다.

여덟 에이전트가 각자 글을 써오면 그 여덟 편이 서로 어울리는지 확인해야 합니다.

  • 같은 개념을 서로 다른 용어로 부르지 않는가
  • 세 편이 같은 예시를 반복하지 않는가
  • 글 사이 링크가 실제로 존재하는 글을 가리키는가
  • 문체가 한 사람이 쓴 것처럼 읽히는가

이걸 확인하려면 여덟 편을 다 읽어야 합니다. 그러면 검토하는 쪽의 컨텍스트에 여덟 편이 전부 들어와야 하고, 이건 순차적으로 쓸 때는 필요 없던 비용입니다.

순차 작업에서는 앞 글을 쓰면서 이미 맥락이 쌓입니다. 5번 글을 쓸 때 1~4번의 용어와 예시를 이미 알고 있어서 따로 맞출 필요가 없습니다. 병렬화는 그 맥락을 버리는 대가로 속도를 삽니다.

숫자로 놓으면 손익분기가 보인다

"빨라질 것 같다"를 식으로 바꾸면 어디서 뒤집히는지가 분명해집니다. 항목 N개, 항목당 처리 시간 T, 에이전트 하나를 띄우고 지시를 준비하는 고정비 F, 결과를 읽고 합치는 비용 M이라고 두면 이렇습니다.

직렬 = N × T 병렬 = N × F + T + M ─────── ─── ─── 띄우는 가장 합치는 고정비 느린 비용 하나 이득 = (N−1) × T − N × F − M

글 여덟 편에 실제 값을 넣어봤습니다. 한 편에 12분, 에이전트 하나 띄우고 무엇을 쓸지 정리해 넘기는 데 1.5분이 들었습니다.

N = 8, T = 12분, F = 1.5분 이득 = 7 × 12 − 8 × 1.5 − M = 84 − 12 − M = 72 − M → 합치는 비용 M 이 72분을 넘으면 병렬이 더 느리다

72분이 커 보이지만 그렇지 않습니다. 여덟 편을 정독하면서 용어를 맞추고 중복 예시를 걷어내는 데 한 편당 9분만 써도 8 × 9 = 72분, 정확히 손익분기입니다. 여기에 어긋난 두어 편을 고치는 재작업은 아직 넣지도 않았습니다.

(N−1) × T 가 병렬화로 얻을 수 있는 최대치입니다.

N 을 아무리 키워도 이득은 항목 하나 처리 시간의 N−1 배를 넘지 못하고, 고정비와 합류 비용은 N 에 비례해 늘어납니다. 항목을 더 잘게 쪼갤수록 이득이 커진다는 직관이 여기서 깨집니다.

4. 그래서 실제로 나눈 지점

결국 이 작업에서 병렬로 돌린 건 집필이 아니라 조사였습니다.

직렬: 기존 글 20편의 주제·날짜 수집 → 8개 주제 선정 (겹침 판정이 필요) 병렬: 각 주제별 근거 자료 수집 → 서로 볼 필요 없음, 결과가 짧음 직렬: 집필 → 빌드 → 커밋 (한 편씩)

조사가 병렬에 잘 맞는 이유는 두 가지입니다. 항목끼리 정말로 독립적이고, 결과물이 짧아서 합치는 비용이 작습니다. 자료 요약 열 줄을 여덟 개 받아 읽는 건 글 여덟 편을 읽는 것과 비교가 안 됩니다.

여기서 일반화할 만한 규칙이 나옵니다. 병렬화는 "넓게 찾고 좁게 답하는" 작업에 잘 맞습니다. 입력이 넓게 흩어져 있고 출력이 압축되는 형태 — 탐색, 검색, 수집, 검증이 그렇습니다.

반대로 출력이 큰 작업은 병렬화 이득이 작습니다. 결과물 자체가 커서 그걸 다시 읽고 합치는 데 원래 작업만큼 드는 경우가 있습니다.

작업 유형별로 미리 갈라두기

매번 처음부터 따지지 않으려고 자주 하는 작업을 미리 분류해뒀습니다. 세 열이 곧 앞에서 본 세 비용입니다.

작업 항목 독립 출력 크기 합류 비용 적합도 ────────────────────────────────────────────────────────────────── 코드베이스 검색 높음 작음(경로) 낮음 매우 좋음 자료 조사·근거 수집 높음 작음(요약) 낮음 좋음 테스트 실행·결과 수집 높음 작음(통과/실패) 낮음 좋음 파일별 기계적 치환 높음 중간 중간 좋음 링크·참조 검증 높음 작음 낮음 매우 좋음 ────────────────────────────────────────────────────────────────── 글·문서 집필 낮음 큼 높음 나쁨 리팩터링(구조 변경) 낮음 큼 높음 나쁨 주제·계획 수립 낮음 작음 높음 매우 나쁨

아래 세 줄에서 "주제·계획 수립"만 출력이 작은데도 적합도가 최악인 게 눈에 띕니다. 출력 크기는 세 비용 중 하나일 뿐이고, 여기서는 항목 독립성이 아예 없기 때문입니다 — 앞의 1번에서 본 바로 그 경우입니다.

반대로 "파일별 기계적 치환"은 합류 비용이 중간인데도 적합도가 좋습니다. 결과를 사람이 읽어 판단하는 게 아니라 빌드가 대신 검사하기 때문입니다. 합류 비용을 기계로 넘길 수 있으면 그 항목의 등급이 한 단계 올라갑니다.

5. 나누면 안 되는 것

속도와 무관하게 나누는 것 자체가 품질을 떨어뜨리는 작업이 있습니다.

  • 일관된 목소리가 필요한 것. 한 사람이 쓴 것처럼 읽혀야 하는 글은 나눌수록 이어붙인 티가 납니다.
  • 전체를 봐야 판정되는 것. 중복 여부, 균형, 순서 — 개별 항목만 봐서는 알 수 없습니다.
  • 되돌리기 어려운 작업. 여덟 개가 동시에 잘못된 방향으로 가면 여덟 개를 다 되돌려야 합니다. 피해 반경이 그만큼 넓어집니다.

세 번째는 무인 실행에서 특히 중요합니다. 순차 작업은 2번에서 이상하면 3번부터 방향을 고칠 수 있습니다. 병렬 작업은 여덟 개가 이미 다 끝난 뒤에야 그걸 알게 됩니다. 중간에 교정할 기회가 없다는 것이 병렬화의 숨은 비용입니다.

6. 판단 순서

나눌지 말지 고민될 때 이 순서로 봅니다.

1. 항목끼리 서로의 결과를 봐야 하는가 → 그렇다면 나눌 수 없다. 여기서 끝. 2. 공유 자원을 오래 붙잡는 구간이 있는가 → 있으면 그 구간은 어차피 줄을 선다 3. 결과물이 큰가, 작은가 → 크면 합치는 비용이 이득을 먹는다 4. 중간에 방향을 고칠 필요가 있는가 → 있으면 순차가 낫다

1번에서 대부분 걸러집니다. 그리고 1번을 잘못 판단하는 경우가 많습니다 — 항목끼리 직접 참조하지 않으니 독립적으로 보이지만, 실은 "서로 겹치면 안 된다" 같은 전체에 걸린 제약이 있는 경우입니다.

여덟 중 하나가 실패하면

병렬로 돌리면 부분 실패라는 상태가 새로 생깁니다. 순차로 돌 때는 없던 문제입니다 — 순차에서는 3번에서 멈추면 그냥 거기까지가 결과입니다.

네 가지 처리 방식을 써봤고, 각각 맞는 자리가 달랐습니다.

방식 내용 맞는 경우 ────────────────────────────────────────────────────────────── 전체 폐기 하나라도 실패하면 전부 버린다 항목이 서로 얽혀 부분 결과가 무의미할 때 부분 채택 성공분은 그대로 두고 항목이 진짜 독립일 때 실패분만 다시 (여기서는 이쪽) 재시도 1회 같은 지시로 한 번만 더 네트워크·일시적 실패 직렬 폴백 실패분을 순차로 다시 돌린다 원인을 모를 때. 간섭이 원인이면 이때 풀린다

기본값은 부분 채택으로 뒀습니다. 여덟 편 중 여섯 편이 멀쩡한데 전부 버리는 건 병렬화의 이득을 통째로 반납하는 것이라서요. 다만 부분 채택이 성립하려면 조건이 하나 있습니다 — 성공분만 남겨도 저장소가 정상 상태여야 합니다. 이 저장소에서는 글 한 편이 ko/en 두 파일 한 쌍이라, 여섯 편만 남아도 대칭이 깨지지 않습니다.

재시도는 한 번으로 제한했습니다. 두 번째도 실패하면 원인이 일시적인 게 아니라는 뜻인데, 그때 세 번째를 돌리면 같은 실패를 한 번 더 사는 것뿐입니다. 무한 재시도는 무인 실행에서 특히 위험합니다 — 아무도 안 보는 사이에 같은 실패를 반복하게 됩니다.

네 번째가 의외로 자주 답이었습니다. 실패 원인이 앞의 2번에서 본 공유 자원 간섭이면, 직렬로 다시 돌리는 것만으로 원인이 사라집니다. 그래서 "왜 실패했는지 모르겠다"일 때 제일 먼저 시도해볼 값어치가 있습니다.

자주 묻는 질문

동시에 몇 개까지 띄우는 게 좋나요?

동시 개수보다 합류 비용이 먼저 한계에 닿습니다. 위 식에서 M은 N 에 비례해 늘어나는데, 사람이나 검토 에이전트가 한 번에 읽고 판단할 수 있는 양은 늘어나지 않습니다. 결과물이 짧은 조사·검증이면 여덟 개도 무리가 없었고, 글처럼 출력이 큰 작업은 세 개를 넘기면 합치는 쪽이 병목이 됐습니다.

병렬 에이전트끼리 서로 대화하게 하면 되지 않나요?

그렇게 하면 병렬이 아닙니다. 서로의 결과를 봐야 한다는 건 곧 1번 조건에서 이미 탈락했다는 뜻입니다. 대화를 붙이면 대기가 생기고, 대기가 생기면 가장 느린 하나가 아니라 대화 왕복 횟수가 전체 시간을 정합니다. 의존이 있으면 그냥 순차로 두는 게 빠릅니다.

같은 작업을 여러 에이전트에게 시켜서 제일 좋은 결과를 고르는 건요?

그건 속도를 위한 병렬화가 아니라 품질을 위한 중복 실행입니다. 목적이 다르니 계산도 다릅니다 — 이득이 시간이 아니라 결과의 분산에서 나옵니다. 다만 앞에서 본 함정이 그대로 적용됩니다. 같은 입력을 주면 비슷한 답이 여러 개 나옵니다. 이 방식이 값어치가 있으려면 각 에이전트에게 서로 다른 관점이나 제약을 줘야 합니다.

병렬로 돌렸더니 결과의 형식이 제각각입니다

지시가 아니라 출력 형식이 고정돼 있지 않아서 생기는 문제입니다. 사람이 합칠 걸 전제로 자유 형식을 받으면 합류 비용이 그대로 늡니다. 받을 형태를 미리 못 박아두면 — 필드 이름과 순서까지 — 합치는 쪽이 읽는 대신 기계적으로 이어붙일 수 있습니다. 앞 표에서 "합류 비용을 기계로 넘긴다"고 한 게 이겁니다.

중간에 하나가 멈춘 걸 어떻게 아나요?

끝났는지 여부를 에이전트의 보고가 아니라 산출물로 판정합니다. "다 했습니다"는 실패한 에이전트도 말할 수 있지만, 파일 두 개와 빌드 통과는 못 만들어냅니다. 이건 병렬만의 문제가 아니라 재개 가능한 작업 설계와 같은 이야기입니다 — 완료 표시가 결과 자체에 남아 있으면, 멈춘 항목이 무엇인지 나중에 봐도 알 수 있습니다.

병렬화 이득이 없는데도 나눠야 할 때가 있나요?

있습니다. 한 작업이 컨텍스트 한도를 넘을 때입니다. 이때 나누는 이유는 속도가 아니라 애초에 한 번에 안 들어가기 때문이고, 판단 기준도 달라집니다 — 이건 무엇을 읽힐지 고르는 문제에 가깝습니다.

7. 정리

  • 나눌 수 있는 조건은 서로의 결과를 안 봐도 되는 것. 전체에 걸린 제약도 의존성입니다.
  • 같은 입력을 보는 병렬 판단은 다양성이 아니라 중복을 만든다.
  • 공유 자원 구간은 병렬화되지 않는다. 붙잡는 시간이 짧으면 그냥 직렬로 둡니다.
  • 합치는 비용을 계산에 넣는다. 결과물이 클수록 이득이 줄어듭니다.
  • 넓게 찾고 좁게 답하는 작업에 잘 맞는다. 탐색·수집·검증이 그렇습니다.
  • 병렬화는 중간 교정 기회를 포기하는 것이기도 하다.

여덟 편을 순차로 쓰는 데 걸린 시간은 병렬로 돌렸을 때보다 길었을 겁니다. 그런데 3편을 쓰다가 알게 된 것이 4편의 구조를 바꿨고, 5편에서 쓴 예시가 7편에서 다시 쓰였습니다. 나눴다면 그 연결은 생기지 않았을 것이고, 나중에 사람이 여덟 편을 읽으며 손으로 맞춰야 했을 겁니다.

병렬화는 속도를 사는 대신 맥락을 파는 거래입니다. 맥락이 별로 필요 없는 일에서는 좋은 거래이고, 맥락이 결과물의 품질 자체인 일에서는 나쁜 거래입니다.