본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 31. 20:17

브라우저에서 실제 GitHub 관리자 업무를 수행하는 작은 로컬 모델 — 그리고 그 이면의 패턴

요약

브라우저 환경에서 0.5~7B 규모의 소형 모델로 GitHub 관리 업무를 수행하는 Macrokit 프로젝트를 소개합니다. 복잡한 추론을 모델에 맡기는 대신, 워크플로우를 결정론적인 도구 호출 시퀀스로 인코딩하여 약한 모델의 한계를 극복하는 구조적 접근법을 제안합니다.

핵심 포인트

  • 브라우저 내 로컬 실행으로 API 키나 서버 없이 GitHub 업무 수행 가능
  • 약한 모델의 추론 능력을 높이는 대신 런타임 추론 요구사항을 제거하는 전략
  • 반복되는 워크플로우를 결정론적 도구 호출 시퀀스로 인코딩하여 신뢰성 확보
  • 데이터 프라이버시와 비용 효율성을 동시에 해결하는 구조적 설계

제작자 공개: 저는 Macrokit (Apache-2.0, 완전 오픈 소스)를 개발했습니다. 이 포스트는 패턴을 설명하기 위한 것이지 홍보가 아닙니다 — 구매할 것은 없습니다. 링크는 마지막에 있으며, 데모는 키(key)가 필요 없고 전적으로 귀하의 브라우저에서 실행되므로, 귀하의 네트워크 탭에서 모든 주장을 직접 확인할 수 있습니다.

링크를 하나 열면, 브라우저 내에서 실행되는 약 0.5~7B 규모의 모델이 — 가입도, API 키도, 서버도, 설치된 것도 없이 — 프론티어 모델 (Frontier model)이 필요할 것이라고 생각되는 GitHub 관리자 업무를 수행합니다: 공개 저장소의 최신 PR (Pull Request) 분류, 레이블 제안, 열린 이슈 (Open issues) 요약 등입니다. 실행 중에 네트워크 탭을 열어보면 유일한 외부 트래픽은 모델 가중치 (Model weights)를 한 번 다운로드하는 것과 공개 GitHub 읽기 작업뿐임을 확인할 수 있습니다. 추론 서버 (Inference server)는 없습니다. 제 것이든 귀하의 것이든 키도 필요 없습니다.

그 데모는 속임수가 아니며, "약한 모델이 비밀리에 GPT만큼 똑똑하다"는 뜻도 아닙니다. 그것은 _추론이 어디에서 일어나는가_에 대한 구조적인 선택입니다. 전체 아이디어는 다음과 같습니다.

모두가 시작할 때 직면하는 강제된 선택

오늘날 LLM (Large Language Model) 앱을 배포한다면, 당신은 한쪽을 선택해야 합니다:

  • **프론티어 API 모델 (Frontier API models)**은 다단계 워크플로우 (Multi-step workflows)를 계획하고, 오류에서 복구하며, 지저분한 표면 데이터를 파싱합니다. 하지만 호출당 비용이 비싸고, 미국이 제어하는 API로의 네트워크 홉 (Network hop)이 필요하며, 데이터 거주성 (Data-residency) 규칙, 에어갭 (Air-gaps), 또는 제한된 예산 하에서는 시작조차 할 수 없습니다.
  • 약한 / 로컬 모델 (Weak / local models) (3B~14B 오픈 웨이트 (Open weights), Ollama/llama.cpp/MLX를 통한 온디바이스 (On-device))은 저렴하고, 프라이빗하며, 로컬에서 제어 가능하지만 — 다단계 추론 (Multi-step reasoning)에서는 무너집니다. 도구 (Tool)를 호출해야 할 때 산문 (Prose)으로 흘러가 버립니다. 도구 이름을 환각 (Hallucinate)합니다. 루프 (Loop)에 빠집니다. 첫 번째 오류에서 포기합니다.

기본적인 반응은 약한 쪽을 밀어붙이는 것입니다: 작은 모델이 더 잘 추론하도록 훈련시키고, 루프를 보조하는 에이전트 프레임워크 (Agent framework)로 감싸서, 지연 시간 (Latency)과 취약성 (Brittleness)을 감수하는 것입니다. 저는 이것이 대부분의 프로덕션 작업에 있어 잘못된 레버 (Lever)라고 생각합니다.

레버를 바꾸는 관찰

대부분의 프로덕션 LLM 워크플로우 (workflow)는 새로운 추론 문제를 다루지 않습니다. 그것들은 서로 다른 인자 (arguments)를 가질 뿐, 수천 번 반복되는 동일한 형태의 작업입니다 — 이것을 가져오고, 저것을 추출하고, 점수를 매기고, 라벨을 붙이는 식이죠. 어려운 점은 요청을 이해한 뒤 무엇을 할지 결정하는 것이 아닙니다. 진짜 어려운 점은 _단계별로 추론하여 그곳에 도달하는 것 (reasoning your way there step by step)_이며, 이것이 바로 약한 모델 (weak models)들이 신뢰성 있게 수행하지 못하는 바로 그 부분입니다.

