본문으로 건너뛰기
cd /blog

언어 재귀적 자기 개선: 약 280개 언어에 걸친 코드 인텔리전스 갈아내기

[아키텍처][언어][에이전트]

> 우리는 약 280개 언어에 대한 코드 인텔리전스를 지원합니다. 사람이 이를 일일이 검수할 수는 없습니다. 그래서 우리는 언어 재귀적 자기 개선 루프 — 무작위 점검, LLM 판정, 한 가지 수정, 재검증 — 를 만들었고, 추출이 단순히 초록불(green)이 아니라 실제로 옳아질 때까지 격리된 에이전트 플릿으로 이를 실행합니다.

이 글의 수치는 게시 시점(2026년 5월) 기준입니다. 최신 수치는 팀 페이지를 참고하세요.

Maguyva는 약 280개 언어의 소스 코드에서 심볼, 참조, 의존성 그래프를 추출합니다. 각 언어는 커스텀 tree-sitter 핸들러 — 쿼리, 휴리스틱, 엣지 케이스 — 로 이루어져 있으며, 모든 핸들러는 저마다의 방식으로 미묘하게 틀릴 수 있습니다. 메서드 호출이 읽기(read)로 잘못 표기되는 경우. 함수가 잘못된 감싸는 스코프에 귀속되는 경우. 실제로는 존재하지 않는 관계가 만들어지는 경우.

이런 것들은 일일이 검수할 수 없습니다. 어떤 팀도 280개 문법 전체의 추출 결과를 읽고 나쁜 엣지를 짚어낼 수는 없습니다. 그래서 흥미로운 질문은 “우리 추출이 정확한가”가 아니라 “이 정도 규모에서 모든 루프에 사람이 개입하지 않고도 어떻게 틀렸다는 것을 알아낼 것인가”입니다. 우리의 답은 언어 재귀적 자기 개선입니다. 언어 에이전트가 주도하는 품질 루프, 판정자 역할을 하는 LLM, 그리고 우리가 계속 다시 배우는 하나의 규칙입니다. 초록불이 곧 정답은 아니라는 것이죠.

초록불이 곧 정답은 아니다

모든 언어는 픽스처(fixture) 스위트를 갖고 있으며, 릴리스 게이트는 이를 정확도, 구조적 무결성, 완전성, 품질, 성능이라는 다섯 가지 차원에서 채점합니다. 언어는 픽스처에서 정밀도 ≥ 0.95, 재현율 ≥ 0.99, F1 ≥ 0.97을 만족하고 통계적 신뢰를 위한 예상 엣지가 최소 20개 이상일 때만 GREEN이 됩니다. 그 밑으로는 YELLOW나 RED이며, 출시되지 않습니다.

그 게이트는 필요조건이지 충분조건은 아닙니다. 픽스처는 우리가 작성한 픽스처를 기준으로 검증됩니다. 즉 우리가 이미 생각해낸 케이스들을 담고 있을 뿐입니다. 핸들러는 자신의 픽스처에서는 완벽하면서도, 실제 코드에서만 나타나는 패턴 — 매크로 관용구, 제네릭 바운드 메서드, 아무도 픽스처를 작성하지 않은 언어 기능 — 을 여전히 망가뜨릴 수 있습니다. GREEN은 픽스처를 통과했다는 뜻입니다. 실제 저장소가 깔끔하게 추출된다는 뜻은 아닙니다. 그래서 루프는 픽스처를 뒤로하고 야생을 들여다봐야 합니다.

내부 루프: 무작위 점검, 판정, 수정, 증명

