# OpenMMO

> 1인 개발자가 라이브까지 올린 MMORPG. README만 보고 쓴 제 요약이 코드를 열자 두 군데 틀렸습니다.

- 수치: 내 요약 2건 정정
- 사람이 보는 화면: https://aitryed.com/ko/teardowns/games/openmmo/
- 반대 언어: https://aitryed.com/en/teardowns/games/openmmo/index.md
- 저장소: https://github.com/Julian-adv/OpenMMO
- 이 사이트 안내(AI용): https://aitryed.com/ko/llms.txt

---

**한 사람이 혼자서, AI에게 시켜 가며, 진짜로 돌아가는 온라인 게임을 만들어 서비스까지 올린 기록입니다. 그런데 이 편에서 제일 값나간 결과는 그 게임이 아니라 제 실수였습니다.**

먼저 규모부터 보겠습니다. 한 사람이 **347일** 동안 만들었고, 코드가 **11만 6천 줄**입니다. 그리고 코드 수정 기록 1,163건 중 **71%에 「AI와 같이 작업했다」는 서명**이 찍혀 있습니다.

> **[도판]** 홍보 문구는 "에이전트가 인간처럼 논다"인데, 그걸 가능하게 한 구조는 이 크레이트 공유 쪽이다.
>
> 이 프로젝트의 실제 아키텍처적 발명. 러스트 크레이트 하나를 서버·에이전트·브라우저 세 런타임에 동시 배포한 것이다. 공유 크레이트에 메시지 정의와 길찾기와 월드 생성이 들어 있다.

## 「혼자 만든 온라인 게임」이 왜 어려운 일인가

혼자 게임을 만드는 사람은 많습니다. 그런데 **여러 사람이 동시에 접속하는 게임**은 이야기가 완전히 다릅니다.

혼자 하는 게임은 내 컴퓨터 안에서만 앞뒤가 맞으면 됩니다. 온라인 게임은 **수십 명의 화면이 동시에 같은 이야기를 하고 있어야** 합니다. 내가 본 자리에 상대가 서 있어야 하고, 내가 준 물건이 상대에게 도착해야 하고, 그 와중에 인터넷이 끊겼다 붙어도 앞뒤가 안 맞으면 안 됩니다.

이 사람이 만든 세계는 **32제곱킬로미터**입니다. 땅을 잘게 나눈 칸으로 세면 **26만 칸**이 넘습니다.

## 그런데 제가 쓴 요약이 두 군데 틀렸습니다

여기가 이 편의 본론입니다.

저는 처음에 **창고 대문에 붙은 설명글만 읽고** 요약을 썼습니다. 그 뒤에 코드를 실제로 열어 봤더니 **두 군데가 사실과 달랐습니다.**

**틀린 것 하나 — 「AI가 사람처럼 논다」가 아니었습니다.** 홍보 문구만 보면 AI가 사람과 똑같은 조건에서 게임을 하는 것처럼 읽힙니다. 코드를 열어 보니 AI 쪽에 **혼자만 받는 특권**이 여럿 있었습니다.

| AI 캐릭터가 받는 것 | 무슨 뜻인가 |
|---|---|
| 벽에 안 부딪힘 | 사람은 막히는 곳을 그냥 통과합니다 |
| 매일 돈을 받음 | 사람은 벌어야 하는 것을 그냥 받습니다 |
| 거래창을 강제로 띄울 수 있음 | 사람은 상대가 받아야 열립니다 |

즉 **같은 조건에서 노는 게 아니라, 유리한 조건을 받고 노는 것**이었습니다.

## 이 실수에서 배운 것이 이 레포에서 배운 것보다 많았습니다

두 번 틀렸고, **틀린 방향이 양쪽이었습니다.** 어떤 건 실제보다 대단하게 썼고, 어떤 건 실제보다 못하게 썼습니다.

그래서 규칙 하나를 새로 적었습니다.

> **설명 문서는 「계획」이고 코드는 「현황」이다. 계획을 현황으로 읽지 않는다.**

만든 사람이 거짓말을 한 게 아닙니다. 설명 문서는 대개 **만들기 전에 쓰고 그 뒤에 잘 안 고칩니다.** 그래서 문서와 코드가 갈라지는 건 자연스럽고, **읽는 쪽이 그걸 감안해야** 합니다.

## 잘 만든 구조 하나 — 「똑같은 뇌를 두 곳이 나눠 쓴다」