그러니 약한 모델이 더 잘 추론하도록 만들지 마세요. 런타임 (runtime) 추론 요구 사항을 제거하십시오.

강력한 모델이 이미 알려진 표면 위에서 단계별 추론을 통해 해결할 수 있는 모든 워크플로우는, 결정론적이고 매개변수화된 도구 호출 (tool calls) 시퀀스로 한 번 인코딩 (encode)될 수 있습니다. 그 이후의 _실행 (executing)_은 의도 분류 (intent classification)만을 필요로 하며, 이는 작은 모델들도 충분히 잘 처리할 수 있는 원샷 라우팅 (one-shot routing) 문제입니다.

그 인코딩된 시퀀스가 바로 **매크로 (macro)**입니다. 이는 작업을 두 가지로 나눕니다:

  • 설계 시간 (Design time, 오프라인, 드물게 발생): 개발자의 감독 하에 이미 사용 중인 코딩 에이전트 (coding agent)를 사용하는 강력한 모델이 워크플로우를 한 번 해결하고 매크로를 작성합니다. 버전 관리가 가능하고, 검토 가능하며, 결정론적입니다. 추론 비용은 약 0.50달러 정도이며 한 번만 발생합니다.
  • 런타임 (Runtime, 온라인, 지속적으로 발생): 약하거나 로컬에서 돌아가는 모델이 요청을 받고, 그것이 어떤 매크로에 매핑되는지 분류한 뒤, 추출된 인자들과 함께 매크로를 호출합니다. 매크로는 일반적인 테스트 완료된 코드로서 실행됩니다. 모델은 워크플로우를 계획하지 않습니다.

비용의 비대칭성이 핵심입니다: 프런티어 모델 (frontier model)로 한 번 인코딩하고, 비용이 약 1/100 ~ 1/1000 수준이며 노트북에서도 돌아가는 모델로 수천 번 실행하십시오. 그러면 해당 워크플로우에 대해서는 모델 간의 능력 격차가 더 이상 중요하지 않게 됩니다.

매크로의 실제 정체

프롬프트 템플릿 (prompt template)도 아니고, 캐시 (cache)도 아닙니다. 다섯 가지 부분으로 구성된 매개변수화된 프로그램입니다: 라우터가 대조할 의도 명세 (intent spec), 타입이 지정된 인자 스키마 (typed argument schema), 결정론적인 핸들러 (코드 내의 실제 도구 호출 시퀀스), 구조화된 실패 계약 (structured failure contract), 그리고 테스트 픽스처 (test fixtures)입니다.

