로드 중

스트리밍 도구 호출: 멈춘 스피너는 이제 그만

강의 48분
로드 중

스트리밍 도구 호출: 멈춘 스피너는 이제 그만

요약대본

스트리밍되는 도구 호출은 도구의 이름이 먼저 도착하고 입력이 조각 단위로 도착하므로, 화면에 무슨 일이 일어나고 있는지 보여줄 수 있습니다. 이 영상은 가상의 엔지니어링 컨설팅 회사인 Meridian의 화면 두 가지 버전을 나란히 보여줍니다. 하나는 스트리밍이 없고 다른 하나는 스트리밍이 있습니다. 데모는 시뮬레이션이며 3분의 1 속도로 재생됩니다.

이 영상은 2026년 9월에 녹화되었으며, 코드에서는 Claude Sonnet 5(claude-sonnet-5)를 사용합니다. 최신 모델에서는 결과가 다를 수 있습니다.

사용자가 8초 동안 스피너를 바라본다고 가정해 보겠습니다. 이는 도구 루프가 각 요청을 보내고, 기다렸다가, 완료된 응답을 받기 때문에 일어나는 일입니다.

그 시간 동안 Claude는 도구를 선택하고 입력을 작성하며, 여러분의 코드는 도구를 실행하고, Claude는 답변을 작성합니다. 여러분의 코드는 각 응답이 완료된 후에야 이를 확인하기 때문에, Claude가 작성하는 동안 UI에는 보여줄 것이 없습니다.

Meridian은 오늘날 이러한 문제를 겪고 있습니다. Meridian의 지원 에이전트는 Python으로 작성되었으며 직원들의 프로젝트 관련 질문에 답변합니다. 한 직원이 "펌프장 작업은 어떻게 진행되고 있나요?"라고 물으면, 답변이 올 때까지 화면에는 "생각 중..."이라고 표시됩니다.

스트리밍은 해당 직원이 보게 되는 내용을 바꿉니다. 스트리밍을 사용하면, 응답이 완료되기 전에 코드가 응답을 조각 단위로 받게 됩니다. 그래서 Meridian의 화면은 Claude가 도구를 선택하자마자 "프로젝트 조회 중..."이라고 표시할 수 있습니다.

스트리밍 도구 호출의 모습

도구 루프가 요청을 보내는 부분에서, client.messages.create(...)를 client.messages.stream(...)로 바꾸세요. 그러면 응답은 일련의 서버 전송 이벤트, 즉 각각 type을 가진 작은 JSON 메시지들로 도착합니다.

응답은 콘텐츠 블록(줄여서 블록)으로 구성되며, Claude의 텍스트가 이어지는 구간마다 하나의 블록이, 각 도구 호출마다 하나의 블록이 있습니다. 도구 호출 블록의 type은 tool_use입니다. 현재 모델은 thinking 블록을 추가할 수도 있는데, 이 레슨의 코드에서는 이를 무시합니다.

전화로 친구가 전화번호를 불러주는 상황을 떠올려 보세요. 먼저 친구는 그것이 누구의 번호인지 말해줍니다. "이게 배관공 번호야." 그런 다음 몇 자리씩 숫자를 읽어주는데, 원하는 곳에서 멈추기도 합니다. 마지막으로 "이게 다야"라고 말합니다.

도구 호출 블록도 그 전화번호와 같은 방식으로 도착합니다. 하나의 이벤트가 블록을 열고, 하나 이상의 이벤트가 내용을 채우며, 하나의 이벤트가 블록을 닫습니다. 다음은 Meridian의 도구 호출 이벤트들입니다.

text
{"type": "content_block_start", "index": 0,
 "content_block": {"type": "tool_use", "id": "toolu_01",
                   "name": "lookup_project_status", "input": {}}}
{"type": "content_block_delta", "index": 0,
 "delta": {"type": "input_json_delta", "partial_json": "{\"project_"}}
{"type": "content_block_delta", "index": 0,
 "delta": {"type": "input_json_delta", "partial_json": "id\": \"MEG-2"}}
{"type": "content_block_delta", "index": 0,
 "delta": {"type": "input_json_delta", "partial_json": "026-0142\"}"}}
{"type": "content_block_stop", "index": 0}

블록이 열리자마자 선택된 도구 표시하기

도구의 이름은 블록의 첫 번째 이벤트인 content_block_start에 들어 있습니다. 이 이벤트가 도착하면, 코드는 상태 표시줄, 즉 사용자가 기다리는 동안 UI에 표시되는 한 줄짜리 텍스트를 업데이트할 수 있습니다.

Meridian은 각 도구의 이름을 사용자에게 보여줄 문구로 매핑하는 작은 딕셔너리 STATUS를 유지하는데, 이에 따라 lookup_project_status는 화면에서 "프로젝트 조회 중..."이 됩니다.

스트리밍 요청 구성하기

스트림이 끝나면 stream.get_final_message()를 호출하여 완료된 응답, 즉 client.messages.create(...)가 반환하는 것과 같은 종류의 객체를 받으세요. 그러면 도구 루프의 나머지 부분은 그대로 유지됩니다.

다음은 Meridian의 스트리밍 요청입니다. on_status는 문자열을 상태 표시줄로 보여주기 위해 여러분이 작성하는 함수입니다.

로드 중

핵심 요약

  • 스트리밍 도구 호출은 도구의 이름이 먼저 도착하고, 그다음 입력이 조각 단위로 도착합니다.
  • content_block_start가 도착하자마자, 사용자가 이해할 수 있는 말로 선택된 도구를 보여주세요.
  • stream.get_final_message()는 완료된 응답을 반환하므로, 도구 루프의 나머지 부분은 바뀌지 않습니다.