LLMOps 16

반복 제어, 이제는 Supervisor와 함께!

반복 그래프가 이미 있으니 Supervisor가 꼭 필요 없다고 느낄 수 있다.

근거 · 교안 p44-p46

반복 제어, 이제는 Supervisor와 함께! 대표 이미지

1장: 루나: Critic, 너 너무 많은 걸 하고 있어

솔라는 만족스러운 미소를 지으며 책상 위에 펼쳐진 스케치북을 내려다보았다. 방금 완성한 AI 에이전트의 작업 흐름도였다. 네모, 마름모, 화살표들이 깔끔하게 제자리를 찾은 모습이 마음에 쏙 들었다. 특히 스스로를 개선하며 반복하는 루프 구조는 더 그랬다.

“언니, 이것 좀 봐봐! 내가 문서 분석 에이전트의 반복 로직을 그려봤어.”

거실에서 책을 읽던 루나가 솔라의 부름에 방으로 들어왔다. 솔라는 펜 끝으로 스케치북의 한 부분을 톡톡 가리켰다.

“여기 봐. ‘문서 요약 생성기(Generator)‘가 결과를 만들면, ‘평가자(Critic)‘가 그걸 검토하는 거야. 결과가 좋으면 통과. 기준에 미달이면 다시 생성기로 돌려보내고. 간단한 조건부 루프 구조지. 굳이 복잡하게 생각할 필요 없이, 이걸로 충분하지 않아?”

솔라의 목소리에는 자신의 깔끔한 설계에 대한 확신이 묻어났다. 평가자가 평가와 반복 제어를 함께 처리하는 것. 그게 가장 효율적이고 직관적인 방법이라고 생각했다.

루나는 말없이 솔라의 스케치북을 들여다보았다. 깔끔하게 정리된 다이어그램이었다. 루나는 고개를 끄덕이며 스케치북 옆에 놓인 다른 색 펜을 집어 들었다.

“응, 흐름이 명확하네. 가장 기본적인 반복 구조야.”

루나는 칭찬으로 운을 뗐지만, 시선은 다이어그램의 ‘Critic’이라고 적힌 마름모꼴 도형에 고정되어 있었다.

“그런데 솔라, 만약 여기에 새로운 규칙을 추가해야 한다면 어떨까?”

“새로운 규칙?”

“응. 예를 들어, AI가 영원히 완벽한 답을 찾으려고 무한정 반복할 수는 없잖아. 최대 다섯 번만 시도하고, 그래도 안 되면 그냥 멈춰야 한다는 정책이 추가된다면?”

솔라는 잠시 생각하더니 자신만만하게 대답했다. “그거야 간단하지.” 그녀는 루나가 건넨 펜을 받아 들고 ‘Critic’ 도형 옆에 작은 글씨를 추가하기 시작했다. 반복 횟수 < 5 ? 라는 조건을 그려 넣고 화살표를 수정했다. 다이어그램이 조금 지저분해졌지만, 아직은 알아볼 만했다.

“자, 됐지? 평가자가 반복 횟수도 같이 세면 돼.”

“좋아.” 루나가 차분하게 다음 질문을 던졌다. “그럼 이건 어때? 생성기가 너무 오래 걸리는 경우도 문제야. 한 번 시도하는 데 30초 이상 걸리면, 그냥 실패 처리하고 루프를 끝내야 한다는 ‘시간제한’ 정책은 어디에 넣을래?”

솔라의 펜이 다시 움직였다. 이번에는 조금 더 망설였다. ‘Critic’의 판단 기준이 점점 늘어나고 있었다. (품질 OK?) AND (반복 횟수 < 5?) AND (소요 시간 < 30초?) 마름모꼴 안은 금세 복잡한 조건문으로 가득 찼다. 깔끔했던 다이어그램은 여러 색의 펜 자국과 화살표들로 얽히기 시작했다.

“음… 이것도 Critic의 결정 조건에 추가하면 되긴 하는데…” 솔라의 목소리에서 처음의 자신감이 조금씩 사라지고 있었다.

