실무 Multi-Agent 오케스트레이션 24장 · 서비스 통합과 실행 8 / 9 ← 이전목차다음 → TechLead Cro

24장. 서비스 통합과 실행

정리와 체크리스트

24장에서 배운 것

  • 프론트엔드와 백엔드 — 화면(브라우저)과 처리하는 프로그램(서버)은 따로 돌고 HTTP로 대화합니다. 화면은 채팅 화면과 상담원 화면 둘입니다.
  • FastAPI와 Uvicorn — 함수에 @app.get / @app.post를 붙여 주소로 만들고, Uvicorn이 서버를 띄웁니다.
  • 엔드포인트 — 주소 하나와 함수 하나의 짝. 우리 서버에는 고객 쪽 셋(화면, 점검, 채팅)과 상담원 쪽 다섯(/admin, /api/actions, /api/approvals, POST /api/approvals/{action_id}, /api/tickets)이 있습니다.
  • 웹의 승인 게이트 — 23장의 승인 게이트가 상담원 화면의 승인 버튼이 됩니다. 버튼은 같은 decide()를 부르고, 채팅 쪽과 상담원 쪽은 처리 기록 파일(actions.json)로 이어집니다.
  • 입력 검증 — 밖에서 들어오는 요청은 Pydantic 모델로 문 앞에서 검사합니다. 틀리면 422로 돌려보냅니다.
  • session_id — 화면이 만든 대화 이름표. 서버는 이름표별로 이력을 보관합니다. 새로고침하면 새 대화입니다.
  • SSE — data: … 한 줄이 이벤트 하나. delegate · answer · done 세 종류로 과정을 흘려보냅니다.
  • 최종 검수 — 표준 질문 12개로 위임, 처리 결과, 검증 포인트를 맞춰 봅니다. 처리 기록을 비우고 서버를 다시 켠 뒤 시작합니다.

한눈에 보는 핵심

# haru-market 폴더 맨 위에서
$ python -m uvicorn app.main:app --reload --port 8000
# 채팅 화면:   http://localhost:8000
# 상담원 화면: http://localhost:8000/admin      끄기: Ctrl + C
@app.post("/api/chat")
def chat(req: ChatRequest):                               # 입력은 문 앞에서 검사
    history = histories.get(req.session_id, [])           # 이 대화의 이력
    def generate():
        ...
        yield event({"type": "delegate", ...})            # 위임이 보일 때마다
        yield event({"type": "answer", "text": ...})      # 최종 답변
        histories[req.session_id] = new_messages          # 이력 갱신
        yield event({"type": "done"})
    return StreamingResponse(generate(), media_type="text/event-stream", ...)


@app.post("/api/approvals/{action_id}")
def approve(action_id: str, body: Decision):              # 상담원 화면의 승인·반려 버튼
    return decide(action_id, approve=body.approve, by="상담원")   # 23장과 같은 함수
층 파일 하는 일
화면 app/frontend/index.html 고객: 문의를 보내고 이벤트를 받아 그린다
화면 app/frontend/admin.html 상담원: 승인 대기를 승인·반려하고, 처리 내역과 넘겨받은 문의를 본다
서버 app/main.py 주소, 이력 보관, 이벤트
지휘 haru_supervisor.py 위임과 종합
전문가 haru_agents.py 주문조회, 정책안내, 요청처리
도구 haru_tools.py, haru_actions.py 조회(본인 확인, 마스킹)와 처리(코드의 판정, 처리 기록)

체크리스트

  • [ ] 프론트엔드와 백엔드가 무엇이고 어떻게 대화하는지 설명할 수 있다.
  • [ ] main.py를 어느 폴더에 만들고, 서버를 어느 위치에서 어떤 명령으로 띄우는지 안다.
  • [ ] app.main:app의 세 조각이 각각 무엇을 가리키는지 말할 수 있다.
  • [ ] 우리 서버의 엔드포인트 여덟 개를 고객 쪽과 상담원 쪽으로 나눠 쓰임을 말할 수 있다.
  • [ ] 채팅으로 요청한 주문 취소가 상담원 화면에 나타나는 까닭을 처리 기록 파일로 설명할 수 있다.
  • [ ] 상담원 화면의 승인 버튼이 23장의 무엇에 해당하는지, 끝에서 어떤 함수가 불리는지 말할 수 있다.
  • [ ] 모양이 틀린 요청이 왔을 때 어떤 일이 일어나고, 왜 비용이 나가지 않는지 설명할 수 있다.
  • [ ] 새로고침하면 "그거"를 못 알아듣는 이유를 session_id로 설명할 수 있다.
  • [ ] CustomerSession과 session_id의 차이를 말할 수 있다.
  • [ ] 스트리밍이 걸리는 시간을 줄이지 않는데도 필요한 이유를 설명할 수 있다.
  • [ ] 이벤트 세 종류와, 화면의 진행 표시가 어느 이벤트에서 오는지 안다.
  • [ ] 서버를 끄면 대화는 사라지고 처리 기록은 남는 이유를 설명할 수 있다.
  • [ ] 표준 질문 12개를 직접 넣어 보고, 질문마다 위임·처리 결과·검증 포인트를 확인했다.
  • [ ] Q10에서 상담원 화면의 승인 버튼을 눌러 승인대기가 승인완료로 바뀌는 것을 확인했다.
  • [ ] 프롬프트나 코드를 고친 뒤 열두 개를 전부 다시 돌려야 하는 이유를 설명할 수 있다.
  • [ ] 아키텍처의 네 구성요소가 각각 어느 장에서 채워졌는지 말할 수 있다.

과정을 마치며 — 전체 체크리스트

스물네 장을 마친 지금, 아래를 말로 설명할 수 있는지 확인해 보세요.

  • [ ] LLM만으로는 왜 "제 주문 어디 있어요?"에 답할 수 없는가. (도구)
  • [ ] 모델이 도구를 "부른다"는 말이 실제로는 무슨 뜻인가. (5장)
  • [ ] 정책을 모델의 짐작이 아니라 문서에서 가져오게 하려면 무엇이 필요한가. (지식)
  • [ ] LLM은 앞 대화를 기억하지 않는데 어떻게 대화가 이어지는가. (기억)
  • [ ] 에이전트 하나로 충분한 일과 여럿으로 나눠야 하는 일은 어떻게 가르는가. (오케스트레이션)
  • [ ] 어떤 일을 AI에게 맡기고, 어떤 일을 코드가 하고, 어떤 일을 사람이 해야 하는가.
  • [ ] "잘 만들었다"를 무엇으로 확인하는가.

한 줄 핵심

고르고 쓰는 일은 모델에게, 실행하고 보증하는 일은 코드에게, 되돌릴 수 없는 결정은 사람에게. 그리고 바꿀 때마다 같은 질문 열두 개로 다시 확인합니다.

← 이전 절돌아보기 — 아키텍처의 네 칸은 어디서 채워졌나다음 절 →실습문제와 해답
오명운 · macro@prag-ai.com