Menu
Playground에서 시도하기

에이전트 우선 설계: Zero가 존재하는 이유와 거래하는 것들

Zero는 하나의 질문 위에 세워졌습니다. AI 에이전트를 처음부터 1급 사용자로 두면 프로그래밍 언어는 어떤 모습이 될까요? 그 원칙과 거래되는 것들을 정리했습니다.

Zero가 던지는 질문

Zero의 전제는 단순합니다. AI 에이전트가 — 사람뿐 아니라 — 코드를 읽고, 쓰고, 수정할 때 언어 _자체_는 어떤 모습이고 싶어 할까요?

기존 언어들은 에이전트가 코드를 쓰기 훨씬 이전에 설계되었습니다. 우선순위 — 간결한 문법, 풍부한 관용구, 라이브러리 영리함 — 는 에디터에 입력하는 사람에게 의미가 있습니다. 사람이 빈틈을 잘 메우기 때문에 모호함과 암묵적 변환을 견디죠. 에이전트는 그렇지 않습니다. 확률 분포에서 정확한 텍스트를 만들어 내고, 언어의 흐릿한 모서리마다 어딘가 잘못된 토큰으로 대가를 치릅니다.

Zero는 제약을 뒤집어 새로 시작합니다. 에이전트를 위해 먼저 설계하고, 사람이 그 코드를 읽을 거라는 사실을 받아들이고, 뭐가 나오는지 보는 거예요.

원칙 1: 작고 규칙적인 표면

대부분의 프로그래밍 언어는 시간이 지나며 자랍니다. 새 릴리스마다 작은 편의가 추가됩니다 — 새 연산자, 새 문법 형태, 언어가 이미 다루던 것을 표현하는 새 방법. 추가될 때마다 사람의 인체 공학으로 그 비용이 정당화되죠. 추가될 때마다 에이전트에게는 비용이 듭니다. 익혀야 할 변종이 또 하나, 잘못될 방법이 또 하나 생기는 거예요.

Zero는 의도적으로 표면을 작게 유지합니다.

  • 바인딩 형태 하나 (let).
  • 함수 형태 하나 (fun, 선택적으로 pub).
  • 오늘은 루프 하나 (while).
  • 곱타입 모델링 하나 (shape).
  • 페이로드를 가진 합타입 모델링 하나 (choice).
  • 라벨링된 합 모델링 하나 (enum).
  • 패턴 매칭 구조 하나 (match).

연산자 오버로딩 없음, 데코레이터 없음, 매크로 없음, 암묵적 변환 없음, 참/거짓 강제 변환 없음, 삼항 연산자 없음. 부재 하나하나가 기능입니다. 에이전트가 잘못된 변종을 고를 수 있는 자리를 없애 주거든요.

비용은 명백합니다 — 편의 기능이 줄어들죠. 이득은 한 세션 동안 Zero를 익히는 에이전트가 거의 동등한 일곱 가지 후보를 저울질하지 않고도 올바른 문법으로 수렴할 수 있다는 점입니다.

원칙 2: 명시적 효과

대부분의 언어는 어디서든 어느 함수든 I/O를 하게 둡니다. JavaScript의 console.log, C의 printf, Python의 print 같은 식이죠. 함수의 시그니처는 그것이 파일에 쓸지 네트워크를 칠지에 대해 아무 단서도 주지 않습니다. 알려면 본문을 재귀적으로 읽어야 해요.

Zero는 정반대 입장을 취합니다. 함수가 가진 모든 효과가 시그니처에 드러납니다.

  • I/O는 World 능력으로 통제됩니다. World를 받지 않는 함수는 I/O를 할 수 없습니다. 타입 시스템이 이를 강제해요.
  • 실패는 raisescheck로 통제됩니다. 실패할 수 있는 함수는 시그니처에 그렇게 말합니다. 모든 호출자는 check나 다른 명시적 구조로 그것을 인정합니다.

함수의 시그니처만으로, 에이전트(혹은 정적 분석기나 사람 리뷰어)가 깊이 신경 쓰는 두 질문에 답할 수 있어요.

  • "이게 바깥 세상에 닿을 수 있나?" — World가 등장하면 그렇다.
  • "이게 실패할 수 있나?" — raises가 등장하면 그렇다.

이 속성은 주류 언어에는 존재하지 않습니다. 그리고 작은 속성도 아니에요.

비용은 매개변수 배관입니다. World 값은 I/O가 필요한 곳마다 전달되고, raises 절은 에러가 흐르는 곳마다 반복됩니다. Zero는 그것을 그 속성의 값으로 받아들입니다.

원칙 3: 결정론적 도구

세 번째 원칙은 에이전트를 가장 직접적으로 겨냥합니다. 컴파일러가 만들어 내는 모든 출력이 구조화된 데이터라는 점이에요.

