# Codex로 1주일 동안 게임을 만든 기록 — 검은 화면에서 APK까지

> Unity 모바일 로그라이크 `회귀자는 탑을 오른다`를 Codex와 함께 데모 상태까지 끌어올린 1주일의 기록.  
> Lobby black screen → 세로형 UI 재구성 → screenshot QA → Android APK 빌드까지.

---

## 왜 이 글을 쓰는가

최근 1주일 동안 Codex를 거의 개발팀처럼 썼다. 정확히는 PM, 클라이언트 개발자, QA, 빌드 담당을 세션별로 나눠 맡긴 것에 가깝다.

처음부터 거창한 완성품을 만든 것은 아니다. 시작점은 더 현실적이었다. Unity Editor에서 Lobby를 열었는데 Game View가 검은 화면이었다. 버튼도 안 보이고, 새 게임도 못 누르고, 첫 보스까지 가는 수동 QA도 막혔다.

결론부터 말하면, 그 상태에서 1주일 안에 여기까지 왔다.

- 모바일 세로형 UI shell 재구성
- Lobby / Floor Map / Event / Rest / Shop / Combat / Boss / Ending 화면 정리
- 1080x1920 screenshot harness 구축
- GUI Test Runner 기준 EditMode / PlayMode 검증 흐름 복구
- BossGate 선택지와 지도/상태/장비 유틸리티 보강
- Android APK 생성 및 재빌드

이 글은 "AI가 코드를 다 짜줬다"는 식의 이야기가 아니다. 오히려 반대다. Codex를 제대로 쓰려면 작업 범위를 쪼개고, 사실과 추측을 분리하고, 테스트 실패와 실행 환경 실패를 계속 구분해야 했다.

## 시작점: 게임은 있었지만, 플레이할 수 없었다

이미 프로젝트에는 많은 구조가 있었다. ScriptableObject 기반 데이터, encounter pipeline, 전투 루프, 마타이오스 NPC, save/continue, 상점과 휴식 구조도 있었다.

문제는 "있는 것"과 "플레이 가능한 것"이 다르다는 점이었다.

2026년 5월 15일 QA 기록의 가장 큰 blocker는 Lobby black screen이었다. Unity는 열리고, Play Mode도 들어가는데, Game View에는 아무것도 보이지 않았다. New Game을 누를 수 없으니 자연스럽게 Floor Map, 전투, 상점, 보스까지 이어지는 수동 검증도 막혔다.

이때 중요한 판단은 "기능을 더 붙이지 말고, 먼저 보이는 게임으로 만들자"였다.

Codex에게 시킨 일도 그래서 구현보다 복구에 가까웠다.

- Lobby scene bootstrap 확인
- Canvas / EventSystem / GraphicRaycaster 계층 점검
- portrait safe area와 runtime UI 생성 경로 정리
- PlayMode smoke로 Lobby UI가 실제로 활성화되는지 고정

이후 Lobby는 다시 보이기 시작했다.

![Lobby 화면](/Users/godju/Downloads/AI%20Game/hwigi-tower/Docs/Blog/assets/codex_week1/01_lobby.png)

화면 하나가 보이는 데서 끝나지 않았다. 모바일 게임에서 Lobby는 단순 메뉴가 아니라 첫 인상이다. 그래서 이후 작업은 "기능을 이어 붙이는 것"에서 "세로 화면에서 읽히는 게임으로 만드는 것"으로 넘어갔다.

## 세로형 UI를 다시 짠 이유

PC에서 돌아가는 Unity UI와 모바일 세로형 UI는 완전히 다르다. 특히 1080x1920 기준으로 보면, 작은 텍스트나 상단 HUD 과밀이 바로 드러난다.

초기 UI의 문제는 크게 세 가지였다.

1. 화면마다 이전 상태의 잔상이 남았다.
2. debug-like label이나 raw stableId가 종종 플레이어 화면에 보였다.
3. 버튼은 있었지만, 무엇을 눌러야 하는지 한눈에 들어오지 않았다.

그래서 `PrototypeHud`를 다시 나눴다. 큰 방향은 화면을 계층으로 분리하는 것이었다.

- top status
- objective
- visual stage
- companion area
- result summary
- map
- action buttons
- ending layer

