토큰·컨텍스트 윈도우
글을 세는 단위, 올릴 수 있는 양, 그리고 비용.
한눈에
- 토큰 = 글을 잘게 부순 조각 (레고 블록, 한글은 영어보다 더 잘게 쪼개진다)
- 컨텍스트 윈도우 = 한 번에 올릴 수 있는 최대 토큰 수 (책상 크기, 넘치면 앞부분부터 밀려 떨어진다)
- 컨텍스트 윈도우 = 입력 + 출력 합산 (자료를 가득 넣으면 답 쓸 자리가 좁아진다)
- 글자 수 ≠ 토큰 수 (공백·줄바꿈·문장부호도 전부 토큰, 정확한 수는 세어봐야 안다)
- 비용 = 토큰 수로 과금 (입력·출력 단가가 다르고 보통 출력이 더 비싸다)
모델은 글을 통째로 읽지 않는다. 문장을 잘게 부수어 조각으로 만든 다음, 그 조각들을 하나씩 센다. 이 조각이 **토큰(token)**이다. 레고를 떠올리면 쉽다. 완성된 문장이 레고 작품이라면, 모델은 그걸 일단 블록 단위로 분해해서 다룬다. "안녕하세요"는 사람 눈엔 한 단어지만, 모델에겐 여러 블록으로 쪼개진 무더기일 수 있다.
그리고 이 블록을 한 번에 올려놓을 수 있는 자리는 정해져 있다. 그게 **컨텍스트 윈도우(context window)**다. 책상 크기라고 보면 된다. 책상이 넓으면 블록을 많이 올려 한눈에 보고 작업하지만, 좁으면 다 못 올린다. 억지로 올리면 앞쪽 블록부터 책상 밖으로 밀려 떨어진다 — 모델이 그 부분을 못 보게 된다는 뜻이다.
토큰, 글을 조각내서 센다
토큰은 딱 단어 하나가 아니다. 단어 조각(subword)일 때가 많고, 언어에 따라 잘게 쪼개지는 정도가 다르다. 몇 가지 감만 잡아두면 된다.
그래서 "글자 수"와 "토큰 수"는 다르다. 대충 어림하되, 비용이나 한계를 따질 땐 실제로 세어보는 게 맞다. 모델마다 쪼개는 방식(토크나이저)이 조금씩 다르기 때문이다.
컨텍스트 윈도우, 책상이 넘치면
컨텍스트 윈도우에서 꼭 기억할 점 하나. 입력과 출력을 합쳐서 센다. 내가 넣은 질문·자료(입력)와 모델이 쓸 답(출력)이 같은 책상을 나눠 쓴다. 자료를 책상 가득 올리면 답 쓸 자리가 좁아진다.
긴 대화에서 모델이 "앞에서 한 말"을 잊은 것처럼 굴 때가 있는데, 실제로 앞부분이 책상 밖으로 밀려난 경우가 많다. 윈도우가 아무리 커져도 무한은 아니라서, 넣을 것을 고르고 줄이는 게 늘 일이 된다.
비용, 토큰이 곧 계산서
대부분의 LLM API는 토큰 수로 과금한다. 쓴 만큼 낸다. 그리고 입력 토큰과 출력 토큰의 단가가 다르다 — 보통 출력이 더 비싸다. 그래서 "자료를 얼마나 넣었나"와 "답을 얼마나 길게 뽑았나"가 둘 다 비용에 잡힌다. 같은 작업이라도 자료를 통째로 밀어넣느냐, 필요한 부분만 추려 넣느냐로 청구서가 갈린다.
우리 프로젝트에선
saegim-eval은 LLM을 심판으로 세워 검색·답변 품질을 채점하는데, 호출마다 토큰과 비용을 실측한다(usage.py). 모델이 돌려주는 usage 값을 받아 입력·출력 토큰을 세고 단가를 곱해 비용을 남긴다. 단가를 아직 확인하지 못한 모델은 억지로 숫자를 채우지 않고 정직하게 비워둔다 — 날조하느니 빈칸이 낫다는 원칙이다. 자세한 건 LLM-as-judge에.
토큰을 아끼는 쪽으로도 쓴다. 이 블로그를 짓는 하네스는 멀티 에이전트로 도는데, 큰 탐색이나 검색은 서브에이전트에게 떼어 맡긴다. 서브에이전트는 자기만의 책상에서 파일을 잔뜩 읽고 결론만 메인에 돌려준다. 파일 수백 줄이 메인 대화의 책상에 올라오지 않으니 그만큼 토큰이 절약된다. 컨텍스트 윈도우가 유한하다는 사실을 설계로 받아친 셈이다.
더 읽기
토큰과 컨텍스트 윈도우를 그림·예시로 더 풀어놓은 글들. 감이 안 잡힐 때 하나씩.
- LLM의 토큰이 대체 뭔가요? — brunch — 김밥 자르기·레고 블록 같은 일상 비유로, 토큰화부터 컨텍스트 한계까지 쉽게
- LLM 컨텍스트 윈도우란? 정의·중요성·RAG — appen — 컨텍스트 윈도우가 왜 중요한지, RAG와 어떻게 얽히는지
- 토큰 이해 — Microsoft Learn — 토큰화 방식·컨텍스트 창·토큰 기반 가격까지 원리 중심으로 정리한 공식 문서