본문 바로가기
카테고리 없음

응답 시간이 같아도 "빠르다"는 느낌이 다른 이유 - TTFT, SSE, UX체감

by BOOST YOUR INFORMATION 2026. 5. 23.

LLM 스트리밍 API (TTFT, SSE, UX체감) 참조 이미지
LLM 스트리밍 API

 

응답 생성 시간이 똑같아도 "빠르다"는 느낌이 완전히 달라질 수 있다. 고객 응대 챗봇에 스트리밍을 처음 도입했을 때, 나도 이 사실을 수치로 직접 확인하고 나서야 비로소 믿게 됐다. 그리고 그 이후로 스트리밍에 대한 생각이 꽤 많이 바뀌었다.

TTFT가 UX를 바꾸는 이유

챗봇이 응답을 내놓기까지 4~6초를 기다리는 경험은 생각보다 불쾌하다. 비스트리밍 방식으로 챗봇을 운영하던 시절, 내부 사용자 피드백에서 "너무 느리다"는 불만이 반복적으로 올라왔다. 실제 응답 품질에는 문제가 없었는데도 말이다.

핵심은 TTFT(Time To First Token)다. TTFT란 사용자가 질문을 보낸 뒤 모델이 첫 번째 토큰, 즉 첫 글자를 화면에 내보내기까지 걸리는 시간을 의미한다. 전체 응답이 완성될 때까지 기다렸다가 한꺼번에 보여주는 방식과 달리, 스트리밍은 이 TTFT를 최소화해서 사용자가 즉각 무언가를 보고 있다는 느낌을 받게 만든다.

UX 연구 분야에서 오래전부터 확립된 기준이 있다. 1초 이내 응답은 사용자가 "즉각적"으로 느끼고, 10초를 넘어가면 집중력 자체가 끊긴다는 것이다. 스트리밍은 전체 응답 완성 시간을 줄여주지는 않지만, 첫 반응이 1초 안에 화면에 찍히도록 만들어 사용자의 체감 대기 시간을 근본적으로 바꿔놓는다.

내가 직접 경험한 수치가 이를 잘 보여준다. 스트리밍 전환 후 응답 생성 시간은 동일했지만, "빠르다"는 인식이 눈에 띄게 올라갔다. 같은 서버, 같은 모델, 같은 프롬프트였다. 달라진 건 오직 응답을 언제 보여주느냐, 그 하나였다.

한 가지 비판을 덧붙이고 싶다. TTFT 최적화는 분명 중요하지만, 이게 진짜 느린 서비스를 가리는 마취제로 쓰이는 경우도 있다. "첫 글자가 빨리 나오니까 빠른 것 같다"는 착시 효과에 기대어 근본적인 응답 품질이나 서버 성능 개선을 미루는 함정에 빠질 수 있다. 스트리밍은 UX 개선 도구이지, 성능 문제를 해결하는 수단이 아니다. 나도 초기에 "스트리밍 붙였으니까 됐다"는 안도감에 실제 서버 레이턴시 개선을 미룬 적이 있었다. 나중에 보니 서버 처리 시간 자체가 꽤 컸고, 스트리밍은 그걸 숨겨주고 있었을 뿐이었다.

SSE 스트림 처리에서 배운 것들

스트리밍 구현의 기술적 뼈대는 SSE(Server-Sent Events)다. SSE란 서버가 클라이언트에게 단방향으로 데이터를 지속적으로 밀어 보내는 HTTP 기반 프로토콜로, 웹소켓처럼 양방향 통신이 필요하지 않은 상황에서 훨씬 가볍게 쓸 수 있는 방식이다. Anthropic API도 이 SSE 방식으로 스트림을 제공한다.

직접 Anthropic API의 SSE 스트림을 붙여보면서 몇 가지를 확실히 배웠다.

먼저 재연결 로직이다. 스트림 도중 연결이 끊기는 경우는 실제로 발생한다. 클라이언트가 자동으로 재연결을 시도하는 로직이 없으면 사용자 화면이 중간에 멈춰버린다. 이 부분을 처음에 간과했다가 모바일 환경에서 특히 문제가 발생했다. 와이파이와 LTE를 전환하는 순간 연결이 끊기는데, 재연결 로직이 없으면 사용자 입장에서는 그냥 응답이 멈춘 것처럼 보인다. 생각보다 이 케이스가 자주 발생한다는 걸 나중에야 알았다.