이 분리는 생각보다 중요했다. 전투 화면에서는 지도와 상점 잔상이 없어야 하고, 이벤트 화면에서는 전투 결과 패널이 끼어들면 안 된다. Rest 화면에서는 입력창과 액션 카드가 겹치면 안 되고, Shop 화면에서는 merchant visual과 상품 카드가 서로 방해하면 안 된다.

지도도 다시 잡았다. 위에서 아래로 내려가는 지도보다, 모바일 세로 화면에서는 아래에서 위로 오르는 구조가 더 직관적이었다. 탑을 오른다는 게임 컨셉과도 맞았다.

![Floor Map 화면](/Users/godju/Downloads/AI%20Game/hwigi-tower/Docs/Blog/assets/codex_week1/02_floor_map.png)

이 시점부터 Codex 작업은 단순히 "버튼 추가"가 아니라 "화면 상태를 서로 침범하지 않게 정리하는 일"이 됐다. 이건 자동 생성 코드만으로 해결하기 어렵다. 계속 screenshot을 보고, 겹침을 찾고, 어떤 layer가 어느 상태에서 꺼져야 하는지 테스트로 고정해야 했다.

## 게임 루프를 화면으로 증명하기

vertical slice에서 중요한 건 기능 목록이 아니다. 플레이어가 한 번의 run으로 실제 흐름을 이해할 수 있어야 한다.

이번 주에 정리한 핵심 루프는 이렇다.

```text
Lobby
  → Floor Map
  → Event / Combat / Rest / Shop
  → BossGate
  → Boss Combat
  → Ending Choice
```

각 화면은 기능적으로 이미 존재했지만, 데모로 보이려면 presentation이 필요했다.

Event 화면은 top status, central cutscene image, event text, bottom choice 구조로 다시 잡았다.

![Event 화면](/Users/godju/Downloads/AI%20Game/hwigi-tower/Docs/Blog/assets/codex_week1/03_event_jar_room.png)

Rest 화면은 마타이오스가 있는 화면이다. 여기서 NPC가 단순한 UI mode처럼 보이면 게임의 차별점이 죽는다. 그래서 portrait, rest action cards, input field, response bubble을 분리했다.

![Rest / Mataios 화면](/Users/godju/Downloads/AI%20Game/hwigi-tower/Docs/Blog/assets/codex_week1/04_rest_mataios.png)

Shop은 보스 전 준비 장소로 정리했다. 상품명, 가격, 효과, Gold 부족 상태가 보여야 했다. 단순히 "구매 불가"라고 쓰는 것보다, 플레이어가 무엇이 부족하고 무엇을 목표로 해야 하는지 알 수 있어야 했다.

![Shop 화면](/Users/godju/Downloads/AI%20Game/hwigi-tower/Docs/Blog/assets/codex_week1/05_shop.png)

Combat은 가장 많이 흔들린 화면이다. 처음에는 Attack / Defend / Skill 버튼이 있다는 것만으로 충분해 보였지만, 실제로 보면 선택 이유가 약했다. 그래서 combat dock을 다시 만들었다. 적은 위, 전투 로그는 가운데, 플레이어와 마타이오스는 아래에 고정했다.

![Combat 화면](/Users/godju/Downloads/AI%20Game/hwigi-tower/Docs/Blog/assets/codex_week1/06_normal_combat.png)

아직 전투는 완성됐다고 말하기 어렵다. enemy intent, defend value, skill condition, hit/guard feedback은 더 필요하다. 하지만 최소한 "전투 화면으로 읽힌다"는 단계까지는 끌어올렸다.

## Screenshot harness가 QA의 기준이 됐다

이번 주 가장 큰 전환점은 screenshot harness였다.

UI를 고칠 때 가장 위험한 말은 "대충 괜찮아 보인다"다. 어떤 화면에서 괜찮았는지, 몇 해상도에서 봤는지, 다음 수정 후에도 그대로인지가 남지 않는다.

그래서 PlayMode 기반 screenshot QA를 만들었다. 기준은 1080x1920 portrait였다. 처음에는 8개 화면을 찍었다.

- Lobby
- Floor Map
- Event / Jar Room
- Rest / Mataios
- Shop
- Normal Combat
- Boss Combat
- Ending Choice

이후 Floor 3~5 shop과 BossGate choice까지 확장되면서 12장 기준으로 늘어났다.

