LLM 모델로 어려운 일을 가능하게 하는 방법
LLM은 다양한 지식, 글, 영상, 데이터에 점수를 메기고 가중치를 두어 input으로 제공하고, output에 대해서 다시 특정 점수들을 높이는 방향으로 피드백하며 만들어지는 모델입니다. 특정 시기까지의 인간 세상 + 연구자의 철학이 반영되어 만들어진 박스라고 저는 생각합니다.
이렇게 생각했을 때, 이 박스는 다음과 같은 한계들을 기본적으로 가지는 것 같습니다.
- 인터넷의 자료, 유명한 것들, 커뮤니티 생태계, 만든 사람들의 영향을 크게 받습니다.
- 시간적 제약이 존재합니다.
- 논리적 체계 (Reasoning, Chain of thought)
그리고 이러한 한계들과 상황 속에서, 신경망 내부에서 여러 시냅스를 거치고 점수로 평가되어 최종 output이 발생하게 됩니다. 그 output은 우리가 제공한 context 속에서 그 context에 있었던 대화나 기록 문서들, 그리고 벤치마킹을 높이고 연구자들의 철학이 들어간 종합적인 가장 높은 점수의 무언가일 것입니다.
이제 다시 돌아와서, 우리가 LLM을 통해서 진정으로 원하는 것은 우리의 상황에 맞는 최고 점수의 응답을 얻는 것입니다.
- 내가 일을 하는 방식
- 내가 일하는 회사의 규칙들
- 역사
같은 일이나 질문에 대해서도 확률적으로 여러 답변이 존재하고, 우리는 context나 도구를 통해서 우리가 원하는 답변의 확률 분포에 접근하고자 하게 됩니다.
지금까지 이렇게 optimal한 output을 얻기 위해 LLM위에 만들어진 체계들은 다음과 같습니다.
- Prompting
- MCP
- Skill
- Harness
- Hook
우리는 이 도구들을 작업 전(프롬프팅, 스킬), 작업 중(MCP, Skill, hook), 그리고 작업 후(Harness, hook)에 배치해 최종 결과물이 나오는 과정에 간섭함으로써 확률 분포를 결정적으로 만들고자 합니다. 그러나, 우리는 우리가 만든 장치들로 제한된 확률 분포가 무엇인지 정확하게 알지 못하고, 그로부터 발생하는 결과물들을 가지고 우리는 우리가 제한한 장치들의 효과를 추측합니다.
따라서, AI를 가지고 작업을 설계하고 진행하는 것은 본질적으로 많은 시도와 결과에 대한 피드백을 필수로 가지게 됩니다. 많이 사용하고, 이를 데이터화하고 우리가 벗어나는 확률분포를 제거하기 위해 장치를 추가하고, 이 반복을 끊임없이 필요로 합니다.
또한 이런 특성들에서 발생하는 문제가 없는 것을 만드는 것은 쉽습니다. 그러나 이미 존재하는 시스템을 고치는 것은, 모델이 가지는 확률 분포와 이미 존재하는 확률 분포 사이의 차이들을 관찰하고 조정하여 맞춰가는 과정을 끊임없이 시간을 들여야 합니다. 이를 개발자들은 ‘매우 똑똑한 신입을 가르치는 것과 같다’라고 표현하는 것 같습니다.
- portkey API를 통해서 프롬프트를 관리하고 기록을 기반으로 대시보드를 생성하는 일 -> 매우 잘 됨
- Portkey logs에서 하나하나 클릭하여 request와 response 수집 -> 수집 개수에 따라 거절(많은 트레이스를 수집하라고 명령하면 효율을 들어 거절)
- 레거시가 많은 프레임워크에서 feature 개발 요청 -> 컨벤션이 다른 코드 생성 확률 증가
그런데 여기서 발생하는 고민점은, 레거시 컨벤션이 좋은 컨벤션이 아닌 경우 - 혹은 레거시와 리팩토링의 중간 상태에 있는 경우, 모델에 입력되는 컨텍스트가 혼란한 상태인 경우입니다. 이 경우 프롬프트와 스킬로 최대한 모델의 확률분포를 제한하더라도, 컨텍스트가 계속 모델의 불확정성을 유발하게 됩니다.
이 경우 제가 한 선택은 skill+hook 기반으로 매 iteration, 입력마다 refine과 규칙을 강제하고, 최소 코드 원칙을 바탕으로 slop을 정리하는 것을 반복했습니다. 그러나, 레거시일수록 같은 기능 구현이나 변화에 더 많은 휴먼리소스를 필요로 하는 것처럼, 더 많은 AI token과 시간으로 소모됩니다.
결론
결국, AI로 모든 걸 혁신하고 모든 것을 앞당길 수 있다고 생각했던 저의 생각은 반 정도 성공했습니다. 그 동안 회사에서 아무도 체계적으로 관리하고 있지 못 했던 것을 관리할 수 있는 시스템을 구축했지만, 레거시 시스템에서 AI기반으로 빠르게 feature를 개발하는 것은 성공하기 어려웠습니다. 결국에는 기존 컨벤션을 지키면서 개발할 수 있는 환경을 구성했지만, 시간과 토큰 소모량이 더 높아졌습니다. 앞으로 AI 기반 일을 설계할 때는 모델에 대한 이해, 그리고 적용하는 환경에 대한 이해를 충분히 하고 middle layer로 연결하는 방식들을 좀 더 시도하는 방식을 익혀야할 것 같습니다. Everything claude code, ontology도 좋은 연결고리이지만, 얼마나 혁신을 추구할지, 얼마나 리팩토링을 하고 기존 패턴으로 진행할 지와 같은 큰 그림을 그리는 부분은 앞으로도 발전할 여지가 많은 것 같습니다.
LLM은 확률의 박스다
LLM은 특정 시점까지의 인터넷 텍스트, 코드, 영상, 데이터에 가중치를 부여하고 피드백 루프를 거쳐 만들어진 모델이다. 나는 이것을 인간 세상의 스냅샷 + 제작자의 철학이 반영된 확률 박스라고 생각한다.
이 박스에는 세 가지 태생적 한계가 있다.
편향(Bias). 인터넷에서 많이 다뤄진 것, 유명한 것, 커뮤니티 생태계의 주류에 확률이 편중된다. Stack Overflow에서 많이 추천받은 패턴은 높은 확률로 생성되고, 니치한 도메인이나 소수 커뮤니티의 관행은 낮은 확률을 받는다. 제작자의 RLHF(Reinforcement Learning from Human Feedback) 철학도 확률 분포에 직접 개입한다.
시간적 단절(Temporal Cutoff). 학습 시점 이후의 정보는 모델 내부에 존재하지 않는다. 지난주 릴리즈된 라이브러리의 breaking change는 모델이 알 수 없다.
추론의 불확실성(Reasoning Uncertainty). Chain of Thought나 Reasoning 능력은 강력하지만, 모델의 “추론”은 학습된 패턴의 확률적 조합이다. 논리적으로 보이는 출력이 실제로는 가장 높은 확률의 토큰 시퀀스일 뿐인 경우가 있다.
우리가 이 박스에 질문을 던지면, 내부 신경망이 수십억 개의 파라미터를 거쳐 가장 높은 점수의 output을 생성한다. 그 output은 우리가 제공한 context, 학습 데이터의 확률 분포, 그리고 벤치마크 최적화의 종합적 결과물이다.
여기서 핵심적인 문제가 드러난다. 모델이 내놓는 “일반적으로 가장 좋은 답”과 “우리의 상황에 맞는 가장 좋은 답”은 다르다. 나의 업무 방식, 회사의 코딩 컨벤션, 프로젝트의 역사 — 이런 맥락 위에서의 최적 응답이 필요하다. 같은 질문에도 확률적으로 여러 답변이 존재하고, 우리는 그 분포에서 variance를 줄이고, 우리가 원하는 범주의 확률을 높이는 작업을 하게 된다.
Variance를 줄이는 도구들
LLM의 출력 variance를 줄이기 위해, 지금까지 다양한 장치들이 만들어져 왔다. Claude Code 생태계를 중심으로, 나는 이것들을 작업의 시간축(전·중·후)에 따라 분류한다. 이 분류는 Claude Code의 공식 개념들에 내 사용 경험을 더해 정리한 것이다.
Anthropic은 에이전트 시스템을 설계할 때 “workflow(사전 정의된 코드 경로)와 agent(LLM이 동적으로 프로세스를 지시하는 것)를 구분”해야 한다고 말한다. 아래 도구들은 이 두 가지 접근법을 실현하는 구체적인 장치들이다.
작업 전 — 확률 분포의 출발점을 설정
Prompting — 모델이 어떤 관점에서, 어떤 포맷으로, 어떤 제약 조건 하에서 답해야 하는지를 지정한다. 가장 기본적인 variance 감소 도구이면서, 동시에 가장 과소평가되기 쉬운 도구이기도 하다. 연구에 따르면 추상적 지시보다 프로젝트의 실제 코드 예시를 포함한 few-shot 프롬프팅이 정확도를 45~55%p 향상시킨다.
CLAUDE.md — 프로젝트 레벨에서 매 세션마다 자동으로 로드되는 지속적 instructions 파일이다. 프롬프팅이 일회성이라면, CLAUDE.md는 프로젝트의 규칙과 맥락을 영구적으로 모델에 주입하는 장치다. “이 프로젝트에서는 항상 이렇게 해라”를 매번 말하지 않아도 되게 해준다. Anthropic이 말하는 “효과적인 컨텍스트 엔지니어링”의 핵심 구현체다.
작업 중 — 모델의 행동 범위를 실시간으로 제한
Skill — 특정 도메인의 베스트 프랙티스와 규칙을 SKILL.md 파일에 정의해둔 것이다. 프롬프팅이 한 번의 지시라면, 스킬은 반복적으로 적용되는 도메인 전문 지식의 묶음이다. 별도의 SDK 없이 마크다운만으로 에이전트에게 전문 지식을 가르칠 수 있다는 점에서, 진입 장벽이 낮으면서도 효과가 큰 도구다.
MCP (Model Context Protocol) — 외부 시스템(API, DB, 파일)에 접근하여 모델이 실시간으로 맥락을 가져올 수 있게 하는 표준 프로토콜이다. 모델의 “알 수 있는 범위”를 확장하는 장치로, 학습 데이터에 없는 우리 회사의 Jira 티켓이나 Slack 메시지 같은 것을 모델이 참조할 수 있게 해준다. MCP가 없으면 모델은 학습 데이터의 일반적 확률에 의존할 수밖에 없고, 이는 곧 우리 상황과 맞지 않는 출력으로 이어진다.
Subagent — 특정 역할에 특화된 커스텀 에이전트다. 메인 에이전트가 모든 것을 처리하는 대신, “테스트 실행 전문”, “코드 리뷰 전문” 같은 역할을 분리하여 각각의 variance를 독립적으로 줄일 수 있다. 하나의 거대한 확률 분포를 조정하는 것보다, 여러 개의 작고 특화된 분포를 각각 조정하는 것이 더 효과적이다.
작업 후 — 결과를 검증하고 교정
Hook — 작업의 특정 시점(이벤트, 트리거, 완료 단계)에서 자동으로 실행되는 스크립트다. 모델이 특정 패턴의 코드를 생성하면 차단하거나, 결과물에 후처리를 적용하는 가드레일 역할을 한다. 작업 중과 후 모두에 걸쳐 동작하며, 확률적으로 발생할 수 있는 원치 않는 출력을 사후적으로 필터링하는 안전망이다.
Harness — Claude Code의 공식 기능명은 아니지만, Anthropic이 블로그에서 “에이전트의 실수가 반복되지 않도록 엔지니어링하는 것”으로 설명한 아키텍처 개념이다. 테스트, 린팅, 리뷰 같은 품질 게이트를 배치하여 최종 결과물을 검증한다. 특히 long-running agent에서는 에이전트가 여러 context window를 넘나들기 때문에, 세션 간의 일관성을 유지하기 위한 harness 설계가 필수적이다.
이것들을 묶는 배포 단위
Plugin — Skill, Hook, MCP, Subagent를 하나의 패키지로 묶어 배포하는 단위다. 개별 도구를 하나하나 설정하는 대신, 특정 워크플로우에 필요한 모든 장치를 한 번에 설치하고 팀 전체에 공유할 수 있게 해준다. variance를 줄이는 장치의 조합 자체를 재사용 가능하게 만드는 메타 도구다.
도구의 한계 — 관찰할 수 있을 뿐, 확정할 수는 없다
이 도구들을 조합하여 출력의 variance를 줄이고, 우리가 원하는 결과가 나올 확률을 높여간다. 하지만 결정적인 한계가 있다. 이 장치들이 분포를 실제로 어떻게 바꿨는지 우리는 정확히 알 수 없다. temperature를 0으로 설정하더라도 GPU의 부동소수점 연산 순서, 배치 처리 방식, 모델 업데이트 등으로 인해 LLM의 출력은 기술적으로 deterministic하지 않다. Structured output이나 constrained decoding(Guidance, Outlines 같은 도구)으로 출력의 형식은 보장할 수 있지만, 의미까지 보장하지는 못한다.
우리가 할 수 있는 것은 결과물을 관찰하고, 원하는 범주에서 벗어난 출력이 나오면 장치를 추가하거나 조정하는 것뿐이다. AI와 함께 작업을 설계한다는 것은 본질적으로 반복적인 실험과 피드백의 과정이다. 많이 사용하고, 결과를 데이터로 남기고, 벗어나는 패턴을 관찰하여 장치를 보강하는 루프를 돌려야 한다.
Greenfield는 쉽고, Brownfield는 어렵다
이런 확률적 특성에서 흥미로운 비대칭이 발생한다.
Greenfield(새로 만드는 것)는 비교적 쉽다. 모델이 가진 일반적인 확률 분포가 곧 “좋은 코드”의 방향과 일치하기 때문이다. HumanEval 같은 벤치마크에서 LLM이 87%의 정확도를 보이는 것은, 이런 종류의 과제 — 독립적이고, 컨텍스트가 적고, 일반적 패턴이 곧 정답인 과제 — 에서 모델의 확률 분포가 자연스럽게 정답 영역과 겹치기 때문이다.
하지만 Brownfield(이미 존재하는 시스템을 수정하는 것)는 근본적으로 다른 문제다. 연구에 따르면 실제 코드베이스에서 cross-file dependency가 존재하는 환경에서의 정확도는 약 30%까지 떨어진다. 벤치마크의 87%와 현실의 30% — 이 간극이 바로 greenfield와 brownfield의 차이다.
개발자들 사이에서 AI를 “매우 똑똑한 신입”에 비유하는 이유가 여기에 있다 — 빠르고, 박식하고, 의욕적이지만, 우리 팀만의 맥락은 가르쳐야 한다. 그리고 가르치는 비용은 환경의 복잡도에 비례한다.
왜 Brownfield가 어려운가 — Context Pollution
Brownfield에서 AI가 어려운 근본 원인은 context pollution이다. 연구에 따르면 컨텍스트에 10%의 무관한 정보가 추가되면 정확도가 23% 하락한다. 레거시 코드베이스에서는 이보다 훨씬 심각한 일이 벌어진다.
실제 업무에서 겪은 사례가 이를 잘 보여준다.
잘 된 경우 — Greenfield 시스템 구축: 프롬프트 관리 시스템과 로그 기반 모니터링 대시보드를 구성하는 작업이었다. 이전에 아무도 체계적으로 관리하지 않던 영역이었기에, 모델의 일반적 지식이 그대로 좋은 결과로 이어졌다. API 연동, 대시보드 설계 모두 모델이 학습한 “좋은 패턴”과 우리가 원하는 것이 일치했다. context pollution이 없는 깨끗한 환경이었다.
어려웠던 경우 — Brownfield Django 프로젝트에서 feature 개발: 수년간 운영된 백엔드 프로젝트에 새 기능을 추가하는 작업이었다. 모델은 Django 공식 문서 기준의 “모범적인” 코드를 생성했지만, 이 프로젝트만의 컨벤션 — 커스텀 미들웨어 패턴, 특수한 시리얼라이저 구조, 독자적인 에러 핸들링 방식 — 과는 달랐다. 모델이 참조하는 컨텍스트 안에 “Django의 일반적 패턴”과 “이 프로젝트만의 패턴”이 공존하면서, 출력이 둘 사이에서 흔들렸다. Skill로 컨벤션 규칙을 정의하고, Hook으로 매 iteration마다 규칙 위반을 감지하고, 최소 코드 원칙으로 slop을 정리하는 반복이 필요했다. 결국 컨벤션을 지키는 환경은 구성했지만, 시간과 토큰 소모량이 오히려 더 높아졌다.
가장 까다로운 경우 — 리팩토링 중간 상태: 레거시 컨벤션 자체가 좋지 않거나, 리팩토링의 중간 상태에 있는 경우다. 같은 프로젝트 안에서 “옛날 방식”과 “새 방식”이 공존하면, 모델에 입력되는 컨텍스트 자체가 모순적이다. 프롬프트와 스킬로 아무리 variance를 줄이려 해도, 컨텍스트가 variance를 생성하는 원천이 된다. 이것이 context pollution의 가장 극단적인 형태다.
결론 — 도구보다 환경이 먼저다
AI로 모든 것을 혁신하고 앞당길 수 있다고 생각했다. 결과는 반쯤 성공이었다.
성공한 부분은 명확하다. 체계적으로 관리되지 못하던 영역에 AI로 새 시스템을 구축했다. 실패한 부분도 명확하다. 레거시 시스템에서 AI 기반으로 빠르게 feature를 개발하겠다는 기대는 현실의 벽에 부딪혔다.
반년간의 시행착오에서 배운 가장 중요한 교훈은 이것이다. AI를 도입할 때 가장 먼저 해야 할 질문은 “이 도구가 얼마나 똑똑한가”가 아니라 “이 환경의 컨텍스트가 얼마나 정리되어 있는가”다.
환경이 일관되면 — 컨벤션이 통일되어 있고, 패턴이 예측 가능하고, 문서가 최신 상태이면 — 도구 몇 개로 variance를 충분히 줄일 수 있다. 환경이 혼란스러우면 — 레거시와 신규가 뒤섞이고, 컨벤션이 파편화되어 있고, “왜 이렇게 했는지” 아무도 모르면 — 도구를 아무리 쌓아도 모델은 흔들린다. Garbage in, garbage out은 LLM 시대에도 여전히 유효하다.
결국 세 가지가 균형을 이뤄야 한다.
모델에 대한 이해 — LLM이 확률 박스임을 인정하고, 그 확률을 조정하는 메커니즘(prompting, skill, hook, harness)의 원리와 한계를 아는 것.
적용 환경에 대한 이해 — 이 환경이 greenfield인지 brownfield인지, context pollution의 수준은 어떤지, 모델이 참조할 컨텍스트의 일관성은 어떤지를 파악하는 것.
Middle layer의 설계 — 위의 두 이해를 바탕으로, 모델과 환경 사이에 어떤 도구를 어떤 순서로 배치할지를 결정하는 것. 얼마나 혁신을 추구할지, 얼마나 기존 패턴을 존중하고 점진적으로 바꿔갈지 — 이 큰 그림을 그리는 능력이 앞으로 AI와 함께 일하는 사람에게 가장 중요한 역량이 될 것이다.
댓글 남기기