클로드 API 스트리밍 응답 구현하기: 챗봇처럼 글자를 흘려 보여주기

클로드 API 스트리밍 응답 구현하기: 챗봇처럼 글자를 흘려 보여주기 대표 이미지

API로 챗봇을 만들어 처음 테스트했을 때, 질문을 보내고 10초 동안 아무 반응이 없다가 답이 한꺼번에 나타났습니다. 답은 좋았지만 사용자는 그 10초 동안 "고장 났나?" 생각했을 겁니다. claude.ai처럼 글자가 흘러나오게 하려면 스트리밍(Streaming)을 써야 합니다.

스트리밍이 필요한 이유

일반 응답과 스트리밍 응답 비교

구분 일반 응답 스트리밍
첫 글자가 보이는 시점 답변 완성 후 생성 시작 직후
체감 속도 느림 빠름
총 소요 시간 같음 같음
비용 같음 같음
긴 출력의 시간 초과 위험 있음 낮음

총 시간은 같지만 사용자가 기다린다고 느끼는 시간이 크게 줄어듭니다. 그리고 아주 긴 출력을 요청할 때 HTTP 요청 시간 초과를 피하는 데도 스트리밍이 권장됩니다.

파이썬 기본 예제

파이썬 SDK의 messages.stream()을 쓰면 간단합니다.

import anthropic

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-sonnet-5",
    max_tokens=2048,
    messages=[{"role": "user", "content": "재택근무 생산성을 높이는 습관 5가지를 설명해 줘."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

print()

text_stream은 생성되는 텍스트 조각을 차례로 내보냅니다. flush=True로 바로바로 출력하면 터미널에서 글자가 흘러나오는 것을 볼 수 있습니다.

최종 메시지와 사용량 받기

스트리밍이 끝난 뒤 완성된 메시지 전체와 토큰 사용량이 필요할 때가 많습니다.

with client.messages.stream(
    model="claude-sonnet-5",
    max_tokens=2048,
    messages=messages,
) as stream:
    for text in stream.text_stream:
        send_to_client(text)          # 화면으로 조각 전달
    final = stream.get_final_message()  # 완성된 메시지

print(final.stop_reason)
print(final.usage.input_tokens, final.usage.output_tokens)

get_final_message()로 받은 메시지는 대화 기록에 저장하거나 비용을 집계하는 데 씁니다. 화면에 조각을 보여 주는 일과 기록 저장을 이렇게 나누면 깔끔합니다.

웹 서비스로 전달하는 구조

스트리밍 웹 서비스 구조: 브라우저, 서버, Claude API

실제 챗봇에서는 서버가 클로드로부터 받은 조각을 다시 브라우저로 흘려 보내야 합니다.

브라우저 ⇄ 내 서버 ⇄ Claude API
         (SSE 등)     (stream)
  • 서버 → 브라우저: Server-Sent Events(SSE)나 웹소켓으로 조각을 전달합니다.
  • API 키는 서버에만: 브라우저에서 직접 Claude API를 호출하면 키가 노출됩니다. 반드시 서버를 거치세요.

이벤트 단위로 다루기

텍스트 외에 툴 호출이나 생각(thinking) 블록 등을 함께 다루는 고급 기능에서는 텍스트 조각 대신 이벤트 단위로 처리합니다. 메시지 시작, 콘텐츠 블록 시작·변경·종료, 메시지 종료 같은 이벤트가 순서대로 옵니다. 처음에는 text_stream으로 충분하고, 툴 사용 같은 기능을 붙일 때 이벤트 처리를 공부하면 됩니다.

주의할 점

  1. 중간 끊김 처리: 네트워크 오류로 스트림이 끊기면 화면에 상태를 알리고 재시도 버튼을 제공하세요.
  2. stop_reason 확인: max_tokens로 끊긴 경우 답이 중간에 잘린 것이니, 사용자에게 알리거나 이어서 생성하게 합니다.
  3. 화면 렌더링 부하: 조각마다 화면 전체를 다시 그리면 느려집니다. 일정 간격으로 묶어 갱신하세요.
  4. 마크다운 렌더링: 표나 코드 블록은 완성되기 전까지 깨져 보일 수 있습니다. 렌더링 라이브러리가 부분 마크다운을 처리하는지 확인하세요.

💬 체감 속도가 사용자 경험입니다

스트리밍을 적용하기 전과 후, 같은 챗봇에 대한 테스트 사용자들의 반응이 확연히 달랐습니다. 응답 시간은 똑같은데 "빨라졌다"는 말을 들었습니다. 사용자 경험에서는 실제 속도만큼 체감 속도가 중요하다는 걸 배웠습니다. 사용자가 화면 앞에서 기다리는 서비스라면, 스트리밍은 선택이 아니라 기본으로 생각하세요.

이 글의 요점

  1. 스트리밍은 비용 변화 없이 체감 속도를 높이고, 긴 출력의 시간 초과 위험을 줄입니다.
  2. 파이썬 SDK의 messages.stream()과 text_stream으로 간단히 구현합니다.
  3. get_final_message()로 완성 메시지와 사용량을 받고, 끊김·잘림 처리를 준비하세요.

더 알아보기

🤔 자주 묻는 질문 (FAQ)

Q. 스트리밍을 쓰면 비용이 달라지나요?

아닙니다. 스트리밍은 응답을 전달하는 방식만 다를 뿐 토큰 사용량과 요금은 같습니다.

Q. 스트리밍은 꼭 써야 하나요?

사용자가 화면에서 답을 기다리는 서비스라면 체감 속도 때문에 권장됩니다. 또한 출력이 아주 긴 요청은 요청 시간 초과를 피하기 위해 스트리밍을 쓰는 것이 안전합니다.

Q. 스트리밍 중 오류가 나면 어떻게 되나요?

네트워크 문제 등으로 중간에 끊길 수 있으므로, 화면에 오류 상태를 보여 주고 다시 시도할 수 있게 처리해야 합니다. 이미 받은 부분을 어떻게 처리할지도 미리 정해 두세요.
#스트리밍 #Streaming #ClaudeAPI #챗봇개발 #파이썬