Multi-Agent 09
Router 패턴: 단순 분기를 넘어선 전문가 위임과 비용 최적화
Router를 단순 if문과 같은 것으로만 보면 패턴의 의미가 작아진다.
근거 · 교안 p25-p26
1장: Router: 단순 조건문이 아닌 ‘결정자’의 탄생
솔라는 노트북 화면에 떠 있는 문장 하나에 시선이 묶여 있었다. 기술 블로그의 아티클 한 구절이었다. ‘Router 패턴: 입력을 분류하여 전문가에게 위임하기.’ 몇 번을 다시 읽어도 개운하지 않은 느낌에 솔라는 미간을 찌푸렸다.
“언니, 잠깐 이것 좀 봐봐.”
옆에서 조용히 책을 읽던 루나가 고개를 들었다. 솔라가 노트북을 루나 쪽으로 돌렸다.
“Router 패턴이라는 게 있는데, 들어온 요청을 분류해서 알맞은 처리기(Agent)에 보낸대. 근데 이거… 그냥 if문으로 조건 몇 개 만들어서 함수 호출하는 거랑 본질적으로 뭐가 다른 거지? 말을 너무 어렵게 하는 거 아니야?”
솔라의 목소리에는 ‘결국 다 똑같은 이야기’라는 확신이 섞여 있었다. 어떤 값이 들어오면, 그 값에 따라 다른 코드를 실행한다. 이게 조건문의 전부이고, Router라는 것도 그 이상으로 보이지 않았다.
루나는 화면을 잠시 들여다보더니, 노트북을 덮어 옆으로 밀어두었다. 그리고는 빈 테이블을 손으로 툭툭 쳤다.
“솔라, 네가 아주 큰 회사의 안내 데스크에 혼자 앉아있다고 상상해 보자.”
“안내 데스크?”
“응. 하루에도 수백, 수천 건의 요청이 너한테 쏟아지는 거야. ‘신제품 환불받고 싶어요’라는 이메일, ‘서비스 장애 문의’라는 전화, ‘신입사원인데 제 자리가 어디죠?‘라며 찾아온 사람까지.”
루나의 말에 솔라는 자연스럽게 상황을 그리기 시작했다.
“음, 그럼 내가 요청을 하나씩 확인해야겠네. 환불 요청이면 재무팀으로 연결하고, 장애 문의는 기술 지원팀에, 신입사원은 인사팀에 알려주고… 정신없겠지만, 못 할 건 없지.”
솔라의 대답은 명쾌했다. 그녀의 머릿속에서는 if (request == '환불') { connectTo('재무팀'); } else if (request == '장애') { connectTo('기술지원팀'); } 같은 코드가 그려지고 있었다.
“바로 그 지점이야.”
루나가 말했다.
“네가 방금 ‘연결하고’, ‘알려주고’라고 했지? 그 일을 하려면, 네가 각 요청의 내용을 최소한은 이해해야 해. 환불 요청이 타당한지 서류를 검토하거나, 장애 문의가 어떤 서비스에 대한 건지 기술 용어를 알아들어야 할 수도 있지. 만약 네가 그 모든 걸 직접 판단하고 처리한다면, 네 안내 데스크는 금방 마비될 거야. 요청이 밀려들수록 너는 점점 느려지겠지.”
“음… 그렇긴 하겠네. 내가 모든 팀의 업무를 조금씩은 알아야 하니까.”
솔라가 고개를 끄덕였다. 병목이 되는 지점이 선명하게 보였다. 바로 자기 자신이었다.
“자, 그럼 역할을 바꿔보자. 너는 안내 데스크의 직원이 아니야. 너는 그 직원을 돕는, 아주 유능한 ‘비서’야. 네 일은 요청을 처리하는 게 아니야. 오직 한 가지, ‘이 서류 뭉치는 어느 부서로 가야 하는가?‘만 판단하는 거지.”
루나는 테이블 위에 놓인 펜 하나를 집어 솔라에게 건넸다.
“이게 ‘환불 요청서’라고 해봐. 비서인 너는 이 안에 적힌 환불 사유나 금액을 읽을 필요가 없어. 그냥 겉면에 쓰인 ‘환불’이라는 두 글자만 보고 재무팀 책상에 던져주면 돼. ‘기술 문의’라고 적힌 서류는 내용이 뭔지 볼 필요도 없이 기술 지원팀 바구니에 넣고.”
솔라는 손에 들린 펜을 내려다보았다. 처음에는 안내 데스크에서 모든 것을 해결하려던 자신의 모습과, 지금 루나가 설명한 비서의 모습이 겹쳐 보였다. 역할이 완전히 달랐다.
“아…”
솔라에게서 나지막한 탄성이 터져 나왔다.
“그러니까… Router는 요청을 직접 처리하는 게 아니구나. 나는 if문처럼 Router가 조건에 따라 자기가 직접 함수를 호출하며 일을 처리한다고 생각했는데… 그게 아니라 그냥 ‘판단’만 하는 거네. ‘이건 네 담당’ 하고 알려주기만 할 뿐, 실제 환불 절차나 기술적인 해결은 전혀 신경 쓰지 않는 거야.”
“맞아. 그래서 Router를 그냥 조건 분기문이라고 부르지 않고 ‘결정자(Dispatcher)‘라고 부르는 거야. 교통경찰처럼 신호만 보내줄 뿐, 자동차를 직접 운전하지는 않잖아. 요청을 처리하는 게 아니라, 가장 잘 처리할 전문가에게 빠르고 정확하게 ‘파견(dispatch)‘하는 역할에만 집중하는 거지.”
솔라는 다시 노트북을 열어 아까 봤던 문장을 읽었다. ‘입력을 분류하여 전문가에게 위임하기.’ 이제야 ‘위임’이라는 단어의 무게가 다르게 느껴졌다. 그냥 함수를 호출하는 게 아니었다. 책임과 실행의 주체를 완전히 넘겨버리는 행위였다.
“역할이 다르다는 건 이제 알겠어. 내가 일을 하는 게 아니라, 일할 사람을 지정해주는 역할이라는 거. 그런데 언니, 그 ‘결정자’라는 것도 결국 코드로 구현하면 if문이나 switch문을 쓰는 거 아니야? ‘환불’이라는 단어가 있으면 재무팀으로 보내고, 아니면 다른 걸 확인하고… 구조적으로는 결국 똑같은 거 같은데. ‘던져준다’는 그 방식이 구체적으로 어떻게 다르다는 거지?“
2장: Router의 본질: 의도 분류, 병렬 처리, Stateless
솔라는 거실 테이블에 커다란 스케치북을 펼쳐놓고 두 개의 다이어그램을 그리고 있었다. 하나는 위에서 아래로 흐르는 깔끔한 순서도였다. ‘요청 입력’이라는 상자에서 시작해, ‘환불인가?’라는 마름모를 만나 ‘예’이면 ‘재무팀 전달’로, ‘아니오’이면 다음 마름모인 ‘장애 문의인가?’로 이어지는 구조. 전형적인 if-else의 흐름이었다. 그 옆에는 두 번째 다이어그램을 그렸다. ‘요청 입력’ 상자 다음에 ‘Router’라는 조금 더 큰 상자가 있고, 그 상자에서 똑같이 여러 개의 화살표가 뻗어 나가 각 팀으로 연결되었다. 솔라는 두 그림을 번갈아 보며 고개를 갸웃했다.
루나가 다가와 스케치북을 들여다보자, 솔라는 펜 끝으로 두 다이어그램을 툭툭 쳤다. “언니 말대로 Router가 직접 일을 안 하고 ‘결정’만 한다는 건 알겠어. 그런데 내 눈에는 이 구조가 결국 똑같아 보여. Router라는 상자 안에서 if문 돌리는 거랑, 그냥 if문 쓰는 거랑 뭐가 달라? 길만 나눠주는 거면, 결국 한 번에 한 길로만 가는 거잖아.”
솔라의 그림은 그녀의 질문을 명확하게 보여주고 있었다. Router를 그저 조건문이 담긴 예쁜 상자로 이해하고 있었다. 루나는 고개를 끄덕이며 잠시 생각하더니, 입을 열었다.
“좋아, 솔라. 네가 그린 그 두 번째 다이어그램에 아주 까다로운 손님을 한 명 초대해 보자.”
“까다로운 손님?”
“응. 고객센터에 이런 이메일이 왔다고 상상해 봐. ‘안녕하세요. 이번 달 휴대폰 요금이 왜 이렇게 많이 나왔는지 상세 내역 좀 알려주시고요, 혹시 제가 적용받을 수 있는 할인 혜택이 있는지도 확인해주세요. 그리고 나온 김에 더 좋은 요금제로 바꿀 수 있는지도 궁금하네요.’”
솔라는 이메일 내용을 들으며 잠시 눈살을 찌푸렸다. 요청이 세 개나 한꺼번에 들어 있었다. 그녀는 자신의 첫 번째 if-else 다이어그램을 손가락으로 따라가기 시작했다.
“음… 일단 ‘요금’이라는 단어가 있으니, ‘요금 문의인가?’ 조건에서 ‘예’가 되겠네. 그럼 ‘청구팀’으로 연결. 거기서 끝나는데?”
“바로 그거야. 단순 if-else 구조는 첫 번째로 참이 되는 조건에서 실행이 끝나버리지. 그럼 나머지 두 요청은 어떻게 해? 고객에게 다시 문의하라고 해야 하나?”
“아니, 그럼 if를 연달아 쓰면 되지. 요금인지 확인해서 청구팀에 알리고, 할인인지 확인해서 마케팅팀에 알리고, 요금제인지 확인해서 상품팀에 알리고…”
솔라가 자신있게 대안을 제시했다. 하지만 루나는 빙그레 웃으며 한 가지를 더 짚었다.
“그 방법은 가능하지만, 순서대로 처리해야 하네. 청구팀 일이 끝날 때까지 마케팅팀은 기다려야 하고, 마케팅팀 일이 끝나야 상품팀이 시작할 수 있어. 세 가지 답변을 모두 받는 데 시간이 아주 오래 걸리겠지. 고객은 그저 이메일 하나 보냈을 뿐인데.”
루나는 솔라의 스케치북에 그려진 ‘Router’ 상자를 손가락으로 가리켰다.
“Router의 진짜 힘은 여기서 나와. 첫째, Router는 단순한 키워드 검사기가 아니야. ‘의도 분류(Intent Classification)’ 전문가에 가까워. 고객의 긴 문장에서 ‘요금 조회’, ‘할인 문의’, ‘요금제 변경’이라는 세 가지 독립적인 ‘의도’가 있다는 걸 한 번에 파악해 내.”
“하나의 조건이 아니라, 여러 개의 의도를 동시에 알아챈다고?”
“응. 그리고 두 번째, 그래서 Router는 **‘병렬 처리(Parallel Processing)‘**에 강해. 하나의 길을 선택하는 게 아니라, 파악된 세 개의 의도를 각각의 전문가에게 동시에 던져주는 거야. 청구팀, 마케팅팀, 상품팀이 ‘땅!’ 하는 소리와 함께 각자 자기 일을 시작하는 거지. 서로 기다릴 필요 없이.”
루나의 설명에 솔라의 머릿속에서 새로운 그림이 그려졌다. 하나의 줄기에서 차례로 가지가 뻗어 나가는 나무가 아니었다. 중앙의 허브에서 사방으로 빛이 동시에 뿜어져 나가는 모습에 가까웠다.
솔라는 잠시 생각에 잠겼다. “동시에 일을 시작하면 훨씬 빠르긴 하겠네… 근데 그러면 일이 복잡해지지 않아? 마케팅팀에서 할인 정보를 찾았는데, 그게 특정 요금제에만 적용되는 거면 어떡해? 상품팀이 뭘 하고 있는지 알아야 하잖아.”
“좋은 지적이야. 그리고 그게 Router의 세 번째 특징, **‘Stateless(무상태)‘**와 연결돼.” 루나가 말했다. “각 전문가, 즉 에이전트는 자기 일을 하는 데 필요한 모든 정보를 요청과 함께 전달받아. 다른 전문가의 작업 상태나 중간 결과에 의존하지 않아. 각자 독립적으로 완결된 일을 처리하고, 그 결과를 Router에게 돌려주기만 하면 돼. 나중에 그 결과들을 취합하는 건 다른 조정자(Coordinator)나 혹은 Router 자신이 할 일이지. 덕분에 시스템 전체의 구조가 훨씬 단순하고 명확해져.”
솔라는 이제 자신의 스케치북에 그린 두 번째 다이어그램이 완전히 틀렸다는 것을 깨달았다. 화살표를 여러 개 그리긴 했지만, 그건 여전히 ‘여러 길 중 하나’를 고르는 모습이었다. 진짜 Router는 그런 분기점이 아니었다.
“아…”
솔라의 입에서 작은 탄식이 흘러나왔다.
“단순히 길을 나눠주는 게 아니었구나. 들어온 요청을 해체해서 여러 개의 독립적인 일감으로 만들고, 그걸 여러 전문가에게 동시에 뿌려주는 ‘작업 지시 센터’ 같은 거였어. if문은 정해진 길 중 하나를 가는 거고, Router는 아예 여러 개의 길을 새로 만들어서 동시에 출발시키는 거네.”
솔라는 펜을 들어 두 번째 다이어그램의 ‘Router’ 상자 옆에 새로운 단어들을 적기 시작했다. ‘의도 분류’, ‘병렬 처리’, ‘Stateless’. 이제 보니 ‘결정자’라는 역할의 구조적인 실체가 보이기 시작했다. 이건 if문 몇 개로 흉내 낼 수 있는 방식이 아니었다.
“구조가 완전히 다르다는 건 이제 알겠어. 훨씬 빠르고 효율적이겠네. 그런데 언니, 이런 구조를 만들려면 전문가 팀도 여러 개 만들어야 하고, 의도를 분석하는 똑똑한 Router도 개발해야 하잖아. 그냥 개발자 한 명이 if문 길게 짜는 것보다 훨씬 비싸고 복잡한 일 아니야? 이게 어떻게 ‘비용 최적화’로 이어진다는 거지?“
3장: 언제 Router가 빛을 발하는가? 효율성과 비용 최적화
솔라는 자신의 스케치북에 그린 다이어그램 옆, 빈 페이지에 두 개의 가상 견적서를 그리고 있었다. 하나는 ‘만능 해결사 A팀’, 다른 하나는 ‘전문가 연합 B팀 (Router 방식)’이라는 제목이 붙어 있었다. 솔라의 펜은 망설임 없이 각 팀의 예상 비용을 채워나갔다.
[A팀: 만능 해결사]
- 최고급 만능 개발자 1명: 월 1,000만 원
- 총계: 1,000만 원
[B팀: 전문가 연합 (Router)]
- Router 개발 및 유지보수: 월 300만 원
- 청구 전문가 1명: 월 500만 원
- 마케팅 전문가 1명: 월 500만 원
- 상품 전문가 1명: 월 500만 원
- 총계: 1,800만 원
견적서를 완성한 솔라는 펜을 내려놓고 팔짱을 꼈다. 그녀의 미간에 다시 희미한 주름이 잡혔다. 숫자는 명백했다. B팀이 훨씬 비쌌다.
“언니, 이거 봐봐. 내가 생각해도 이상해.”
솔라가 스케치북을 루나에게 내밀었다. 루나는 솔라가 만든 두 개의 가상 견적서를 조용히 들여다보았다.
“병렬 처리가 가능하고, 의도를 파악해서 일을 나눠주니 훨씬 빠르고 효율적인 건 알겠어. 그런데 초기 구축 비용이나 월간 유지보수 비용을 생각하면, 그냥 똑똑한 사람 한 명 뽑아서 if문으로 다 처리하게 하는 게 훨씬 싸게 먹히는 거 아니야? B팀은 인건비만 해도 거의 두 배잖아. 이게 어떻게 ‘비용 최적화’가 되는 거지? 속도가 빠른 만큼 비싼 값을 치르는, 그냥 고성능 옵션 같은데.”
솔라의 질문은 타당했다. 그녀의 견적서는 ‘인건비’라는 단일 척도에만 집중하고 있었다. 빠른 응답과 병렬 처리의 가치는 그저 ‘성능’이라는 추상적인 항목으로만 남아, 비용 계산에는 전혀 반영되지 않았다.
루나는 솔라의 견적서에서 눈을 떼지 않은 채, 차분한 목소리로 물었다.
“좋은 비교야. 그럼, 이 회사에 네 번째 요구사항이 들어왔다고 상상해 보자. 예를 들어 ‘실시간 배송 조회’ 기능이 필요해졌어. 이 새로운 업무를 각 팀에 추가해 볼래?”
루나의 말에 솔라는 다시 펜을 들었다. 그녀는 먼저 A팀의 ‘만능 해결사’ 항목 아래에 작은 글씨로 메모를 추가하기 시작했다.
“A팀은… 일단 배송 시스템에 대한 공부를 새로 해야겠네. 학습 기간이 필요할 거고, 기존의 요금, 할인, 상품 처리 로직에 배송 조회 로직까지 추가되면 코드가 엄청 복잡해지겠지. 버그가 생길 확률도 높아지고, 만능 해결사 한 명에게 모든 부담이 쏠려서… 결국 전체 처리 속도가 느려질 거야.”
솔라의 펜이 잠시 허공에서 멈췄다. 비용은 월 1,000만 원으로 같았지만, 그 비용으로 얻어내는 가치가 떨어지고 있었다. 보이지 않는 비용, 즉 ‘기회비용’과 ‘유지보수 비용’이 눈덩이처럼 불어나는 것이 느껴졌다.
이번에는 B팀 항목으로 시선을 옮겼다.
“B팀은… 그냥 ‘배송 전문가’ 한 명을 더 채용하고, Router에 ‘배송’이라는 키워드가 들어오면 새 전문가에게 연결하라는 규칙 하나만 추가하면 되겠네.”
솔라는 B팀 견적서에 ‘배송 전문가 1명: 월 500만 원’을 추가했다. 총계는 2,300만 원으로 늘어났다. 하지만 솔라의 표정은 어둡지 않았다.
“기존 청구, 마케팅, 상품 전문가들은 아무 영향을 받지 않고 자기 일을 계속할 수 있어. 시스템 전체의 안정성도 그대로고. 새로운 기능이 추가되는 속도도 훨씬 빠르겠네.”
바로 그 순간, 솔라는 무언가 깨달은 듯했다. 그녀가 간과했던 비용의 다른 측면들이 보이기 시작했다.
“아… 비용이라는 게 단순히 월급 총액이 아니구나.”
“맞아.” 루나가 조용히 동의했다. “두 가지 비용을 더 생각해 봐. 첫째, 자원 활용의 비용. 만능 해결사는 비싼 몸값의 전문가인데, 어쩌면 전체 업무의 50%는 아주 단순하고 반복적인 일일지도 몰라. 하지만 전문가 연합은? 단순한 일은 저렴한 자동화 도구나 신입 전문가에게 맡기고, 복잡한 일에만 비싼 전문가를 투입할 수 있지. 각 작업의 난이도에 맞는 ‘비용 최적화된’ 전문가를 배치하는 거야. 모든 요청을 처리하기 위해 매번 최고 사양의 슈퍼컴퓨터를 돌릴 필요는 없으니까.”
루나의 비유에 솔라는 고개를 끄덕였다. 모든 이메일에 답장하기 위해 박사 학위 소지자를 고용할 필요는 없다는 뜻이었다.
“둘째는 시간의 비용. 고객의 요청이 복잡해서 세 명의 전문가가 동시에 달라붙어 10분 만에 해결하는 것과, 한 명의 만능 해결사가 순서대로 처리하느라 30분을 끄는 것. 고객에게 20분의 차이는 서비스를 계속 쓸지 말지를 결정하는 시간일 수 있어. 빠른 응답으로 얻는 고객 만족과 이탈 방지는 그 자체로 엄청난 금전적 가치야.”
솔라는 자신의 첫 번째 견적서를 가만히 내려다보았다. 너무나 단순하고 평면적인 비교였다. 그녀는 망설임 없이 그 페이지에 커다란 X자를 그었다. 그리고 새 페이지를 펼쳤다. 이번에는 견적서가 아니었다. 그녀는 ‘Router 패턴 도입 타당성 평가’라는 제목 아래, 질문 목록을 작성하기 시작했다.
- 전문 영역 분리가 명확한가? (환불, 기술 지원, 배송 등 서로 다른 지식이 필요한가?)
- 작업 간 의존성이 낮은가? (하나의 요청을 여러 독립적인 작업으로 나눌 수 있는가?)
- 빠른 응답과 병렬 처리가 사업적으로 중요한가? (사용자 대기 시간이 매출이나 만족도에 직접적인 영향을 미치는가?)
- 향후 기능 확장이 자주 예상되는가? (새로운 유형의 요청이 계속 추가될 가능성이 있는가?)
- 작업의 난이도와 중요도가 다양하여, 비용이 다른 여러 처리기(Agent)를 조합할 때 효율이 극대화되는가?
목록을 완성한 솔라는 만족스러운 표정으로 스케치북을 덮었다. 이제 ‘if문과 뭐가 다른가?’라는 최초의 질문은 무의미해졌다. 그녀의 머릿속에는 대신 훨씬 더 구체적이고 실용적인 질문들이 자리 잡고 있었다. Router는 더 이상 복잡하고 비싼 기술이 아니었다. 시스템의 성장과 변화에 유연하게 대응하며, 보이지 않는 비용까지 절감하는 현명한 투자 전략으로 보이기 시작했다. 자신의 프로젝트에 이 전략이 필요한지 판단할 수 있는 명확한 기준이 생긴 것이다.