다음은 마크다운 렌더링 타이밍 문제다. 토큰이 하나씩 쌓이는 과정에서 마크다운 파서가 미완성 문법을 만나면 화면이 깨진다. 특히 코드 블록이 절반만 도착한 상태에서 렌더러를 돌리면 레이아웃이 무너지는 상황이 생긴다. 완성된 코드 블록이 닫히는 시점을 감지해서 그때 렌더링하는 버퍼링 처리가 별도로 필요하다. 이 문제는 원인 파악에만 한참 걸렸다. 코드 블록 안에 내용이 스트리밍되는 동안 ``` 기호가 닫히지 않은 상태여서, 파서가 이후 텍스트 전체를 코드로 인식하고 레이아웃 전체를 날려버리는 식이었다.

마지막으로 모바일 환경 고려다. 잦은 소켓 연결과 해제는 배터리 소모와 네트워크 비용을 높인다. 모바일 트래픽이 많은 서비스라면 이 부분을 사전에 따져봐야 한다. 나는 이 비용을 처음에 전혀 계산하지 않았는데, 모바일 사용자가 늘어나면서 생각보다 눈에 띄게 영향을 미쳤다. 스트리밍 자체가 연결을 오래 유지하는 구조이기 때문에, 신호가 불안정한 환경에서는 그만큼 재연결 비용이 커진다.

솔직히 이 부분은 예상 밖이었다. 스트리밍 자체는 API 파라미터 하나 바꾸면 되는 일이지만, 클라이언트 사이드에서 토큰 단위로 화면을 업데이트하면서 동시에 마크다운을 안정적으로 렌더링하는 건 꽤 손이 가는 작업이었다. "스트리밍 도입"이라는 항목이 태스크 보드에서 작아 보이는 것과 실제 구현 공수 사이의 갭이 크다는 점을 팀에 미리 공유해두는 게 좋다.

스트리밍이 항상 정답은 아닌 이유

스트리밍은 비용 구조를 직접 바꾸지는 않는다. 같은 프롬프트와 같은 응답이라면 스트리밍 여부와 무관하게 청구되는 토큰 수는 동일하다. 다만 실질적인 절감 효과가 하나 있었다. 사용자가 스트리밍 도중 원하는 답변을 발견하고 생성을 중단할 수 있게 되면서, 실제 운용 과정에서 불필요하게 완성되는 응답이 줄어들었다. 사용자가 응답 중간에 이미 원하는 내용을 확인하고 생성을 멈추는 패턴이 꽤 빈번하게 나타났다. 특히 긴 답변이 필요한 질문보다 짧은 확인성 질문이 많은 서비스라면 이 효과가 더 두드러진다.

그렇다고 스트리밍이 모든 상황에서 최선이라는 생각에는 동의하지 않는다. 백엔드 파이프라인에서 정밀한 JSON 파싱이나 구조화된 데이터를 받아야 할 때는 스트리밍이 오히려 처리 복잡도를 높인다. 스트리밍 중에는 응답 전체가 완성되기 전까지 구조가 확정되지 않기 때문이다. 내가 실제로 이 실수를 했다. 분류 파이프라인에 스트리밍을 붙였다가, 파서가 불완전한 JSON을 받고 에러를 뱉는 상황이 반복됐다. 결국 그 파이프라인은 비스트리밍으로 돌아갔다.

이런 경우에는 비스트리밍 방식, 즉 응답이 완성된 뒤 전체를 한 번에 받는 배치 방식이 더 안정적이다. 배치 방식이란 API 응답이 완전히 생성된 이후에야 클라이언트에 전달하는 방식으로, 파싱 정확도가 중요한 자동화 파이프라인에서 적합하다.

"스트리밍이 더 좋다"는 인식이 생기면 모든 케이스에 무조건 적용하려는 경향이 생기는데, 사용자 인터페이스에는 스트리밍, 데이터 처리 파이프라인에는 비스트리밍, 이렇게 목적에 따라 명확히 나눠서 설계하는 것이 훨씬 합리적이다. 나는 이 구분을 처음부터 명확히 하지 않아서 나중에 파이프라인 일부를 다시 뜯어고쳐야 했다.

결국 스트리밍은 도구다. UX가 중요한 대화형 인터페이스에서는 사실상 기본값으로 채택해야 할 만큼 효과가 검증되어 있지만, 응답 구조의 정확성이 최우선인 백엔드 로직에서는 오히려 짐이 될 수 있다. 처음 챗봇에 스트리밍을 붙이던 날 "이걸 왜 이제야 했지"라고 생각했던 기억이 난다. 지금도 대화형 서비스를 새로 설계할 때 스트리밍을 빼는 경우는 거의 없다. 다만 어디서 쓰고 어디서 빼야 하는지를 처음부터 구분하고 들어가는 것, 그게 내가 배운 가장 중요한 교훈이었다.

 

참고


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 ⚡ 정보 부스터 🚀