![BossGate 선택 화면](/Users/godju/Downloads/AI%20Game/hwigi-tower/Docs/Blog/assets/codex_week1/12_boss_gate_choices.png)

이 스크린샷들은 단순 결과물이 아니라 테스트 기준이었다. 예를 들어 Shop을 고치면 Shop만 보는 게 아니라, Rest나 Combat에 이전 UI가 남지 않는지도 같이 봐야 했다. BossGate 선택지를 고치면 boss combat으로 바로 들어가는 경로뿐 아니라 `돌아간다`가 route state를 망가뜨리지 않는지도 봐야 했다.

이때부터 Codex에게 줄 수 있는 지시도 훨씬 구체적이 됐다.

나쁜 지시는 이런 식이다.

```text
UI 좀 더 예쁘게 해줘.
```

실제로 도움이 된 지시는 이런 식이었다.

```text
Rest 화면에서 action card, input field, response bubble이 겹치지 않게 phase를 분리해.
Shop과 Map 상태에서는 result/objective/debug layer가 남지 않게 꺼.
수정 후 screenshot harness 기준으로 01~12 화면을 다시 검증해.
```

Codex는 추상적인 미감보다 명확한 실패 조건을 줬을 때 훨씬 잘 움직였다.

## Test Runner와 LicenseClient 삽질

이번 주에 제일 많이 시간을 먹은 건 게임 로직이 아니라 검증 경로였다.

Unity batchmode는 몇 번이나 애매하게 실패했다. 어떤 날은 LicenseClient timeout이 났고, 어떤 날은 PlayMode test가 exit code 0으로 끝났는데 XML이나 PNG가 생성되지 않았다. 5월 19일 manual QA에서는 Lobby가 보였지만, Codex/OS coordinate click으로 `새 게임` 버튼을 실제로 진행시키지 못했다.

여기서 중요한 건 실패를 한 덩어리로 뭉개지 않는 것이다.

- 게임 로직이 실패한 것인가
- Unity 실행 환경이 실패한 것인가
- batchmode test runner가 실패한 것인가
- GUI Test Runner에서는 통과하는가
- 실제 물리 입력에서는 되는가
- screenshot은 이전 것인가, 이번 run에서 새로 생성된 것인가

이걸 분리하지 않으면 QA 기록이 금방 오염된다. "테스트 통과"라고 했는데 사실은 오래된 XML을 본 것일 수도 있고, "게임이 안 된다"고 했는데 실제로는 자동화 클릭이 Unity Game View에 전달되지 않은 것일 수도 있다.

그래서 진행 로그에는 일부러 지저분한 사실도 남겼다.

- batchmode가 XML/PNG를 만들지 않음
- GUI Test Runner로 우회 검증
- 임시 TestRunner wrapper 사용 후 제거
- ADB device 없음으로 실기 smoke 미실행
- manual route는 Lobby click automation에서 막힘

블로그에 이런 내용을 쓰는 이유는 간단하다. 실제 개발은 성공한 커밋만으로 설명되지 않는다. 테스트 실행 경로를 복구하는 시간도 개발 시간이다.

## APK까지 갔다

5월 18일에는 Android APK를 만들었다. Unity 6, IL2CPP, ARM64, portrait 설정으로 release/non-development APK를 생성했고, APK signature verify도 통과했다.

5월 20일에는 `2550281` 기준으로 다시 빌드했다. 이 기준점은 기록상 stable gameplay commit으로 남겼다.

```text
2550281 Update tests for polished map and utility flow
```

업로드용 APK 파일의 SHA-256도 확인했다.

```text
ee80aa86d7d053a6cd0278c6f79e9ec605e62a798d001cabd552db6fb411a20b
```

다만 여기서도 선을 그어야 한다. APK 생성은 완료됐지만, Android 실기 install/launch smoke는 ADB 기기가 없어 아직 별도 과제로 남았다. 즉 "APK가 있다"와 "실기 검증까지 끝났다"는 다른 문장이다.

Ending 화면도 데모 경로에 들어왔다.

![Ending Choice 화면](/Users/godju/Downloads/AI%20Game/hwigi-tower/Docs/Blog/assets/codex_week1/08_ending_choice.png)