JSON 진단이 대표적인 예입니다.

{
    "code": "NAM003",
    "message": "unknown identifier",
    "line": 3,
    "repair": { "id": "declare-missing-symbol" }
}

세 가지 속성이 이걸 일반 컴파일러 에러와 다르게 만듭니다.

  1. 안정적인 코드. NAM003은 사람용 메시지가 어떻게 표현되든 오늘과 내일 같은 것을 뜻합니다.
  2. 구조화된 수정 계획. 컴파일러가 진단을 어떻게 수정할지 안다고 생각하면, 영문 제안이 아니라 데이터로서의 계획 — 편집 목록 — 을 내보냅니다.
  3. 여러 구조화된 채널. 진단, 의존성 그래프, 크기 리포트, 설명이 모두 --json 모드 뒤에 살아 있어요.

핵심은 도구 — 에이전트든 아니든 — 가 컴파일러 출력에 따라 행동하기 위해 영문을 파싱할 필요가 없다는 점입니다. 안정적인 코드를 조회하는 건 정확하고, 산문을 파싱하는 건 흐릿합니다. Zero는 전자를 계약으로, 후자를 사람을 위한 편의로 다룹니다.

원칙 4: 언어 안에 사는 라이브러리

에이전트는 기존 패턴을 따르는 코드 작성에 능합니다. 옵션의 바다에서 올바른 외부 의존성을 고르고, 올바르게 통합하고, API가 흘러가는 시점을 추적하는 데에는 약하죠. 모든 외부 의존성은 마찰입니다.

Zero의 설계는 능력을 표준 라이브러리 안으로 밀어 넣습니다. 명시적으로 문서화되고, 일관적이고, 언어가 안정화되면서 안정화되는 라이브러리 말이죠. 목표는 Zero 프로그램이 일상적인 작업을 위해 표준 배포 바깥으로 손을 뻗을 일이 거의 없게 하는 거예요. 에이전트가 추론해야 하는 표면을 한정된 크기로 유지해 줍니다.

이건 오늘 완성된 상태라기보다 지향점입니다. 1.0 이전 표준 라이브러리는 실재하지만 여전히 자라고 있어요. 원칙은 방향이지 목적지가 아닙니다.

Zero가 거래하는 것

모든 설계 선택은 무언가 비용이 듭니다. Zero가 정직하게 받아들이는 절충안:

  • 간결함보다 장황함. 순수 함수는 World가 필요 없습니다. I/O 가능한 함수는 필요해요. 에러는 시그니처에 등장합니다. 결과적으로 JavaScript나 Python 대응품보다 어노테이션이 많아집니다.
  • 마법보다 명시. 반성적 메타프로그래밍 없음, 조용히 동작을 감싸는 데코레이터 없음, 암묵적 전역 없음. 동적 언어에서 "그냥 동작"하는 것처럼 보이는 것들은 손으로 배선되어야 합니다.
  • 동적보다 정적. 매개변수, 반환값, shape 필드에 타입이 필요합니다. 컴파일러가 많은 일을 하고, 그 비용은 모든 시그니처를 작성자(또는 생성기)가 적어야 한다는 점이에요.
  • 변화율보다 안정성. 언어는 1.0 이전이고 빠르게 바뀌고 있지만, _설계 의도_는 표면이 자리 잡으면 잠그는 것입니다. 비용은 나중에 영리한 편의 기능을 더하기 어려워진다는 점이에요. 추가를 위한 기준이 "이게 사람에게 드는 비용보다 에이전트에게 더 도움이 되는가?"가 되거든요.

거래가 가치 있는지는 무엇을 최적화하느냐에 달려 있습니다. 일회성 스크립트를 쓰는 사람이라면 마찰은 진짜고 에이전트 이점은 추상적이죠. 하루에 작은 프로그램을 수천 개씩 만들어 내는 에이전트를 운영한다면, 마찰은 여러 번 되갚아집니다.

Zero가 되려 하지 않는 것

명시적으로 짚을 가치가 있는 몇 가지 부정적 주장:

  • "모든 프로그래밍의 미래"가 아닙니다. Zero는 가설이지 선언문이 아닙니다. 가설은 에이전트 우선 제약이 유용한 언어를 만들어 낸다는 것이고, 주류 언어들이 그 제약을 채택해야 하는지는 별개의 더 긴 대화입니다.
  • Vercel 배포 플랫폼 기능이 아닙니다. Vercel Labs에서 만들지만, Zero는 Next.js나 Vercel 호스팅에 묶여 있지 않습니다. 독립된 시스템 언어예요.
  • 운영 환경에서 Rust, Go, Zig의 대체가 아닙니다. 1.0 이전. 실험적. 학습하고 피드백을 주는 용도로 사용하고, 아직 고객용 소프트웨어를 출시하지 마세요.
  • 완성되지 않았습니다. 표준 라이브러리의 일부, 가변성 문법, 에러 처리 형태, 제네릭의 제약 조건이 1.0 전에 모두 움직일 수 있어요.