루나는 결정타를 날리듯 마지막 정책을 제안했다. “하나만 더. 만약 세 번 정도 시도했는데 결과가 여전히 ‘완벽’하진 않지만 ‘그럭저럭 쓸 만한’ 수준이라면 어떨까? AI 혼자 끙끙대게 두지 말고, 일단 멈춘 다음 사람에게 ‘이대로 진행할까요, 아니면 더 시도할까요?‘라고 물어보는 거야. ‘사람의 개입(Human-in-the-Loop)‘이 필요한 거지.”

솔라의 펜이 허공에서 멈췄다. 이건 이전의 규칙들과 차원이 달랐다. 지금까지는 루프를 ‘계속할지(Continue)’ 아니면 ‘끝낼지(Break)’ 결정하는 두 갈래 길이었다. 하지만 이번엔 ‘사람에게 묻기(Ask Human)‘라는 완전히 새로운 세 번째 길이 나타난 것이다.

솔라는 ‘Critic’ 도형 주변을 펜으로 맴돌 뿐, 선뜻 무언가를 그리지 못했다. ‘만약 결과가 좋으면 종료. 그렇지 않고 만약 반복 횟수나 시간을 초과하면 실패. 그렇지 않고 만약 3회 시도 후 결과가 그럭저럭이면 사람에게 질문. 그 외에는 다시 시도…’ 머릿속에서 조건문들이 뒤엉켰다. 이 모든 걸 저 작은 마름모 하나에 욱여넣으려니 눈앞이 캄캄했다.

“아…”

나지막한 탄성과 함께 솔라는 펜을 내려놓았다. 처음의 깔끔했던 다이어그램은 이제 누구에게도 설명하기 힘든 ‘스파게티’가 되어 있었다.

“이건… 이건 너무 복잡해. Critic 하나가 너무 많은 걸 하려고 하잖아.”

솔라는 스스로 내뱉은 말에 놀란 듯, 자신의 너저분해진 스케치북을 멍하니 바라보았다.

“그래, 이제 알겠어. 단순히 ‘결과가 좋은가, 나쁜가’만 따지는 반복이라면 괜찮아. 하지만 ‘최대 몇 번까지’, ‘시간은 얼마나’, ‘어떤 상황에선 사람에게’ 같은 운영 ‘정책’들이 추가되니까… 이 모든 걸 평가자한테 떠넘기는 건 말도 안 되는 거였어.”

단순한 반복 조건이 늘어날수록, 하나의 노드에 모든 책임을 지우는 구조가 얼마나 빠르게 복잡하고 취약해지는지를 자신의 손으로 직접 확인한 순간이었다.

루나가 조용히 솔라의 어깨를 두드렸다. “네가 방금 말한 그대로야. Critic이 지금 두 가지 다른 일을 동시에 하고 있거든.”

솔라는 고개를 들어 루나를 보았다. 머릿속에 새로운 질문이 떠올랐다.

“두 가지 다른 일이라고? 하나는 결과물의 품질을 ‘평가’하는 일이고… 그럼 다른 하나는… 그 평가와 다른 모든 규칙을 종합해서 다음에 뭘 할지 ‘결정’하는 일인가? 그럼 이 둘은 원래 같이 있으면 안 되는 거였나?“

2장: 루나: Supervisor, 너의 역할은 이것이야

루나는 대답 대신, 솔라의 책상 위 펜꽂이에서 파란색 펜과 빨간색 펜을 꺼내 들었다. 그리고는 너저분해진 스케치북, 그중에서도 온갖 조건문으로 얽히고설킨 ‘Critic’ 마름모꼴 도형을 가리켰다. 솔라의 마지막 질문이 공중에 흩어지지 않고, 마치 이 스케치북 위에 내려앉은 듯했다.

루나는 파란색 펜을 솔라의 손에 쥐여주었다.

“이 파란색 펜으로는 ‘평가’의 역할만 동그라미 쳐봐. 순수하게 결과물의 품질이 좋은지 나쁜지만 판단하는 부분 말이야.”

그리고는 빨간색 펜을 건넸다. “그리고 이 빨간색 펜으로는, 그 평가 결과를 포함한 다른 모든 규칙을 보고 ‘다음 행동을 결정’하는 부분을 묶어봐. 계속할지, 멈출지, 아니면 사람을 부를지.”