아직 텍스트와 연출은 더 다듬어야 한다. 하지만 Lobby black screen에서 시작했던 1주일을 생각하면, 여기까지 온 것만으로도 큰 전환이다. 이제 최소한 화면 단위로 이야기할 수 있는 게임이 됐다.

## Codex를 어떻게 썼나

이번 작업에서 Codex를 잘 쓰는 방식은 점점 분명해졌다.

첫째, 세션 역할을 나눴다. 구현 세션, QA 세션, 빌드 세션, 블로그/기록 세션을 섞지 않았다. 한 세션이 모든 것을 하게 두면 맥락이 흐려지고, 특히 QA와 구현이 섞이면 "검증했다"는 말의 의미가 약해진다.

둘째, PROGRESS를 계속 남겼다. Codex가 이전 작업의 이유를 기억하려면 실행 로그가 필요하다. 단순히 "수정함"이 아니라 무엇을 고쳤고, 어떤 테스트를 돌렸고, 무엇이 막혔는지를 남겨야 다음 세션이 이어진다.

셋째, Codex에게 추상적 완성도를 맡기지 않았다. "좋게 만들어줘"보다 "이 화면에서 이 layer를 숨기고, 이 버튼만 남기고, screenshot harness를 통과시켜"가 훨씬 낫다.

넷째, dirty worktree를 함부로 정리하지 않았다. 작업 중에는 에셋, 문서, 테스트 산출물, 임시 파일이 계속 생긴다. Codex에게도 "내가 만들지 않은 변경은 되돌리지 말라"는 원칙이 중요했다.

다섯째, 테스트 수치를 과장하지 않았다. GUI Test Runner로 확인한 것, batchmode가 실패한 것, screenshot이 새로 생성된 것, 사용자 제공 기준인 것을 분리했다.

## 배운 것

1. **AI로 게임을 만든다는 말은 너무 넓다**  
   실제로는 화면 하나, 테스트 하나, 커밋 하나씩 쪼개서 지시해야 한다. Codex는 방향을 읽을 수 있지만, 검증 기준이 없으면 쉽게 넓어진다.

2. **vertical slice는 기능 목록이 아니라 경로다**  
   Lobby, Map, Combat, Shop이 따로 있는 것과 한 번의 run으로 이어지는 것은 다르다. 이번 주의 핵심은 화면을 연결된 경로로 만드는 것이었다.

3. **스크린샷은 문서가 아니라 테스트다**  
   1080x1920 screenshot harness가 생기고 나서야 UI 수정이 누적될 수 있었다. 눈으로 보는 QA도 반복 가능해야 한다.

4. **실패 기록이 다음 작업 속도를 만든다**  
   LicenseClient timeout, batchmode XML 미생성, Lobby click automation 실패는 보기 좋은 기록은 아니다. 그래도 남겨야 다음에 같은 문제를 게임 로직 버그로 오해하지 않는다.

5. **AI NPC보다 먼저 필요한 것은 결정적인 게임 루프다**  
   이 게임의 장기 목표는 AI NPC지만, 이번 주에 가장 중요했던 건 AI 연결이 아니었다. 같은 입력과 같은 선택이 같은 결과를 내고, 그 결과를 테스트할 수 있는 구조였다.

## 다음 단계

다음은 두 갈래다.

하나는 게임 자체의 QA다. Android 실기에서 install/launch smoke를 하고, Lobby에서 첫 보스까지 물리 입력 기준으로 한 번 더 확인해야 한다. Combat 선택 이유, Shop disabled state, Ending copy도 더 다듬어야 한다.

다른 하나는 AI NPC 연결이다. 이미 LLM provider abstraction, prompt hash, deterministic cache, memory/reaction slot은 준비되어 있다. 이제 실제 local 또는 on-device AI를 붙일 때, 출력 품질보다 먼저 캐시와 fallback이 게임 루프를 흔들지 않는지 봐야 한다.

이번 1주일은 완성품을 만든 시간이 아니었다. 대신 검은 화면에서 시작해, 화면을 찍고, 테스트하고, APK로 묶을 수 있는 데모의 뼈대를 만든 시간이었다.

---

*이 글은 개발 기록 기반 초안이다. 게임 스토리 원문, 내부 경로, 계정/인증 정보, 외주 원본 데이터는 포함하지 않았다.*