핵심 루프는 한 번에 한 언어씩 실행됩니다.

        ┌──────────────────────────────────────────────────────────┐
        │                                                          │
        ▼                                                          │
  1. corpus run ── clone real-world repos, extract relationships   │
        │                                                          │
        ▼                                                          │
  2. spot-check 100 edges (seed 42, then seed 123 to cross-check)  │
        │                                                          │
        ▼                                                          │
  3. LLM judge classifies every sampled edge:                      │
        CORRECT · FALSE_POSITIVE · TYPE_ERROR ·                    │
        SCOPE_ERROR · METADATA_ERROR                               │
        │                                                          │
        ▼                                                          │
  4. fix ONE thing — handler .py, .scm query, or config           │
        │                                                          │
        ▼                                                          │
  5. re-validate — F1 + re-classify + manifest diff (no regressions)│
        │                                                          │
   better? ──no──► revert, try a different fix ────────────────────┤
        │ yes                                                       │
        ▼                                                           │
  6. promote the fix into fixtures (a permanent regression guard) ──┘

이것이 헛돌지 않고 실제로 작동하게 만드는 몇 가지 요소가 있습니다.

판정자는 API 호출이 아니라 에이전트 자신입니다. “LLM 판정”이라고 할 때, 이는 언어 에이전트 스스로가 샘플링된 각 엣지를 실제 소스와 대조하며 읽고, 고정된 5단계 분류 기준으로 분류한다는 뜻입니다. 이 엣지는 올바른가, 거짓양성인가, 관계는 맞지만 타입이 틀렸는가, 잘못된 스코프에 붙었는가, 아니면 잘못된 메타데이터를 담고 있는가? 이 채점 기준이 게임의 전부입니다. “오류율 23%“라는 말은 그것이 실제 결함인지 판정자의 오산인지 알기 전까지는 무의미합니다.

한 가지를 고치고, 그다음 증명하라. 매 반복은 정확히 하나의 편집 가능한 자산만 변경한 뒤, 고정된 하니스를 다시 실행하고, F1이 개선되고 재분류 결과가 더 나아 보일 때만 그 변경을 유지합니다. 그렇지 않으면 되돌립니다. 투기적인 수정을 한꺼번에 몰아넣거나 “더 나아질 것 같다”는 식은 없습니다. 변경은 스스로 자리를 증명하거나 사라집니다. 그리고 수정이 정착되면 픽스처 스위트로 승격됩니다. 그렇게 하면 그 수정이 고친 버그는 조용히 다시 돌아올 수 없습니다. 바로 이 승격 단계가 루프를 단순한 반복이 아니라 재귀적으로 만드는 부분입니다. 매 회차가 다음 회차가 검증할 기준(오라클)을 더 단단하게 만듭니다.

우리가 계속 다시 배우는 교훈: 지표는 과잉 보고한다

여기 함정이 있고, 우리는 그 함정에 그대로 걸어 들어갔습니다. 2차적인 코퍼스 지표들 — 추출된 대상이 해결 가능한 심볼을 갖지 못하는 빈도, 얼마나 많은 심볼이 “고아”처럼 보이는지 등등 — 은 문제를 크게 과잉 보고합니다. 이들은 대부분 버그가 아니라 패러다임의 부산물입니다.

가장 명확한 예: llvm는 한때 “심볼 없는 소스” 비율이 73%로 나타나 재앙 수준으로 낙인찍힌 적이 있습니다. 파고들어 보니 실제 정확도는 **98.5%**였습니다. “누락된 심볼”의 거의 전부는 정당한 외부 참조 — 표준 라이브러리, 프레임워크, 저장소 밖에 존재하는 코드로의 호출 — 였습니다. 그 지표는 핸들러의 결함이 아니라 언어 자체의 속성을 측정하고 있었던 것입니다. Zig, COBOL, Odin 같은 언어는 65~70%의 “고아” 비율을 보이면서도 완전히 정확합니다. COBOL은 실제 오류가 0건이었습니다.

만약 그 수치들이 작업을 이끌게 두었다면, 우리는 이미 옳았던 핸들러를 “고치는” 데 몇 주를 쓰면서 조용하지만 진짜인 버그가 있는 언어들은 무시했을 것입니다. 결론은 단호합니다. 집계 지표는 기껏해야 대략적인 분류(triage) 신호일 뿐입니다. 진짜 품질 신호는 엣지 분류를 곁들인 무작위 점검입니다. 실제 저장소의 실제 엣지들을 하나하나 살펴보고 판정하는 것이죠. 직관보다 데이터를 우선하되, 어떤 데이터가 진실을 말하고 있는지 알고 난 뒤에야 그렇습니다.

