
AI가 제1의 작성자가 된다면, 프로그래밍 언어의 설계 원리는 반전된다
요약
AI가 프로그래밍의 주체가 될 때 변화하는 언어 설계 원리를 다룹니다. 인간 중심의 '작성 편의성' 대신 AI 중심의 '검증 가능성'과 '국소성'을 극대화하는 설계 방향을 제시합니다.
핵심 포인트
- AI 시대에는 작성 비용보다 검증 및 문맥 파악 비용이 더 중요함
- 장황하더라도 모호함을 제거하여 AI의 추론 오류를 방지해야 함
- 에러 메시지는 AI가 즉시 처리할 수 있는 구조화된 데이터 형태여야 함
- 추론의 국소성을 보장하여 AI가 파일 단위로 명확히 이해하게 설계해야 함
2026년 6월 9일, Claude Fable 5가 출시되었다.
자신의 능력의 한계를 명확히 넘어선 도구였다. Anthropic은 당초 6월 22일까지 구독을 통해 이 모델을 사용할 수 있다고 공지했다. 시간이 충분하다——그렇게 생각하고, 평소라면 절대 시도하지 않을 실험을 던져보기로 했다.
예를 들어, 프로그래밍 언어를 처음부터 만든다거나 하는 것 말이다.
결국, 그 시간은 주어지지 않았다. Fable 5는 출시 불과 3일 만에 "너무 강력하다"는 이유로 중단되었다. 22일은커녕, 12일에 사라졌다. 남겨진 것은 그 3일 동안 탄생한 Kei라는 언어였다.
하지만 사라져도 상관없었다. 설계——사상(思想)의 골격, 무엇을 보장하고 무엇을 버릴 것인가에 대한 판단, 트레이드오프(Trade-off)의 풀이——는 Fable 5가 손안에 있을 때 이미 굳혀두었기 때문이다. 가장 발산하기 쉽고 가장 어려운 부분을, 한계를 초월한 도구로 단번에 수렴시켰다. 도구가 사라진 뒤에 남은 것은 수렴된 설계도였다. 나머지는 그것을 Opus에 넘겨 구현으로 옮기고 파생시키기만 하면 된다. 어려운 판단은 강력한 도구로, 그 전개는 견고한 도구로.
기묘하게도 그것은 Kei가 언어로서 체현하고자 했던 분업——어려운 판단은 누군가가 결정하고, 구현은 다른 작성자가 이어받는다——그 자체였다. 나중에 깨달았지만, 필자는 이 언어를 만들면서 그 언어의 사상을 자신의 작업 흐름 속에서 먼저 실천하고 있었던 셈이다.
이 기사는 그 언어 자체에 대한 홍보가 아니다. 만드는 과정에서 필자가 붙잡은 하나의 질문——"AI가 제1의 작성자가 되었을 때, 프로그래밍 언어의 설계 원리는 어떻게 변하는가"——에 대한 기록이다.
기존의 언어는 전부 "인간은 타이핑을 싫어한다"를 전제로 하고 있다
잠시 멈춰서 생각해 보길 바란다. 우리가 매일 사용하는 언어 기능의 상당수는 하나의 전제로부터 역산되어 있다. 인간은 쓰는 것이 귀찮다는 전제다.
타입 추론(Type Inference)은 "일일이 타입을 쓰고 싶지 않다"에서 태어났다. 생략 표기법도, 암묵적 타입 변환(Implicit Type Conversion)도, 연산자 오버로딩(Operator Overloading)도 뿌리는 같다. "인간의 수고를 줄이는 것"에 최적화되어 있다. 이것은 옳다. 작성자가 인간인 한, 수고는 최대의 비용이다.
그런데 작성자가 AI가 되면 이 전제가 무너진다.
AI에게 쓰는 비용(토큰을 출력하는 것)은 거의 제로다. 장황한 기술을 마다하지 않는다. 오히려 AI가 고통받는 지점은 다른 곳에 있다. "이 코드가 맞는지 확인하는 비용"과 "문맥의 외부에 있는 무언가에 의존하고 있어 그 자리에서는 의미를 읽어낼 수 없는 코드"다.
즉, 작성자가 AI로 바뀌면 비용 구조가 통째로 뒤바뀐다. 수고는 저렴해지고, 검증과 국소성(Locality)은 비싸진다. 그렇다면 언어의 설계 원리도 그에 맞춰 반전시켜야 하지 않을까——이것이 Kei의 출발점이었다.
반전시키면 이렇게 된다
인간을 위한 최적화를 버리고 검증 가능성, 추론의 국소성, 에이전트 루프(Agent Loop)와의 친화성에 올인하면 설계 판단은 다음과 같이 변한다.
장황하더라도 모호함을 제로로 만든다. 토큰은 싸다. 모호함은 비싸다. 암묵적 타입 변환도, 암묵적 import도, 연산자 오버로딩도 두지 않는다. 한 글자라도 짧게가 아니라, 1mm의 의심도 없이.
에러는 구조화된 데이터(Structured Data)를 정답으로 삼는다. 인간을 위한 산문 메시지는 파생물에 불과하다. AI에게 가치가 있는 것은 위치, 원인, 수정 후보가 기계 판독 가능한 JSON으로 반환되는 것이다. 생성→검증→수정 루프의 대역폭이 곧 언어의 가치가 된다.
추론의 국소성을 사양(Specification)으로 보장한다. 한 파일의 동작은 그 파일과 명시적인 import만으로 결정된다. 재수출(Re-export) 금지, 글로벌 가변 상태 없음. AI가 "이 함수, 어딘가 먼 곳의 상태에 의존하고 있지 않은가?"라고 의심할 필요가 없게 만든다.
정규형(Normal Form)을 하나로 고정한다. 같은 의미의 코드는 항상 같은 모습으로 정렬된다. 스타일 논쟁을 사양으로 종결시킨다. 차이점(Diff)이 항상 의미론적이 된다.
인간이 이것을 손으로 쓴다면 아마 미쳐버릴 것이다. 장황하고, 선언투이며, 지름길이 전혀 없다. 하지만 쓰는 것은 AI다. 그러므로 문제없다.
인간은 무엇을 읽는가
여기서 당연한 의문이 생긴다. AI에게 전부 쓰게 한다면 인간의 일은 무엇이 남는가.
Kei의 답은, **"인간은 구현(body)을 읽지 않는다. 계약(Contract)을 읽는다"**이다.
func withdraw(account: AccountId, amount: Money) -> Result<Money, WithdrawError>
uses Database.Read, Database.Write
requires amount > Money.zero
...
주목해야 할 점은 함수의 시그니처(Signature)에 세 종류의 '조항'이 실려 있다는 것이다.
uses
는 권한 조항 (Permission Clause). 이 함수는 DB를 읽고 쓰며, 그 외의 외부 세계에는 관여하지 않는다고 AI가 선언한다. 선언에 없는 이펙트(Effect, 예: 네트워크 액세스)를 본체에서 사용하면 컴파일 에러(Compile Error)가 발생한다. -
requires
는 호출 측의 의무. amount는 양수여야 한다는 것. -
ensures
는 구현 측의 약속. 이 함수가 세계에 대해 보증하는 것.
인간이 리뷰하는 것은 이 세 줄로 충분하다. "DB만 건드린다, 입력은 양수, 결과는 이렇게 된다" —— 이것에 서명(승인)할 수 있다면, body의 내용은 AI에게 맡겨도 된다. 리뷰의 단위가 구현에서 계약(Contract)으로 압축된다.
필자는 이 언어의 태그라인(Tagline)을 다음과 같이 정했다.
Code is a 契.
「契(계)」는 언어 이름인 Kei (契의 음독)의 유래이기도 하다. 코드란 인간과 AI가 주고받는 합의서다. 읽을 수 없는 합의서에 사인을 요구하는 것은 사기지만, 계약 조항만 명시되어 있다면 사람은 안심하고 서명할 수 있다.
새로운 언어의 사인(死因)과 그 회피
여기까지는 사상에 관한 이야기다. 하지만 사상뿐이라면 누구나 말할 수 있다. 새로운 언어에는 사상과는 별개로, 훨씬 더 현실적이고 냉혹한 사인(死因)이 존재한다.
학습 데이터(Training Data)가 존재하지 않는다는 것이다.
새로운 언어는 AI의 학습 데이터에 포함되어 있지 않다. 그래서 AI는 쓸 수 없다. 쓸 수 없으니 아무도 사용하지 않는다. 사용되지 않으니 데이터가 늘어나지 않는다 —— 이 악순환으로 인해 대부분의 새로운 언어는 태어나는 순간 막다른 길에 다다른다. AI가 작성자의 중심이 된 시대에는 이 사인이 오히려 더 심각해졌다.
Kei의 도박은 바로 여기에 있었다. "학습 데이터가 없더라도, 취급 설명서(Skill)를 잘 만들어 놓으면 AI는 추론(Reasoning)을 통해 쓸 수 있지 않을까" 하는 점이다. 문법을 암기할 필요는 없다. 올바른 문법을 찾아낼 수 있고, 틀린 부분을 즉시 지적받는 환경이 있다면 쓸 수 있을 것이라고 믿었다.
이를 검증하기 위해 한 가지 실험을 진행했다. Kei를 전혀 학습하지 않은 에이전트(Agent)에게 Kei의 설명서(Skill)만을 건네주고, "도서관 대출 시스템을 작성하라"고 지시했다. 문법은 일절 가르쳐주지 않았다. "외부 스토리지에 기록할 것", "실패 이유가 타입(Type)으로 전달되도록 할 것"과 같은 자연어 요구사항만을 전달했다.
그 결과, 에이전트는 단 한 번의 지시로 검증을 통과하는 코드를 작성해냈다. 일부를 발췌하면 다음과 같다.
func borrowBook(memberId: MemberId, bookId: BookId) -> Result<Loan, BorrowError>
uses Clock, Database.Read, Database.Write
{
...
"외부 스토리지에 기록한다"라는 일본어 요구사항을 에이전트는 스스로 uses Clock, Database.Read, Database.Write라는 권한 조항으로 번역했다. "찾지 못할 수도 있는 취득"은 Option으로, "명확한 실패 이유"는 Result로, 타입을 구분해서 사용하기도 했다. 아무도 문법을 가르쳐주지 않았는데도 말이다.
더욱이 필자가 감탄한 점은 에이전트가 계약을 순수 함수(Pure Function)로 분리해냈다는 것이다. "재고가 정확히 1 감소한다"라는 수량적인 약속을 부작용(Side Effect)이 있는 borrowBook 본체에 직접 쓰지 않고, 순수한 헬퍼 함수(Helper Function)의 ensures로 넘겼다.
func decrementAvailable(available: Int) -> Int
requires available > 0
ensures result == old(available) - 1
...
이는 Kei의 사양(계약식은 부작용 금지)을 정확히 이해하고 있지 않으면 내릴 수 없는 설계 판단이다. 설명서를 읽었을 뿐인 에이전트가 그 정도까지 파악하고 있었던 것이다.
학습 데이터의 부재는 설명서의 완성도로 메울 수 있다. 적어도 이 사례에서는 도박이 성공했다.
같은 산을 다른 루트로 오르고 있던 사람이 있었다
이 설계를 진행하던 중, 필자는 자신과 거의 동일한 사상을 가진 언어가 이미 세상에 존재한다는 것을 알게 되었다. 형식 검증(Formal Verification)을 갖춘 "에이전트 퍼스트 언어(Agent-first Language)"로서, 계약을 코드에 담고 컴파일러가 에이전트용 구조화된 출력(Structured Output)을 내뱉는 —— 컨셉의 핵심이 소름 끼칠 정도로 일치했다.
처음에는 낙담했다. 하지만 지켜보면서 생각이 바뀌었다.
그 언어가 목표로 하는 것은 시스템 프로그래밍 (System Programming) 영역이다. C 언어적인 프리미티브 타입 (Primitive Type)을 가지며, 수학적인 증명을 본격적으로 수행하고, 제네릭 (Generics)이나 클로저 (Closures)는 검증 범위를 좁게 유지하기 위해 의도적으로 덜어냈다. 「정확성을 증명하는 것」에 몰두한, 연구 중심의 시스템 언어다.
반면, 필자인 Kei가 목표로 하는 것은 정반대였다. TypeScript로 트랜스파일 (Transpile)되어 Web이나 Edge에서 동작하며, 업무 도메인을 타입 (Type)으로 묶는 실무 언어. 증명은 미래의 숙제로 남겨두고, 우선은 런타임 어설션 (Runtime Assertion)으로 실용성을 취한다.
같은 「AI 시대의 검증 가능한 언어」라는 산을, 한쪽은 형식 기법 (Formal Methods)의 북벽에서, 다른 한쪽은 Web 실무의 남벽에서 오르고 있었다. 산은 같지만 루트는 다르다. 독립된 두 사람이 같은 산을 발견했다는 사실은, 오히려 이 문제 설정이 진짜임을 보여주는 방증이었다. 아마추어의 막연한 생각은 아니었다는 뜻이다.
(참고로 이 과정에서 언어 이름은 두 번이나 사라졌다. 첫 번째 후보는 기존의 블록체인 언어와 충돌했고, 다음 후보는 앞서 언급한 선행 언어와 완전히 동일한 이름이었다. 이름을 사랑하기 전에 네임스페이스 (Namespace)를 확인하라는 교훈을, 필자는 두 번의 대가를 치르며 배웠다.)
아직 해결되지 않은 것
솔직하게 써두겠다. 이 실험이 Kei가 완성되었음을 의미하지는 않는다. 오히려, 구멍을 하나 찾아낸 것에 가깝다.
앞서 언급한 도서관 시스템에서, 에이전트가 작성한 borrowBook에는 함수 전체로서의 ensures가 없었다. 「이 함수를 호출한 결과, 해당 도서의 재고가 정확히 1 감소한다」라는 사후 조건 (Post-condition)은 순수 헬퍼 (Pure Helper)의 계약 (Contract)으로는 표현되어 있었지만, borrowBook 자체의 계약으로는 작성되어 있지 않았다.
이것은 에이전트의 태만이 아니다. Kei의 사양 (Specification)에 아직 작성할 수단이 없는 것이다. 이펙트 (Effect)를 가진 함수의 사후 조건에서, 외부 스토리지 (Storage)의 상태 변화(old(재고)와 새로운 재고의 관계)를 어떻게 참조하고 어떻게 계약할 것인가 —— 그 부분이 설계되어 있지 않다.
검증을 통과한 것(kei check가 에러 0을 반환한 것)과, 올바른 것은 별개다. 작성되지 않은 계약은 검사되지 않는다. 도그푸딩 (Dogfooding) 실험의 진짜 수확은 「작성할 수 있었다」라는 성공이 아니라, 「이펙트와 계약의 경계에 아직 언어화되지 않은 영역이 존재한다」라는 발견이었다. 이것은 다음 버전으로 넘길 숙제가 될 것이다.
되묻기
필자가 3일 동안 얻은 것은 완성된 언어가 아니라, 하나의 관점이었다.
작성자가 인간에서 AI로 옮겨갈 때, 언어는 「쓰기 쉬움」을 최적화하는 도구에서 「검증하기 쉬움」과 「합의하기 쉬움」을 최적화하는 도구로 설계의 무게 중심을 옮긴다. 코드는 인간이 기계에게 명령하기 위한 문장이 아니라, 인간과 AI가 서로의 책임 범위를 정하는 합의서가 된다.
당신이 평소 사용하는 언어의 기능 중, 어떤 것이 「인간은 쓰기 번거롭다」라는 전제에서 비롯된 것일까? 그 전제를 제거했을 때, 무엇이 남고 무엇이 불필요해질까?
AI가 제1의 작성자가 되는 시대에, 당신의 언어관은 어떻게 업데이트될 것인가? 필자는 아직 그 질문의 입구에 막 섰을 뿐이다.
Kei는 아직 v0.1 구현 단계에 있는 실험적인 언어입니다. 이 글은 「AI 시대의 언어 설계는 어떠해야 하는가」라는 질문을 공유하기 위한 것이며, Kei의 사용을 권장하는 것이 아닙니다. 같은 질문에 흥미를 느끼신 분들과 설계에 관한 논의를 할 수 있다면 기쁘겠습니다.
Discussion

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