콘텐츠로 이동

비대한 코드가 부른 토큰 폭증·컨텍스트 비대화·LLM 환각

사람에게 1,200줄짜리 파일은 그냥 “읽기 싫은 파일”입니다. 하지만 AI에게는 다릅니다. 그 파일을 읽는 순간 작업 기억(컨텍스트 창)이 가득 차고, 토큰 비용이 폭증하고, 결국 AI가 없는 사실을 지어내기 시작합니다. 비대한 코드는 AI 협업에서 단순한 미관 문제가 아니라 정확도 문제이자 돈 문제입니다. 이 글은 그 연쇄가 왜 일어나는지를, 모르는 독자도 따라올 수 있게 처음부터 설명합니다.

먼저 용어 두 개 — 토큰과 컨텍스트 창

섹션 제목: “먼저 용어 두 개 — 토큰과 컨텍스트 창”

이 글의 모든 이야기는 이 두 단어 위에서 돕니다. 어렵지 않으니 짚고 가겠습니다.

핵심은 이것입니다. AI는 코드를 고치려면 먼저 읽어야 하고, 읽은 것은 컨텍스트 창(책상)을 차지하며, 그 차지한 양만큼 토큰(돈)이 듭니다. 그러니 “코드가 크다”는 건 AI 입장에선 “매번 비싸고, 책상이 금방 찬다”는 뜻입니다.

사람과 AI가 같은 큰 파일을 마주할 때 무엇이 다른지 정리하면 이렇습니다.

큰 파일을 만났을 때사람AI
읽는 비용시간(피로)토큰 = 실제 돈
”너무 크다” 직관있음 — 스스로 나눔없음 — 규칙 없으면 계속 덧붙임
작업 기억 한계흐릿하게 인지컨텍스트 창으로 딱딱하게 제한
한계 초과 시잠깐 헷갈림중간 정보 소실 → 환각

큰 파일은 AI에게 곧 비용이다 — 숫자로 보기

섹션 제목: “큰 파일은 AI에게 곧 비용이다 — 숫자로 보기”

SL.AIMS에서 가장 크게 자란 파일들은 1,100~1,300줄에 달했습니다(연구소 ≈1,279줄, 연차 ≈1,133줄, 결재 ≈1,104줄 — god 파일 이야기 참조). 이런 파일 하나를 열면 책상의 상당 부분이 그 파일로 덮입니다. 관련 파일 두세 개만 더 열면 책상이 거의 찹니다.

컨텍스트 창 = AI의 책상 (유한하다) 작은 파일들로 채울 때 필요한 파일 A (작음) 필요한 파일 B (작음) 필요한 파일 C (작음) 여유 공간 — 더 볼 수 있음 god 파일 하나로 채울 때 god 파일 1개 (≈1,200줄) 책상의 대부분을 차지 여유 거의 없음 — 곧 가장자리가 흐려짐
같은 크기의 책상에 작은 파일 여럿을 올리면 여유가 남지만, god 파일 하나를 올리면 책상이 꽉 찹니다. 꽉 찬 책상에서는 가장자리(먼저 올린 정보)가 흐려지기 시작합니다 — 이게 다음 절의 환각으로 이어집니다.

책상이 차면 일어나는 두 가지 나쁜 일

섹션 제목: “책상이 차면 일어나는 두 가지 나쁜 일”

컨텍스트 창이 가득 차면 두 가지가 동시에 나빠집니다.

① 토큰 비용이 치솟습니다. AI는 매 요청마다 책상에 올라온 맥락 전체를 다시 처리합니다. 그 맥락이 거대하면, 작은 질문 하나에도 거대한 비용이 듭니다. 큰 파일을 끼고 대화를 이어갈수록 매 턴이 점점 비싸집니다.

② 먼저 읽은 내용을 “잊습니다.” 더 위험한 쪽입니다. 컨텍스트 창의 한가운데 있는 정보일수록 흐려진다는, 잘 알려진 현상이 있습니다.