기술 쪽에서 배운 게 하나 있습니다.

AI 캐릭터를 게임에 넣을 때 흔한 사고가 있습니다. **게임 본체와 AI 조종 쪽이 각자 자기 계산을 하다가 서로 다른 답을 내는 것**입니다. 게임은 「막혔다」고 보는데 AI는 「지나갈 수 있다」고 보면, AI 캐릭터가 벽에 끼어서 덜덜 떱니다.

이 사람은 그걸 **애초에 갈라지지 않게** 만들었습니다. 판정하는 코드를 **한 벌만 만들어서 양쪽이 같이 쓰게** 한 것입니다. 하나뿐이니 답이 다를 수가 없습니다.

개념은 가져왔지만 지금 제 작업에 넣진 않았습니다 — **드는 품이 얻는 것보다 큽니다.**

## 코드는 못 가져옵니다

법적 조건이 <strong>「상업적으로는 쓰지 말라」</strong>입니다. 그래서 코드를 베껴 오는 것은 처음부터 불가능합니다. 구조만 보고 왔습니다.

## 마지막 — 인상적인 숫자를 인용할 때 붙여야 할 단서

「AI와 같이 작업한 커밋 71%」와 「위험한 코드 패턴 0건」은 인상적인 숫자입니다. 그런데 이걸 **「AI를 쓰면 이렇게 된다」로 읽으면 틀립니다.**

같은 도구를 써도 대부분은 저 숫자가 안 나옵니다. 저 값을 만든 것은 도구가 아니라 **이 사람이 자기한테 건 규율**입니다. 인용할 때는 그 단서를 같이 붙여야 합니다.

## 여기부터는 자세한 기록입니다

**이 편에서 제일 값어치 있는 결과는 레포에 대한 것이 아니라 제 요약에 대한 것입니다.** 1인 개발자가 **바이브코딩으로 만들어 라이브 서비스까지 올린** Rust + Svelte MMORPG입니다. 코드 116,000줄, 커밋 1,163개, 347일, **커밋의 71%에 AI 공동저작 서명**이 찍혀 있습니다. 그런데 코드를 열기 전에 README만 보고 쓴 제 요약에 **사실과 다른 게 둘** 있었고, 그 둘을 정정하는 과정이 이 레포에서 배운 것보다 많았습니다.

## 무엇을 만든 물건인가

**1인 개발자가 347일 동안 만들어 실제로 서비스 중인 MMORPG입니다.** 서버는 Rust, 클라이언트는 Svelte에 WebGPU 전용, 프로토콜은 JSON이 아니라 **바이너리**입니다. 월드가 32km²에 타일 262,144개입니다.

**품질 지표가 인상적입니다.** 서버 코드에 **`unwrap` 0건, `unsafe` 0건**. 테스트 270개. **커밋 1,163개 중 825개(71%)에 AI 공동저작 서명**이 붙어 있는데, 그 결과물이 이 정도 규율을 유지하고 있다는 게 이 레포의 실질입니다.

⚠ **라이선스가 비상업용입니다.** 상업적 사용이 불가하고, **코드 차용은 안 됩니다.** 설계 참고만 가능합니다.

## 깨본 결과 — 제 요약이 두 군데 틀렸습니다

**정정 1 — "모델이 MCP로 붙어서 플레이한다"는 사실이 아닙니다.**

의존성 선언에는 관련 크레이트가 둘 들어 있습니다. 그런데 **소스 전체를 검색하면 사용처가 0건**입니다. **컴파일만 되고 한 줄도 안 씁니다.** 설정 예시의 관련 포트는 주석 처리돼 있고, 설정 구조체에 **그 필드 자체가 없습니다.** 문서의 툴 목록은 **설계 스케치**이고, 같은 문서 뒷부분에 **"우선순위 4번, 미착수"** 로 남아 있습니다.

**실제 인터페이스는 훨씬 단순합니다** — JSON 액션 스키마 7종(말하기·공격·이동·부활·거래 제안·거래창 열기·대기). 모델은 그중 하나를 고를 뿐입니다.

**정정 2 — "서버가 인간과 에이전트를 구분 못 한다"는 정반대입니다.**

전용 인증 메시지가 따로 있고, 인증 결과가 **불린 플래그 하나로 영구히 각인**됩니다. 그리고 그 플래그가 **최소 여섯 곳에서 게임 규칙을 바꿉니다.**