외부 루프: 마라톤이 아니라 플릿

280개 언어를 한 번에 하나씩 처리한다면 영원히 끝나지 않을 것입니다. 그래서 내부 루프는 여러 언어를 병렬로 실행하는 외부 루프로 감싸여 있습니다.

   pick a wave of near-GREEN / high-error languages


   fan out 10–15 agents, each ISOLATED in its own git worktree,
   each grinding ONE language, committing to its own branch


   orchestrator integrates serially: file-scoped apply, then
   `manifest diff` — any cross-language regression blocks the batch


   gated push (reviewed and confirmed) ──► rotate to the next wave

각 에이전트는 서로를 밟지 않도록 일회용 워크트리에서 작업합니다. 오케스트레이터는 이들의 수정 사항을 한 번에 하나씩 통합하며, 매번 전체 매니페스트 리그레션 체크를 거칩니다. 자기 언어에는 도움이 되지만 다른 세 언어를 조용히 망가뜨리는 변경은 반영되지 않습니다. 통합은 무언가가 푸시되기 전에 게이트를 거치고 확인됩니다. 리그레션 게이트는 무엇이 안전한지를 결정하고, 무엇이 출시되는지는 여전히 사람이 결정합니다. 그런 다음 풀(pool)은 다음 언어 집합으로 순환하고, 전체 과정이 다시 실행됩니다.

아직 완벽하지 않은 것들

판정자도 틀릴 수 있고, 그 틀림에는 방향성이 있습니다. 컨텍스트가 너무 적은 상태로 실행되는 에이전트는 과잉 보고하는 경향이 있습니다. 한 배치에서는 8개 언어가 5~20%의 오류율로 플래그되었지만, 살펴보니 실제 언어별 버그는 단 하나였습니다. 나머지는 그 언어 고유의 의미론을 놓친 판정자의 실수였습니다(한 줄의 소스가 정당하게 여러 엣지를 만들어내는 경우, 파라미터 바인딩이 대입으로 모델링되는 경우, 식별자마다 참조가 생기는 언어 등). 그래서 우리는 두 개의 시드로 샘플링하고 교차 검증하며, 판정자와 픽스처 사이의 불일치를 확정된 판결이 아니라 가장 흥미로운 신호로 취급합니다. 때로는 픽스처 쪽이 틀린 것일 수도 있으니까요.

우리는 또한 목표에 대해 솔직합니다. 목표는 명백히 실제 오류 0건입니다. 하지만 “0”은 언어별로 조금씩 갈아나가는 방향일 뿐, 한 번에 체크되는 항목이 아닙니다. 늘 또 다른 관용구를 가진 또 다른 저장소가 있으니까요.

주장하는 것이 아니라 증명해내는 것

Maguyva가 에이전트를 위해 하는 모든 일 — 심볼 찾기, 의존성 추적, 인용된 코드로 질문에 답하기 — 은 그 아래 깔린 추출이 옳다는 전제 위에 서 있습니다. 280개 언어에 걸쳐 “옳다”는 것은 주장할 수 있는 것이 아닙니다. 실제 코드를 상대로 끊임없이 증명해내야 하는 것입니다. 이 루프가 바로 우리가 그것을 증명하는 방법입니다. 자기 지표를 의심하고, 모든 변경을 증명하며, 각 수정을 다음 리그레션에 대한 보호막으로 바꾸는 자율적인 무작위 점검-수정 순환입니다. 화려하지 않습니다. 하지만 우리가 “당신의 언어를 지원합니다”라고 말하고 그 말을 진심으로 할 수 있게 해주는 작업입니다. 초록불은 쉽습니다. 정답은 증명해내야 합니다.

관련 글

Maguyva 빌드 로그의 다른 글들