중간 정보가 흐려지면 AI는 그 빈자리를 그럴듯한 추측으로 메웁니다. 바로 이게 환각입니다.

비대화 → 환각의 연쇄 (왜 한 뿌리인가)

섹션 제목: “비대화 → 환각의 연쇄 (왜 한 뿌리인가)”

이제 조각들이 한 줄로 꿰어집니다. 비대한 코드 한 덩어리가 어떻게 환각까지 이어지는지, 화살표로 따라가 보겠습니다.

코드가 큼1,200줄 파일 토큰 폭증매 요청 비싸짐 책상이 참컨텍스트 창가득 중간 소실가운데 정보흐려짐 환각없는 걸 지어냄 사람 혼자 짤 땐 안 보이던 비용이, AI와 협업하면 이렇게 정면으로 드러납니다.
비대한 코드가 출발점입니다. 큰 파일 → 토큰 폭증 → 컨텍스트 포화 → 중간 소실 → 환각. 사슬의 어느 고리든 끊으면 뒤가 막히지만, 가장 근본은 맨 앞(코드를 작게)입니다.

이론이 아니라 실제로 그랬습니다. 핵심 모듈일수록 파일이 부풀었고(가장 큰 것들이 1,100~1,300줄), 그 파일을 만질 때마다 AI의 응답 품질이 눈에 띄게 떨어졌습니다. 증상은 늘 비슷했습니다.

  • 없는 필드명을 만들어 냈습니다 — 실제 스키마엔 없는 이름을 그럴듯하게 지어 코드에 박았습니다.
  • 이미 있는 유틸을 모르고 또 짰습니다 — 책상에 그 유틸이 안 올라와 있으니, 없는 줄 알고 중복 구현했습니다.
  • 다른 모듈에 미칠 영향을 못 봤습니다 — 전체를 동시에 못 보니 한 곳을 고치며 다른 곳을 깨뜨렸습니다.

전부 “전체 맥락을 동시에 못 보는” 데서 온 실수였습니다. 그리고 그 “못 보는” 이유의 큰 몫이 바로 비대한 파일이 책상을 잡아먹은 것이었습니다.

두 갈래의 처방 — 코드를 줄이고, 안 읽게 만든다

섹션 제목: “두 갈래의 처방 — 코드를 줄이고, 안 읽게 만든다”

대응은 두 방향이었습니다. 하나는 책상에 올릴 짐 자체를 줄이는 것, 다른 하나는 애초에 큰 짐을 책상에 안 올리는 것입니다.

거대 파일을 작은 단위로 쪼개고(facade 분할), 하드코딩을 공통코드로 옮겨 중복을 걷어냈습니다. 읽을 게 적으면 토큰도 적습니다 — 가장 직접적인 처방입니다.

처방 ② 파일 전체를 읽지 않게 만든다

섹션 제목: “처방 ② 파일 전체를 읽지 않게 만든다”

이쪽이 특히 중요했습니다. 큰 파일이 있더라도 통째로 열지 않게 하는 것입니다. 두 가지 도구를 썼습니다.

  • 코드 구조 그래프 — 코드의 구조(어떤 함수가 어디서 불리는가)를 미리 그래프로 만들어 두고, “이 함수의 파급 범위만” 콕 집어 조회합니다. 1,200줄을 다 읽지 않고도 “건드리면 어디가 영향받나”를 압니다.
  • 문서 부분 검색 — 설계 문서는 통째로 읽는 대신 검색 도구로 필요한 조각만 회수합니다.
처방겨냥하는 것구체적 방법
① 코드를 줄인다책상에 올릴 짐 자체거대 파일 분할 · 하드코딩 → 공통코드로 중복 제거
② 안 읽게 만든다큰 짐을 책상에 안 올림구조 그래프로 파급 범위만 조회 · 문서는 부분 검색

이 글은 SL.AIMS를 만들며 겪은 현장 회고 중 하나입니다. 전체 그림은 〈사례연구: SL.AIMS〉에 있고, 비대화를 처음부터 막는 ratchet 게이트 이야기로 이어집니다.