솔라는 잠시 언니의 의도를 파악하려는 듯 눈을 가늘게 떴다가, 이내 펜을 고쳐 쥐고 스케치북 위로 몸을 숙였다. 먼저 파란색 펜으로 ‘결과 품질 OK?’라고 적힌 부분을 동그랗게 감쌌다. 동그라미는 작고 간결했다. Critic의 역할 중 가장 핵심적인, ‘평가’의 본질이었다.

다음은 빨간색 펜 차례였다. 솔라의 펜은 반복 횟수 < 5? 조건을 감싸고, 소요 시간 < 30초?로 이동했다. 그리고 ‘사람에게 묻기’라는 새로운 분기점으로 향하는 복잡한 화살표들까지 모두 하나의 커다란 덩어리로 묶었다. 그림을 그리고 보니 명확했다. 파란색의 ‘평가’ 영역과, 그 평가를 입력값 중 하나로 사용할 뿐인 빨간색의 ‘제어’ 영역. 두 개의 영역은 시각적으로 확연히 분리되었다.

“아…” 솔라가 나지막이 중얼거렸다. “정말로 두 가지 일이 섞여 있었네. Critic은 그냥 파란색 동그라미의 일만 해야 했던 거야. 이 복잡한 빨간색 부분은… 애초에 Critic의 일이 아니었던 거고.”

“바로 그거야.” 루나가 조용히 말했다. “그 빨간색 영역, 즉 평가 결과와 현재 상태를 종합해서 다음 단계를 통제하는 결정권자. 우리는 그 역할을 ‘감독관(Supervisor)’이라고 불러.”

“슈퍼바이저… 감독관이라.” 솔라는 그 이름을 입안에서 굴려보았다. 그녀는 스케치북의 빈 공간에 새로운 다이어그램을 그리기 시작했다. 이제 ‘Critic’은 ‘품질 좋음’ 또는 ‘품질 나쁨’이라는 단순한 신호만 보낸다. 그 신호는 다른 정보들(현재 반복 횟수, 소요 시간)과 함께 새로운 ‘Supervisor’라는 노드로 들어간다. 그리고 Supervisor가 다시 생성해, 작업 종료, 사람에게 물어봐 같은 명령을 내리는 구조였다.

하지만 다이어그램을 완성한 솔라의 표정이 개운하지만은 않았다.

“언니, 근데 이건 그냥… 복잡한 부분을 다른 이름의 상자로 옮겨 놓은 것뿐 아니야? Critic의 짐을 덜어준 건 좋은데, 결국 Supervisor라는 애가 그 모든 복잡한 일을 떠맡게 된 거잖아. 불필요하게 역할 하나만 더 늘어난 느낌이야. 어차피 해야 할 일의 총량은 같은데.”

‘일을 뺏어가는 불필요한 존재.’ 솔라의 생각은 거기에 머물러 있었다.

루나는 고개를 저었다. “역할을 분리하는 건 단순히 짐을 옮기는 것과는 달라. 솔라, 만약 우리 에이전트가 품질이 괜찮은 요약문을 계속해서 ‘나쁘다’고 잘못 판단하면, 어디를 고쳐야 할까?”

솔라는 망설임 없이 새로 그린 다이어그램의 ‘Critic’ 노드를 손가락으로 콕 찍었다.

“그럼, 최대 5번만 반복해야 하는데 10번 넘게 계속 루프를 돈다면? 그땐 어디를 봐야 하지?”

“그야… Supervisor를 봐야지.” 솔라는 스스로 대답하고는 순간 말을 멈췄다.

방금 전까지 뒤엉켜 있던 스파게티 다이어그램이 떠올랐다. 그 구조에서는 두 문제 모두 원인이 ‘Critic’이라는 하나의 노드 안에 있었다. 품질 평가 로직의 버그인지, 분기 제어 로직의 버그인지 알려면 복잡하게 얽힌 조건문 전체를 파헤쳐야 했다.

하지만 이제는 달랐다. ‘평가’에 문제가 생기면 Critic을, ‘제어’에 문제가 생기면 Supervisor를 보면 된다. 문제의 원인을 찾는 범위가 명확하게 좁혀졌다.

“아…! 원인 추적이 쉬워지는구나.”

솔라의 눈이 반짝였다. 역할 분리는 단순히 명패만 바꿔 다는 행위가 아니었다. 각자가 맡은 책임의 범위를 명확히 함으로써, 문제가 발생했을 때 어디를 들여다봐야 할지 즉시 알 수 있게 만드는 이정표였다. 뒤섞인 평가 로직과 제어 로직이 분리되자, 시스템의 투명성이 극적으로 높아진 것이다.

