AI가 러스트로 짠 PHP 엔진, 공식 테스트 17% 통과
러스트(Rust) 문법을 전혀 모르는 개발자가 AI 코딩 에이전트를 지시만 해서 기존 PHP 소스 코드 없이 밑바닥부터 새롭게 구축된 PHP 인터프리터(Phargo)를 개발했습니다. 이 프로젝트는 AI가 자체적으로 결과를 판단하지 못하도록 30년간 축적된 약 2만 2천 개의 공식 PHP 테스트 스위트(suite)를 엄격한 기준으로 삼아 진행되었으며, 현재 전체 테스트의 17.4%를 통과하며 워드프레스 렌더링을 성공적으로 구현했습니다.
원문 제목: 내가 AI로 구축한 러스트 기반 PHP 엔진이 PHP-src 테스트의 17%를 통과하고 워드프레스를 렌더링하다 출처: 해커뉴스(hackernews)
나는 러스트(Rust)를 모른다. 그럼에도 내 AI는 기어코 PHP를 러스트로 다시 작성하고 있다.
며칠 전 밤, 나는 내 터미널이 26KB짜리 워드프레스(WordPress) 프론트 페이지를 출력하는 것을 지켜보았다. <title>Phargo Test Site</title> 태그, 블록 라이브러리 CSS, SQLite 데이터베이스에서 불러온 "Hello world!", 그리고 마지막에 깔끔하게 닫힌 </html>이었다. 지극히 평범한 결과물이었지만, 단 하나 다른 점이 있었다. 이 모든 것을 제공한 PHP 엔진에는 실제 PHP 소스 코드가 단 한 줄도 포함되어 있지 않다는 사실이다. 이것은 러스트로 처음부터 새로 작성된 인터프리터(interpreter)다.
여기서 당신이 곰곰이 생각해 봤으면 하는 부분이 있다. 나는 러스트를 할 줄 모른다. 어휘 분석기(Lexer)를 작성해 본 적도 없다. 다른 탭에서 위키피디아를 찾아보지 않고서는 "트리 워킹 평가자(tree-walking evaluator)"가 무엇인지 설명할 수도 없다. 만약 파티장에서 누군가 나를 구석으로 몰아세우고 PHP의 가비지 컬렉터가 어떻게 작동하는지 묻는다면, 나는 전화가 온 척하며 도망칠 것이다.
이 엔진의 이름은 'Phargo'다. 이 프로젝트에서 내 역할은 대략 '방향을 잡아주는 것'이다. AI가 코드를 작성한다. 내가 목표를 가리키면, 중세 시대의 왕이 해도를 검토하듯 받아쓴 결과물을 읽는다(엄숙하게 고개를 끄덕일 뿐, 이해는 전혀 못한다). 그리고 다음과 같이 현대 소프트웨어 개발에서 가장 강력한 문장을 타이핑한다. "좋아 보이네, 계속해."
실험: '극단적인 정직'을 빌드 시스템으로 삼다
요즘 세상에는 모두가 각자의 반려식물처럼 AI로 만든 프로젝트를 하나씩 가지고 있다. 그리고 그런 프로젝트들은 모두 "작동한다!"라는 반박할 수 없는 주장을 내세운다. 대체 누구 기준으로 작동한다는 걸까? 코드를 작성한 AI 기준인가? 네 번째 다시 찍은 데모 영상 기준인가?
그래서 이번 실험 전체는 하나의 아이디어에 뿌리를 두고 있다. 번(Bun) 팀이 자바스크립트 런타임을 실제 테스트 스위트로 검증하는 것을 보고 얻은 아이디어인데, 바로 "AI가 자기 숙제를 스스로 채점하게 두지 마라"는 것이다.
PHP는 자체 테스트 스위트를 제공한다. PHP 내부 개발팀이 30년에 걸쳐 작성한 약 22,000개의 .phpt 파일이다. 내가 작성한 테스트도 아니고, AI가 작성한 테스트도 아니다. 이 테스트들은 DateTime의 일광 절약 시간제 계산법부터 var_dump()가 부동소수점(float)을 어떻게 출력하는지까지, 언어의 모든 괴상한 구석을 빠짐없이 담아내고 있다. 이 테스트 스위트가 바로 절대적인 기준(Oracle)이다.
점수판은 이 모든 테스트를 실행하며, 통과율은 매 실행 후 저장소에 자동으로 기록된다. 이 숫자는 아첨을 받지 않고, 협상에 응하지 않으며, 프롬프트를 잘 넣는다고 기분이 좋아지지 않는다. bug40261.phpt 테스트가 통과하면 통과하는 것이고, 아니면 실패하는 것이다.
현재 점수: 22,037개 중 3,844개 통과. 전체 상위 PHP 테스트 스위트의 17.4%다. 17%라고 비웃기 전에 알아둘 것이 있다. 현실적인 통과율 한계치는 약 40~45% 수준이다. 나머지 테스트는 명시적으로 범위에서 제외한 C 확장 모듈(GD, curl, SOAP, intl, MySQL 드라이버 등)을 테스트하기 때문이다. 실제 경기장 안에서를 기준으로 보면, 0에서 시작한 것을 감안하면 이 상승세는 매우 현실적이고 가파른 것이다.
인간으로서 내가 반복하는 루프는 부끄러울 정도로 단순하다.
- AI가 전체 테스트 데이터에 대한 실패 히스토그램을 분석하여 실제로 고칠 수 있는 가장 큰 실패 그룹을 찾는다.
- AI가 해당 기능을 구현한다.
- 약 22,000개의 테스트 점수판을 실행한다.(팬이 돌아가는 소음 약 7분)
- 숫자가 오르면: 커밋(commit)하고, 푸시(push)하고, 다시 반복한다.
- 숫자가 내리면: 내가 할 수 있는 말은 또 하나뿐이다. "음, 성능이 후퇴했네(regressed). 다시 확인해 봐."
끝이다. 이게 내가 하는 일의 전부다. 나는 위임의 최고 경지에 도달했고, 조금도 미안하지 않다.
신탁(Oracle)은 매수될 수 없다. 하지만 테스트 도구는 내 얼굴에 대놓고 거짓말을 했다.
초반에 통과율은 어딘가 석연찮은 방식으로 정체되었다. 분명히 간단한 테스트 카테고리 전체가 예상 출력과 완전히 동일해 보이는 상태에서도 계속 실패로 처리되었다. 나는 '다른 점 찾기' 퍼즐의 두 똑같은 사진을 바라보듯, 아무것도 발견하지 못한 채 그 차이 화면만 뚫어지게 쳐다보았다.
그 차이는 눈에 보이지 않았기 때문에 보이지 않았던 것이다. 바로 캐리지 리턴(carriage return, carriage returns)이었다. 테스트 데이터가 CRLF 줄바꿈 방식을 사용하는 윈도우(Windows)에서 체크아웃되었고, 우리의 점수판은 결과를 바이트 단위로 일일이 비교하고 있었다. PHP의 기본 테스트 러너는 비교하기 전에 줄바꿈 방식을 통일(normalize)하는 반면, 우리 시스템은 그렇게 하지 않았던 것이다.
즉, 우리 테스트 도구는 수주 동안 말 그대로 말줄바꿈 문자만을 이유로 말줄바꿈이 여러 줄인 테스트를 조용히 실패시키고 있었던 것이다. 코드 한 줄을 수정해 줄바꿈을 표준화(normalize)하자, 수백 개의 테스트가 즉시 초록불(통과)로 바뀌었다. 이 교훈은 프로젝트에 아주 깊이 새겨졌다.