defineMacro({
  name: "triage_arxiv_paper",
  intent: "summarize and classify an arXiv paper by its ID or URL",
...

런타임(Runtime) 시 모델은 _"triage 2401.12345, I care whether the method is new"_를 보고 정확히 하나의 호출을 생성합니다:

{ "tool": "triage_arxiv_paper", "args": { "paperId": "2401.12345", "classifier": "method" } }

모델은 가져오기(fetch), 추출(extract), 점수 매기기(score)를 순차적으로 결정하지 않습니다. 그 시퀀스는 오프라인(offline)에서 인코딩되었습니다. 모델은 오직 라우팅(routing)만 수행합니다. (조합(Composition) 또한 매크로입니다. 만약 워크플로가 "A를 실행하고, 그다음 B, 그다음 C를 실행하라"라면, 이는 세 번의 라우터 턴(router turns)이 아니라 하나의 매크로 run_full_pipeline입니다. 세 번의 라우터 턴은 뒷문으로 수행되는 런타임 추론(reasoning-at-runtime)입니다.)

제가 실제로 참신하다고 생각하는 부분: 증류 게이트 (distillation gate)

매크로 라이브러리는 사람들이 실제로 실행하는 워크플로를 충분히 포괄할 수 있을 때에만 유용합니다. 대부분의 도구 모음은 유기적으로 성장하다가 부패합니다. 매 세션마다 일회성 헬퍼(helper)가 추가될 뿐, 어떤 세션도 이를 통합하지 않기 때문입니다.

해결책은 도구에 의해 강제되는 규율입니다:

기존 매크로가 없는 워크플로를 사용하는 모든 세션은 종료하기 전에 반드시 매크로를 인코딩해야 한다.

CLI는 세션 로그를 읽고, 인코딩되지 않은 워크플로에 대한 가공되지 않은 도구 호출(raw tool calls)을 발견하면 빌드를 실패 처리합니다:

$ macrokit gate
Session 2026-05-24T14:02Z used 4 raw tool calls for an unmacro'd workflow:
  → fetch_user_profile(id=…)
...

런타임은 단순한 엔지니어링입니다. 게이트(gate)는 문화적인 요소입니다. 이를 CI(지속적 통합)에 연결하면, 여러분의 라이브러리는 헬퍼들의 무덤이 되는 대신 시스템을 사용하는 속도에 맞춰 복리로 성장합니다. 이것이 에이전트 프레임워크(agent frameworks)나 RPA 라이브러리가 성공하지 못한 곳에서 이 패턴이 복리로 성장할 것이라고 믿는 이유입니다.

정직한 지표: 53.5% → 94.5%

저는 실행 전(Qwen 2.5 7B, 4-bit, 16GB MacBook 환경)에 100개의 태스크로 구성된 의도 라우팅 (intent-routing) 벤치마크를 사전 등록했습니다. 첫 번째 실행 결과는 **53.5%**였습니다. 저는 그 수치를 공개했습니다. 모델은 거의 매번 올바른 매크로 (macro)를 선택했지만, 인자 이름 (argument names)을 틀렸습니다. 스키마 (schema)에는 {owner, repo, number}라고 명시되어 있었음에도 {repo_owner, repo_name, pr_number}를 출력한 것입니다. 근본 원인은 모델이 아니라 제가 만든 SDK의 버그였습니다. zod 스키마 (zod schemas)는 기본적으로 JSON 스키마 (JSON Schema)를 전달하지 않기 때문에, 라우터 (router)가 허용적인 {type: object}로 대체되었고 모델은 실제 인자 이름을 전혀 볼 수 없었습니다. 모델은 추측을 하고 있었던 것입니다.

해결 방법은 약 12줄의 코드 수정(defineMacro() 시점에 zod를 JSON 스키마로 변환)이었습니다. 동일한 모델, 동일한 코퍼스 (corpus)에서 결과는 94.5%, 구조적 실패는 0건이었습니다. 이 방법론은 헤드라인보다 더 설득력이 있습니다. 사전 등록 (pre-registration)은 바로 저와 같은 종류의 조용한 설정 누락을 잡아내기 위한 것입니다. 실패한 실행 결과는 수정된 결과 바로 옆에 공개되어 있습니다. 직접 테스트 하네스 (harness)를 다시 실행해 보셔도 좋습니다.

도움이 되지 않는 경우 (잘못 적용하지 않도록 주의하세요)

  • 진정으로 새로운 추론 (Genuinely novel reasoning) — "이 화난 고객에게 답장을 작성해줘", "완전히 새로운 카테고리의 가격을 책정해줘"와 같은 작업입니다. 이런 것들은 프런티어 모델 (frontier model)로 라우팅하세요. 하이브리드 라우팅 (Hybrid routing, 로컬 모델이 일상적인 80~90%를 처리하고 프런티어 모델이 나머지 새로운 작업을 처리하는 방식)은 선택 사항입니다.
  • 매번 변하는 워크플로우 (Workflows that change every time) — 탐색적 연구, 개방형 디버깅 (open-ended debugging) 등입니다. 인코딩할 내용이 없으므로, 이 패턴은 순수한 오버헤드 (overhead)가 됩니다. 가치는 실행 횟수 대비 인코딩 횟수의 비율에서 나옵니다.
  • 기저 환경이 계속 변하는 인터페이스 (Surfaces that change underneath you) — 제3자 UI 위에 구현된 매크로는 UI가 변경될 때 깨집니다. 이에 대한 완화 방법은 "자가 치유 (self-healing)"라는 주장 대신, CI에서 포착되는 명확하고 타입이 지정된 실패 (typed failures)와 DOM/액션 메뉴 추상화 (abstraction)를 구축하는 것입니다.
  • 매우 작은 모델 (Very small models) — 현재 기준으로 약 7B 규모의 인스트럭트 튜닝 (instruct-tuned) 모델이 진지한 배포를 위한 최저선입니다. 그 미만에서는 라우팅이 성공하는 것보다 실패 감지기가 작동하는 경우가 더 많습니다. 이 경험적 한계치는 계속 낮아지고 있습니다.

이것이 아닌 것

에이전트 프레임워크 (Agent framework)가 아닙니다 (에이전트 프레임워크는 더 나은 런타임 추론 (Runtime reasoning)을 두고 경쟁하지만, 이것은 추론을 제거합니다 — "생각하는 에이전트"가 아니라 "라우팅하는 에이전트"입니다). 모델이 아닙니다 (모델은 직접 가져와야 합니다 — OpenAI 호환 및 Ollama 즉시 사용 가능). RPA가 아닙니다 (매크로는 기록된 픽셀이 아니라 의미론적 도구 호출 (Semantic tool calls)입니다). 파인튜닝 (Fine-tuning) 파이프라인이 아닙니다. 노코드 (No-code)도 아닙니다 (작성을 위해 개발자와 강력한 모델이 필요합니다).

저는 최첨단 API (Frontier-API)에 실질적으로 접근할 수 없는 사용자들에게 서비스를 제공하는 별도의 운영 도구 내부에서 약 1년 동안 이 패턴을 프로덕션 환경에서 실행해 왔으며, 산업 분야에 구애받지 않는 핵심 기능을 Macrokit으로 추출해 냈습니다. 저에게 흥미로운 질문은 약한 모델이 최첨단 모델을 따라잡을 수 있느냐가 아니라, 여러분의 실제 업무 중 얼마나 많은 부분이 확인해 볼 필요조차 없을 정도로 반복적인가 하는 점입니다.

체험하기 / 읽어보기

실제 업무에서 이 방식이 어디서 무너지는지 진심으로 듣고 싶습니다 — 그것이 유용한 피드백입니다. 반론도 환영합니다.

— Cheng Qian

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0