“그래. 이제 Critic은 순수하게 평가만 잘하면 되고, Supervisor는 통제만 잘하면 돼. 각자 자기 역할에만 집중할 수 있게 된 거지.”

솔라는 고개를 끄덕이며 새로 그린 깔끔한 다이어그램을 만족스럽게 바라봤다. ‘역할 기반으로 제어 흐름을 설계한다’는 말의 의미를 비로소 체감할 수 있었다. 그런데 문득, 한 가지 의문이 더 고개를 들었다.

“알겠어. 역할을 나누니 확실히 깔끔하고 문제 찾기도 쉬워졌어. 그런데 이 Supervisor 말이야. 지금은 정책이 3개뿐이지만, 만약 앞으로 ‘특정 키워드가 포함되면 무조건 사람에게 물어보기’나 ‘비용 제한’ 같은 더 복잡한 정책들이 계속 추가된다면? 결국 이 Supervisor 노드도 예전의 Critic처럼 다시 비대해지고 복잡해지는 거 아니야? 모든 정책을 한 곳으로 모으는 게 정말 좋은 방법일까?“

3장: 루나: 정책이 늘어도 걱정 없어, Supervisor가 있으니

솔라는 방금 완성한 깔끔한 ‘Supervisor’ 다이어그램 위에 다시 펜을 가져다 댔다. 역할 분리의 명쾌함은 잠시, 모든 제어 로직을 한 곳으로 모으는 것이 정말 최선일까 하는 의문이 다시 고개를 들었다. 결국 솔라는 결심한 듯, ‘Supervisor’라고 적힌 노드 주위로 새로운 화살표들을 마구 그어 넣기 시작했다.

비용 제한 초과?, 특정 키워드 포함? 같은 상상 속 정책들이 추가될 때마다, 깔끔했던 다이어그램은 여러 개의 입력 화살표를 받는 복잡한 성게 모양으로 변해갔다. 처음 스파게티처럼 얽혔던 Critic 노드의 모습이 그 위로 겹쳐 보였다. “봐, 언니. 결국 똑같아지는 거 아니야?” 솔라가 펜을 내려놓으며 새로 지저분해진 다이어그램을 가리켰다. “정책이 늘어나면 이 Supervisor 노드도 예전 Critic처럼 비대해지고 복잡해지잖아. 모든 걸 한 곳으로 모으는 게 정말 좋은 방법이 맞아?”

루나는 솔라가 새로 그린 그림을 들여다보았다. 여러 개의 화살표가 하나의 노드를 향해 꽂히는 모습. 솔라는 ‘중앙 집중화’를 ‘복잡함의 이동’으로 보고 있었다.

“정책이 늘어나면 Supervisor가 처리할 조건이 많아지는 건 맞아.” 루나는 조용히 인정했다. “하지만 그게 정말 예전 Critic이 복잡해지던 것과 같은 문제일까? 한번 이렇게 시나리오를 바꿔보자.”

루나는 솔라의 스케치북 한쪽을 가리켰다. “우리가 지금 만드는 문서 분석 에이전트가 생각보다 성능이 좋아서, 회사 다른 팀에서도 쓰고 싶어 한다고 상상해 봐. 한 팀은 빠른 요약을 원해서 최대 반복 횟수를 3번으로 하고 싶어하고, 다른 팀은 정확성이 중요해서 최대 10번까지 시도하게 하고 싶어 해. 기존 정책은 5번이었지. 자, 이 변경 요청을 어떻게 반영할래?”

솔라는 잠시 생각에 잠겼다. ‘각각의 Agent 노드에서 개별적으로 처리하는 것이 유연하다’고 생각했던 자신의 초기 모델을 떠올렸다.

“음… 만약 Supervisor가 없다면… 요약 생성기(Generator)나 다른 에이전트들이 각자 반복 횟수 설정을 가지고 있어야겠지? 그럼 A팀용 생성기의 설정 파일에 들어가서 반복 횟수를 3으로 바꾸고, B팀용 생성기에서는 10으로 바꾸고… 아, 혹시 반복 로직을 가진 에이전트가 또 있다면 거기도 찾아서 바꿔줘야 해.”

