LLM 잘 쓰는 법

정밀한 요청은 예의가 아니라 토큰 경제학이다 — LLM을 잘 쓰는 법 (1)

RoutineCode Team·2026-09-22·8분

코딩 에이전트를 쓰는 사람이라면 이 장면이 익숙할 것이다. "로그인 쪽 좀 봐줘"라고 던지면, 에이전트는 곧장 코드베이스를 넓게 뒤지기 시작한다. 관련 있어 보이는 파일을 하나씩 열고, 라우터를 따라가고, 미들웨어를 확인한다. 정작 당신이 원한 건 "세션 만료 후 401이 무한 반복되는 것"이었는데, 에이전트는 그걸 모르니 로그인 UI부터 토큰 발급까지 다 훑는다. 답이 나올 때쯤이면 이미 수정에 쓸 여력이 줄어 있다.

흔히 이걸 "요청을 명확히 하라"는 매너의 문제로 넘긴다. 하지만 이건 매너가 아니라 성능의 문제다. 정밀한 요청이 왜 더 나은 결과를 내는지는 LLM이 실제로 어떻게 작동하는지를 보면 필연적으로 따라 나온다. 이 글은 그 원리를 짚고, 거기서 실전 사용법을 도출한다. 특정 제품과 무관하게 LLM 에이전트를 쓰는 사람이라면 그대로 적용된다.

무슨 일이 벌어지나

모호한 요청은 에이전트를 "탐색"으로 몰아넣는다. 무엇을 해야 할지 특정되지 않았으니, 에이전트가 할 수 있는 유일한 일은 단서를 찾아 파일을 읽는 것이다. 이 탐색은 공짜가 아니다. 읽은 파일의 내용이 전부 에이전트의 작업 공간에 쌓이고, 그 공간은 무한하지 않다. 탐색이 길어질수록 정작 당신의 요구사항은 뒤로 밀리고 흐려진다. 결과는 둘 중 하나다 — 엉뚱한 곳을 고치거나, 맞는 곳을 고치더라도 오래 걸리고 되돌림이 잦다.

왜 그런가 — LLM의 작동 원리

세 가지가 겹쳐서 벌어지는 일이다.

첫째, 컨텍스트는 고정된 예산이다. LLM은 정해진 크기의 컨텍스트 윈도(요즘 모델은 대략 20만 토큰) 안에서만 세상을 본다. 시스템 프롬프트, 당신의 지시, 읽은 파일, 도구 출력 — 전부 이 하나의 예산을 나눠 쓴다. 그런데 소스 파일 하나를 읽으면 대략 1,100~2,400토큰이 들어온다. 모호한 요청이 파일 열 개를 읽게 만들면 그것만으로 2만 토큰이 사라진다. 예산이 차오르면 앞쪽에 있던 당신의 원래 지시가 요약되거나 잘려 나간다. Anthropic도 자사 문서에서 이 점을 명시한다 — "파일 읽기가 컨텍스트 사용을 지배한다. 구체적으로 요청할수록 Claude가 파일을 덜 읽는다."

둘째, 어텐션은 제로섬 경쟁이다. 트랜스포머의 셀프 어텐션에서 모델은 다음 토큰을 만들 때 이전의 모든 토큰을 참조한다. 그런데 이 참조의 총량(어텐션 질량)은 softmax로 정규화되어 합이 1로 고정돼 있다. 즉 컨텍스트에 토큰이 많아질수록, 정작 중요한 토큰 — 당신의 실제 요구사항 — 이 가져가는 몫은 작아진다. 관련 없는 파일 내용이 잔뜩 실릴수록 핵심 지시는 잡음에 희석된다. 게다가 이 연산은 토큰 수 N에 대해 O(N²)이라, 긴 컨텍스트는 느리기까지 하다.

셋째, 긴 컨텍스트의 중간은 잘 안 읽힌다. "lost in the middle"이라 불리는 현상으로, 모델은 컨텍스트의 맨 앞과 맨 뒤를 상대적으로 강하게 참조하고 중간에 낀 내용은 회수 신뢰도가 떨어진다. 탐색이 길어져 당신의 초기 지시가 긴 파일 덤프들 사이 중간으로 밀려나면, 그 지시는 물리적으로 남아 있어도 실질적으로 약해진다.

정리하면, 모호한 요청의 진짜 비용은 "다시 물어봐야 하는 번거로움"이 아니라 "핵심 신호가 희석되고 예산이 소진되는 것"이다. 요청을 좁히는 것은 예의가 아니라 토큰 최적화다.