| 자리 | 효과 | 성격 |
|---|---|---|
| 충돌 판정 | 에이전트는 **건너뜁니다** — 사실상 벽을 통과 | **특권** |
| 일일 급여 | 에이전트만 골드를 받습니다 | **특권** |
| 거래창 | 에이전트만 상대 화면에 거래창을 띄울 수 있습니다 | **특권** |
| 거래 제안 | 인간의 제안은 거부됩니다 | 제약 |
| 몬스터 스폰 | 에이전트 주변은 스폰을 억제합니다 | 최적화 |

**절반은 맞습니다** — 전송 계층은 진짜로 같습니다. 같은 포트, 같은 프레임, 같은 메시지, 같은 길찾기 코드. **그런데 "특권 API가 없다"의 나머지 절반이 불린 하나에 담겨 있었습니다.**

> **[도판]** 두 정정의 방향이 서로 반대다. 한쪽으로만 틀렸다면 편향인데, 양쪽으로 틀렸으니 그냥 안 읽은 것이다.
>
> README만 읽고 쓴 요약과 코드를 열어 확인한 사실의 대조. 두 건 모두 방향이 반대였다. 하나는 없는 기능을 있다고 했고, 하나는 있는 특권을 없다고 했다.

**중요한 건 README가 거짓말을 안 했다는 것입니다.** 문서는 **설계 문서**라고 적혀 있었고, 미착수 표시도 같은 문서 안에 있었습니다. **저는 설계 문서를 현황으로 읽었습니다.** 그리고 *"전송 계층이 같다"* 는 문장을 *"규칙이 같다"* 로 확장해서 읽었습니다.

**둘의 방향이 반대라는 게 진단에 중요합니다.** 한쪽으로만 틀렸으면 기대 편향인데, **없는 걸 있다고 하고 있는 걸 없다고 했으니** 그냥 **안 열어 본 것**입니다.

## 내 환경에 대봤다

**코드는 못 가져옵니다** — 라이선스가 비상업용이라 **차용 금지**입니다. 설계만 봅니다.

**제일 배울 만한 건 크레이트 공유입니다.** 길찾기와 월드 생성이 **서버·봇·브라우저 세 곳에서 같은 코드로 돕니다.** 제 QA 자동화는 봇이 쓰는 판정 로직과 게임이 쓰는 로직이 **따로**입니다 — 그래서 *"봇이 통과 가능하다고 봤는데 게임에서는 막힌다"* 가 생깁니다. **한 코드로 만들 수 있으면 그 종류의 불일치가 원천적으로 안 생깁니다.**

⚠ 다만 **제 상황에 바로 적용은 안 됩니다.** 게임 엔진과 봇의 런타임이 다르고, 그걸 하나로 만들려면 게임 쪽을 고쳐야 합니다. **비용이 이득보다 큽니다.**

**AI 공동저작 71%인데 `unwrap` 0건**이라는 조합도 눈에 남습니다. *"AI가 쓴 코드는 품질이 떨어진다"* 는 통념에 대한 반례이긴 한데, ⚠ **이건 개발자 한 명의 규율이 만든 결과이지 도구의 성질이 아닙니다.** 같은 도구로 다른 사람이 쓰면 다른 숫자가 나옵니다.

## 판정

| 무엇 | 판정 |
|---|---|
| 코드 차용 | ⛔ **금지.** 라이선스가 비상업용이다 |
| **한 코드를 여러 런타임에 공유** | **개념만 채택.** 봇과 게임의 판정 불일치가 원천 차단된다<br>⚠ 지금 적용은 비용 > 이득 |
| **"설계 문서를 현황으로 읽지 않는다"** | **채택 — 규칙으로.** 이번에 두 번 틀렸다 |
| AI 공동저작 71% · `unwrap` 0 | **인용 시 한정 필요.** 도구가 아니라 사람의 규율이 만든 값이다 |

**이 편에서 값을 치른 교훈은 이겁니다 — 문서를 읽고 쓴 요약은 코드를 열면 뒤집힙니다.** 그것도 **양쪽 방향으로** 뒤집힙니다.

그리고 ⚠ **틀린 요약을 지우지 않고 정정으로 남기는 편이 낫습니다.** 지우면 *"원래 맞게 알고 있었다"* 가 되는데, 실제로는 **코드를 열기 전까지 두 군데 틀린 상태로 알고 있었습니다.** 다음에 README만 보고 판단하려 할 때, 이 기록이 그걸 막습니다.