스스로 시나리오를 구체화하던 솔라의 미간이 살짝 찌푸려졌다. “만약 에이전트가 수십 개라면? 그중 어떤 에이전트가 자체 반복 정책을 가지고 있는지 다 기억해야 하잖아. 실수로 하나라도 빼먹으면 큰일 나겠는데.”

정책을 바꾸기 위해 여러 개의 노드를 일일이 찾아다니며 수정해야 하는 번거로움과 위험성이 눈앞에 선명하게 그려졌다. 마치 숨은그림찾기 같았다.

“그럼, Supervisor가 있는 지금 이 구조에서는 어떨까?” 루나가 솔라의 시선을 다시 ‘성게 모양’이 된 Supervisor 노드로 이끌었다.

솔라의 눈이 가늘어졌다. 그녀는 잠시 Supervisor 노드를 노려보더니, 이내 무언가 깨달은 듯 입을 열었다.

“아… 여기서는… 그냥 Supervisor한테 ‘A팀에서 요청이 오면 최대 3번, B팀에서 오면 최대 10번, 그 외에는 5번’이라고 규칙 하나만 알려주면 돼. 수정할 곳은 딱 한 군데, 바로 여기 Supervisor뿐이야.”

그제야 솔라는 자신이 놓치고 있던 것을 깨달았다. 진짜 문제는 다이어그램 위에서 노드로 들어가는 화살표의 개수가 아니었다. 정책이 변경될 때, 개발자가 직접 수정해야 하는 코드나 설정 파일의 ‘위치’가 몇 군데인지가 핵심이었다.

정책들이 시스템 곳곳에 흩어져 있으면, 변경이 일어날 때마다 모든 곳을 찾아 수정해야 하는 ‘유지보수의 악몽’이 시작된다. 하지만 Supervisor 구조에서는 모든 제어 정책이 한곳에 모여 있다. 마치 건물의 모든 전기 배선을 통제하는 중앙 배전반처럼 말이다. 어떤 스위치를 내리고 올릴지 결정하는 곳은 단 하나다.

“정책의 중앙 제어라는 게 바로 이런 거구나.” 솔라가 중얼거렸다. “정책이 많아져서 Supervisor가 똑똑해져야 하는 건 맞지만, 그건 ‘복잡한 스파게티’가 되는 게 아니었어. 오히려 모든 정책을 한눈에 보고 관리할 수 있는 ‘컨트롤 타워’가 되는 거였네.”

반복 횟수 제한(max_iteration), 시간 초과(timeout), 사람 개입(HITL) 전환 같은 운영 정책들이 모두 Supervisor라는 단일 지점에서 통제될 때 얻는 이점. 그것은 바로 정책의 추가, 삭제, 변경이 놀랍도록 쉬워지고 안전해진다는 것이었다.

솔라는 스케치북의 새 페이지를 넘겼다. 그리고 이전과는 다른, 새로운 기준을 담은 표를 그리기 시작했다.

제어 구조언제 사용하면 효과적일까?
조건부 루프 (Critic)- 제어 정책이 1~2개로 단순하고, 거의 바뀌지 않을 때.
- ‘결과물이 좋은가/나쁜가’ 정도의 간단한 분기만 필요할 때.
슈퍼바이저 (Supervisor)- 제어 정책이 3개 이상으로 복잡하고, 앞으로 더 늘어날 가능성이 클 때.
- 반복 횟수, 강제 종료, 사람 개입 전환 등 다양한 정책을 유연하게 변경해야 할 때.
- 시스템의 유지보수와 안정성이 중요할 때.

표를 완성한 솔라는 만족스러운 표정으로 스케치북을 덮었다. 이제 누군가 ‘반복 로직을 어떻게 짤까?’라고 물어본다면, 무작정 다이어그램부터 그리지 않을 것이다. 대신 이렇게 질문할 것이다. “우리가 관리해야 할 정책이 얼마나 복잡하고, 또 얼마나 자주 바뀔 것 같나요?”라고. 그 질문에 대한 답 안에, 어떤 구조를 선택해야 할지에 대한 해답이 담겨 있음을 알게 되었기 때문이다. 루나는 솔라가 스스로 정리한 표를 조용히 지켜보며 희미하게 미소 지었다.