그래서 어떻게 써야 하나

에이전트가 탐색으로 알아내야 할 것을 당신이 미리 주면, 그만큼 파일을 안 읽어도 된다. 요청에 세 가지를 담는다.

  • 동사 — 무엇을 하는 행위인가. 고쳐라 / 추가해라 / 옮겨라.
  • 증상 또는 위치 — "세션 만료 후 401 무한 반복", 혹은 아는 경우 auth.middleware.ts.
  • 기대결과 — "만료 쿠키를 감지하면 조용히 재로그인으로 보내야 한다."

나쁜 예와 좋은 예를 나란히 두면 차이가 분명하다.

  • "로그인 봐줘"
  • "세션이 만료되면 401이 무한 반복된다. auth.middleware.ts에서 만료 쿠키를 감지해 재로그인 플로우로 보내도록 고쳐줘."
다트가 과녁 정중앙에 꽂힌 흑백 이미지
정밀한 요청은 정확히 겨냥한다. 모호한 요청은 과녁 주변을 흩어진다.

문장 하나 늘렸을 뿐이지만, 에이전트는 넓은 스캔을 건너뛰고 바로 해당 지점으로 간다. 파일 경로를 모르면 증상만이라도 구체적으로 주면 된다 — 증상이 좁을수록 탐색 범위도 좁아진다.

RoutineCode도 같은 원리 위에 있다

RoutineCode가 작업을 처리하는 방식은 이 원리를 제품 차원에서 구현한 것이다. RoutineCode는 요청을 받으면 무턱대고 파일을 읽는 대신, 정밀한 요청일수록 탐색을 건너뛰고, 광범위한 탐색이 필요할 때는 그 비용을 별도의 서브에이전트 컨텍스트로 밀어내 메인 대화의 예산을 지킨다. 조사가 파일 스무 개를 읽어야 하는 일이면, 그 스무 개는 격리된 창에서 읽히고 당신의 세션에는 요약된 결론만 돌아온다.

여기서 순정 Claude Code와의 차이가 갈린다. 기본 에이전트는 "이 프로젝트가 빌드되나", "이 심볼이 어디서 쓰이나", "의존성이 어떻게 얽혀 있나" 같은 반복적 조회에도 결국 파일을 열어 컨텍스트에 적재하고 추론으로 답한다 — 그 읽기 자체가 예산을 갉아먹는다. RoutineCode는 그 위에 한 겹을 더해, 이런 일상 조회를 추론이 아니라 결정적 도구로 처리하고 파일 본문 대신 구조화된 답만 컨텍스트에 돌려준다. 본문이 추론 창에 실리지 않으니, 같은 질문에 드는 컨텍스트가 원리적으로 다르다. 넓은 탐색이 필요한 순간에도 곧장 파일을 읽지 않고 "직접 처리할지, 격리된 탐색 에이전트에 위임할지"를 먼저 판정해, 불필요한 탐색을 시작 전에 잘라낸다.

당신이 정밀한 요청을 주는 것과 RoutineCode가 탐색을 격리하는 것은 같은 목적 — 핵심 신호가 잡음에 희석되지 않게, 예산을 실제 작업에 남겨두는 것 — 을 위한 두 방향의 노력이다.

기대효과와 결과

  • 첫 응답이 빨라진다. 탐색 라운드가 줄어드니 처음부터 맞는 지점을 건드린다.
  • 한 번에 맞는 결과가 나온다. 요구사항이 잡음에 희석되지 않아, 엉뚱한 걸 고쳐놓고 되돌리는 왕복이 준다.
  • 긴 작업에서도 초기 의도가 살아 있다. 예산이 여유로우니 당신의 지시가 중간으로 밀려 잊히지 않는다.

체감상으로는 "다시 설명하고 다시 시키는" 반복이 눈에 띄게 줄어든다. 에이전트를 잘 쓰는 것은 결국 좋은 입력을 주는 일이고, 좋은 입력의 첫 번째 규칙은 탐색시킬 것을 미리 좁혀 주는 것이다.


이 글은 "LLM을 잘 쓰는 법" 시리즈의 1편이다. 다음 편에서는 CLAUDE.md 같은 상시 로드 지시가 왜 길수록 안 지켜지는지 — 지시가 많을수록 준수율이 떨어지는 역설 — 을 같은 원리로 다룬다.

참고 자료

#LLM#ContextWindow#어텐션#AI에이전트#ClaudeCode

Want posts like this weekly?

Subscribe for AI dev-workflow insights.