쓰지 않더라도 흥미로운 점들

Zero를 한 줄도 쓰지 않더라도 이 실험은 시사적입니다.

  • 작은 시스템 언어에서 실제로 동작하는 능력 기반 효과 시스템의 가장 명확한 예입니다. 멘탈 모델 — 권한을 전달하고, 시그니처에서 효과를 본다 — 은 다른 데로 옮겨 갈 수 있어요.
  • 진단 이야기는 지난 10년 동안 모든 컴파일러가 했어야 할 일입니다. 구조화된 출력이 늘 산문을 이기고, Zero의 안정적인 코드 약속은 언어 변경 없이 다른 도구들도 채택할 만한 것입니다.
  • "각각의 일을 하는 한 가지 방법, 의도적으로 작은 표면"이라는 원칙은 통상적인 언어 설계의 결을 거스릅니다. 그 원칙이 어디서 도움이 되고 어디서 답답한지 지켜보는 것은, 내일 어떤 언어를 쓰든 유용합니다.

다음에 읽을 곳

이 문서들을 모두 읽었다면, 가장 유용한 다음 읽을거리는 외부에 있습니다.

  • Zero 저장소 github.com/vercel-labs/zero — 예제, 소스, 그리고 메인테이너의 의도 선언인 AGENTS.md.
  • 공식 사이트 zerolang.ai — 시작 안내와 정석적인 소개.

둘 다 진화하고 있어요. 거기서 찾을 수 있는 내용은 어떤 제3자 튜토리얼보다도 최신일 것입니다. 이 문서의 원칙들은 천천히 움직이는 부분이고, 그 주변의 문법은 언어가 안착하는 동안 움직일 거예요.

자주 묻는 질문

'에이전트 우선 프로그래밍 언어'란 무슨 뜻인가요?

AI 에이전트를 — 사람뿐 아니라 — 처음부터 언어의 주요 사용자로 다룬다는 뜻입니다. 사람의 가독성과 인체 공학 같은 평소의 관심사와 함께, 에이전트의 요구(문법을 기계적으로 파싱하고, 유효한 프로그램을 생성하고, 에러 출력을 데이터로 읽고, 결정론적으로 수정을 적용하는 것)가 설계 결정을 이끕니다.

기존 언어로는 에이전트에게 충분하지 않은 이유는?

기존 언어들은 사람을 위해 설계되었습니다. 문법에는 사람은 견디지만 코드 생성기를 걸려 넘어뜨리는 단축 표현, 암묵적 변환, 모호한 구조가 들어 있어요. 컴파일러는 데이터가 아닌 산문을 출력하고, 효과 시스템은 암묵적입니다. 어느 것도 치명적이진 않아요 — 에이전트가 모두 우회할 수 있죠 — 하지만 처음부터 에이전트를 위해 설계된 언어는 그 마찰을 덮어 쓰는 대신 제거합니다.

Zero 설계의 핵심 원칙은 무엇인가요?

작고 규칙적인 문법(각각의 일을 하는 한 가지 방법), World 능력을 통한 명시적 효과(기본 I/O 없음), raises/check를 통한 명시적 실패(숨은 제어 흐름 없음), 그리고 결정론적 도구(안정적인 코드와 수정 계획을 가진 구조화된 데이터로서의 컴파일러 출력)입니다. 원칙들은 복합되어 작동해요. 각 원칙이 다른 원칙들을 에이전트에게 더 유용하게 만듭니다.

에이전트 우선이 되기 위해 Zero가 포기하는 것은?

간결함과 기본 편의성이요. 암묵적 참/거짓도, 전역 print도, 호출 스택을 가로질러 조용히 풀리는 try/catch도 없습니다. 함수가 매개변수가 더 많아지고 시그니처가 더 많은 어노테이션을 짊어집니다. 거래는 함수가 무엇을 하는지 — 무엇을 실패할 수 있는지를 포함해 — 시그니처만으로 읽을 수 있다는 거예요.

Zero가 사람이 작성하는 프로그래밍 언어를 대체할까요?

아니요, 그게 목표도 아닙니다. Zero는 에이전트 우선 설계가 어떤 모습인지에 대한 실험이지, 다른 언어들도 그 모든 선택을 채택해야 한다는 주장이 아닙니다. 흥미로운 결과는 실험이 가르쳐 주는 것입니다. 어떤 제약이 에이전트에게 가장 도움이 되는지, 어떤 절충안을 사람이 견디는지, 그리고 어떤 아이디어가 시간이 지남에 따라 주류 언어로 옮겨갈 수 있는지요.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기