지난 글까지 무엇을 어떻게 찾을 것인가를 다뤘다. 이번에는 그 한 번이 얼마나 걸리고 얼마가 드는가다.
RAG가 느리다거나 비싸다는 말은 자주 나오는데, 어디가 그런지를 나눠 본 뒤에 하는 경우는 드물다. 그리고 나눠 보면 대개 짐작과 다른 자리가 나온다.
시간은 생성이 먹는다
숫자는 구성마다 다르지만 비율의 모양은 잘 안 바뀐다. 검색 쪽 전부를 합쳐도 200ms 안팎이고, 답을 만드는 데 2~3초가 든다. 벡터 저장소를 더 빠른 것으로 바꿔 검색을 40ms에서 20ms로 줄여도 사용자가 느끼는 시간은 0.7% 짧아진다.
검색 안쪽만 따로 보면 재순위가 3분의 2를 쓴다. 재순위는 후보 50개를 모델에 한 번씩 통과시키는 일이라, 벡터 거리를 재는 것과는 자릿수가 다르다. 그래서 「검색이 느리다」는 대개 재순위 이야기다.
그런데 재순위를 빼는 것이 답은 아니다. 재순위가 있으면 근거를 열 개 대신 세 개만 넣고도 답 품질이 유지된다. 근거 일곱 개가 빠지면 생성 단계에 들어가는 토큰이 몇천 개 줄고, 그쪽에서 아끼는 시간이 재순위에 쓴 120ms보다 훨씬 크다. 한 단계만 보고 판단하면 이 맞바꿈이 안 보인다.
돈은 근거 토큰이 먹는다
비용은 시간과 조금 다르게 쏠린다. 임베딩과 벡터 저장소도 돈이 들지만, 질의 한 번의 비용을 세어 보면 대부분 생성 모델에 넣은 입력 토큰이다.
한 질의를 토큰으로 세어 보자. 사용자 질문 30토큰, 시스템 지침 800토큰, 근거 청크 열 개 6,000토큰, 답 400토큰. 입력이 6,830이고 출력이 400이다. 그리고 이 중 88%가 근거다.
여기서 나오는 결론이 하나 있다. 근거 개수를 줄이는 것이 가장 큰 절약 수단이다. 열 개를 네 개로 줄이면 입력 토큰이 절반 아래로 떨어진다. 문제는 그냥 줄이면 답이 나빠진다는 것이고, 그래서 앞에서 본 재순위가 필요하다 — 개수를 줄이면서 품질을 지키는 장치다.
| 줄이는 수단 | 지연 | 비용 | 치르는 대가 |
|---|---|---|---|
| 근거 개수를 줄인다 | 크게 준다 | 크게 준다 | 필요한 근거가 빠지면 답이 틀린다 |
| 재순위를 넣는다 | 검색은 늘고 생성은 준다 | 준다 | 재순위 모델 비용이 붙는다 |
| 청크를 짧게 만든다 | 준다 | 준다 | 맥락이 잘려 근거가 조각난다 |
| 작은 모델로 답한다 | 크게 준다 | 크게 준다 | 근거가 많을 때 요약을 놓친다 |
| 답을 흘려 보낸다 | 체감만 준다 | 그대로 | 없다. 안 할 이유가 없다 |
| 프롬프트 캐시를 쓴다 | 조금 준다 | 준다 | 순서를 고정해야 한다 |
맨 아래 두 줄부터 한다. 대가가 거의 없기 때문이다. 위쪽 넷은 품질과 맞바꾸는 것이라 평가 없이 손대면 안 된다.
흘려 보내면 체감이 달라진다
전체 3초 중 첫 글자가 나오기까지가 600ms이고 나머지 2,400ms는 뒷부분을 쓰는 시간이다. 답을 다 만든 뒤에 한꺼번에 보내면 사용자는 3초를 기다리고, 흘려 보내면 0.6초 뒤부터 읽기 시작한다. 총 시간은 똑같다.
그래서 재는 값이 둘이어야 한다. 첫 글자까지의 시간과 전체 시간은 고쳐야 할 자리가 서로 다르다.
- 첫 글자까지가 길다 → 입력이 길다. 근거 토큰, 시스템 지침, 캐시 적중률을 본다
- 전체가 길다 → 출력이 길다. 답 길이 지침, 모델 크기를 본다
근거를 줄이면 앞엣것이 짧아지고, 답을 짧게 쓰게 하면 뒤엣것이 짧아진다. 한 값만 보고 있으면 엉뚱한 쪽을 만지게 된다.
캐시는 앞에서부터만 걸린다
프롬프트 캐싱은 입력 토큰 비용을 크게 깎는 수단인데, RAG에서는 조건이 하나 붙는다. 캐시는 프롬프트의 앞에서부터 같은 데까지만 걸린다. 한 글자라도 다른 지점이 나오면 거기서 끊긴다.
근거 문서는 질의마다 다르니 캐시에 걸릴 수 없다. 그건 어쩔 수 없다. 문제는 그 근거를 프롬프트 맨 앞에 두는 구성이다 — 그러면 뒤에 오는 시스템 지침 800토큰이 고정인데도 매번 새로 계산된다.
고정된 것을 앞으로, 매번 바뀌는 것을 뒤로 보낸다. 시스템 지침과 고정 예시를 앞에 두면 그만큼이 캐시에 걸리고, 근거와 질문만 매번 새로 읽힌다. 순서를 바꾸는 것뿐인데 입력 비용이 눈에 띄게 내려간다.
여기에 하나 더 있다. 근거 청크를 붙이는 순서도 고정해야 한다. 검색 점수 순으로 붙이면 같은 문서가 뽑혀도 자리가 흔들려 캐시가 안 먹는다. 문서 식별자처럼 안 변하는 기준으로 정렬해 붙이면, 자주 뽑히는 문서 조합에서 캐시가 걸릴 여지가 생긴다. 다만 청크 순서가 답 품질에 영향을 주는 만큼, 이 맞바꿈은 평가로 확인하고 정한다.
평균이 아니라 꼬리를 본다
마지막으로 무엇을 재느냐다. 평균 응답 시간이 2.8초라는 값은 거의 쓸모가 없다. 불만은 평균에서 나오지 않는다.
p95를 본다. 상위 5%가 8초를 쓰고 있다면 그 5%가 매일 수천 번이고, 그 사람들이 서비스를 판단한다. 그리고 꼬리가 길어지는 이유는 평균이 길어지는 이유와 다른 경우가 많다 — 근거가 유난히 긴 문서였거나, 앞 글에서 본 것처럼 남의 대량 적재에 밀렸거나, 필터 선택도가 나쁜 구간에 걸렸거나.
단계마다 따로 기록한다. 전체 시간 하나만 남기면 느린 요청을 찾아도 어디가 느렸는지 모른다. 임베딩·검색·재순위·생성 네 값과 입력 토큰 수, 근거 개수를 함께 남기면 느린 요청 몇 개만 봐도 원인이 보인다. RAG 평가에서 품질 지표를 남길 때 이 값들을 같은 자리에 함께 남기면, 나중에 품질과 비용을 한 화면에서 비교할 수 있다.
목표를 먼저 정한다. 「빠르게」는 목표가 아니다. 사내 문서 검색이라면 p95 5초도 괜찮고, 통화 중에 상담원을 돕는 용도라면 첫 글자까지 1초를 넘으면 못 쓴다. 목표가 정해져야 위 표의 어느 줄까지 감수할지가 정해진다.
정리
- 한 질의의 시간은 대부분 생성이 쓴다. 검색을 반으로 줄여도 전체는 거의 안 준다
- 검색 안쪽에서는 재순위가 대부분이지만, 그 덕에 근거를 줄이면 생성에서 더 크게 돌려받는다
- 비용은 근거 토큰이 8할 이상이다. 개수를 줄이는 것이 가장 큰 절약이다
- 흘려 보내기와 캐시 순서 정리부터 한다. 품질을 안 깎고 얻는 것이라서다
- 캐시는 프롬프트 앞에서부터만 걸린다. 고정된 것을 앞에, 바뀌는 것을 뒤에 둔다
- 첫 글자까지의 시간과 전체 시간을 나눠 잰다. 고칠 자리가 다르다
- 평균이 아니라 p95를 보고, 단계별 시간과 토큰 수를 함께 기록한다
읽어주셔서 감사합니다. 😊

