AI가 세계 최강의 오목 엔진을 만들었다? …로그를 보기 전까지는
AI가 세계 최강의 오목 엔진을 만들었다? …로그를 보기 전까지는
AI에게 오목 엔진을 만들어 달라고 했다.
단 1시간 만에 780줄의 Minimax 엔진이 완성됐다.
그리고 현존 최강 오목 엔진 Rapfi와 대결을 붙였다.
결과가 너무 완벽했다. 그래서 오히려 믿을 수 없었다.
1부에서 이어집니다
지난 1부에서는 한 가지 사실을 확인했다: LLM 혼자서는 오목을 잘 두지 못한다. 보드를 텍스트로만 '독해'해야 하는 구조적 한계, Alpha-Beta나 MCTS 같은 탐색 알고리즘의 부재. 어쩌면 당연한 결과였다.
하지만 질문을 바꿔보기로 했다:
"생성형 AI는 오목을 못 두더라도, 오목을 잘 두는 엔진을 만들 수 있을까?"
AI가 플레이어가 아니라 개발자가 되면 어떻게 될까?
1. AI가 엔진을 만들었다
Deepseek v4 Flash에게 "Alpha-Beta Pruning과 Iterative Deepening을 사용하는 Python 오목 엔진을 만들어라"고 요청했다.
AI는 약 1시간 만에 동작하는 Minimax 엔진을 만들어냈다.
코드 구조도 생각보다 깔끔했다. 이제 Rapfi와 대결을 시켜보기로 했다.
2. 첫 테스트 — 결과가 너무 완벽했다
상대 엔진은 Rapfi. 현존 오픈소스 오목 엔진 중 최상위다. Alpha-Beta + NNUE(신경망 평가)를 사용하며 프로 기사 수준의 실력을 가진 엔진이다.
환경: 15x15 보드, 흑돌 Minimax(depth 4, 10초 제한), 백돌 Rapfi(10초 제한), 5판 대결.
Game 1 : Win
Game 2 : Win
Game 3 : Win
Minimax 3:0. Rapfi를 상대로 전승이었다.
솔직히 이때는 내가 뭔가 엄청난 걸 만든 줄 알았다. 하지만 뭔가 이상했다. Rapfi는 분명히 최강 엔진인데, Minimax(단순 패턴 평가 + depth 4 탐색)가 이길 수준이 아니다. 결과보다 로그를 먼저 확인했다.
3. 첫 번째 문제 — NNUE 비활성화
로그를 분석해보니 Rapfi가 NNUE 가중치를 로드하지 않고 있었다.
원인은 AI가 생성한 코드의 파일 포맷 처리 방식이었다. Rapfi는 내부적으로 LZ4 압축을 해제할 수 있는데, AI는 일반 압축 파일이라고 판단해 미리 해제하도록 구현했다. 결과적으로 Rapfi가 다시 압축 해제를 시도하다 실패, NNUE가 비활성화된 상태로 동작했다.
NNUE가 없으면 Rapfi는 고전적인 평가 함수만 사용한다. 실력이 크게 떨어진 상태였다.
수정 요청 → AI가 코드 수정 → 재대결.
Game 1 : Win
Game 2 : Win
Game 3 : Lose
Minimax 2:1 승. 여전히 Minimax가 앞서고 있었다. 아직도 뭔가 이상하다.
4. 두 번째 문제 — 유령 돌 (Ghost Stone)
이번엔 로그에서 이상한 패턴이 발견되었다:
Rapfi played invalid move G8
Rapfi played invalid move J8
Rapfi played invalid move K7
Rapfi가 이미 돌이 있는 위치에 수를 두고 있었다. 처음에는 Rapfi 버그를 의심했다. 하지만 로그를 따라가 보니 문제는 내 엔진 안에 있었다.
로그를 AI에게 다시 보여주고 원인을 분석하게 했다.
원인은 타임아웃 처리 누락이었다.
Minimax 엔진의 Alpha-Beta 탐색은 가상으로 돌을 놓고 회수하면서 검색한다:
for row, col in moves:
board.grid[row][col] = color
value = self._alpha_beta(...)
board.grid[row][col] = Board.EMPTY # 타임아웃 발생 시 실행 안 됨
시간 초과 예외가 발생하면 Board.EMPTY가 실행되지 않고 돌이 보드에 영원히 남는다. 이 유령 돌 때문에 Rapfi가 정상적으로 수를 두었지만 Python 보드에서는 이미 돌이 있어서 "invalid move"가 발생, Rapfi가 억울하게 패배 처리되었다.
AI가 원인을 찾고 스스로 코드를 수정했다. 해결은 단 3줄:
try:
value = self._alpha_beta(...)
finally:
board.grid[row][col] = Board.EMPTY
수정 요청 → AI가 코드 수정 → 재대결.
5. 제대로 된 결과
드디어 정상적인 결과가 나왔다.
Minimax(depth 4, 10s) vs Rapfi(NNUE, 10s) — 5판 대결
| 게임 | 승자 | 턴 | 비고 |
|---|---|---|---|
| 1 | Rapfi | 22 | L5 5목 완성 |
| 2 | Rapfi | 22 | 동일 수순 |
| 3 | Rapfi | 22 | |
| 4 | Rapfi | 22 | |
| 5 | Rapfi | 22 | |
| 종합 | Rapfi 5:0 | 22수 | Invalid move: 0 |
Minimax가 결정론적(난수 시드 고정)이라 5게임 모두 동일한 수순이 나왔다.
Turn 1: ● Minimax H8
Turn 2: ○ Rapfi G7 [5.0s]
...
Turn 22: ○ Rapfi L5 [5.0s] 5목!
6. 정리
| 단계 | 상태 | 결과 | 원인 |
|---|---|---|---|
| Stage 1 | Rapfi NNUE 비활성화 | Minimax 3:0 | AI가 생성한 코드의 LZ4 처리 방식 |
| Stage 2 | 유령 돌 버그 | Minimax 2:1 | AI가 생성한 코드의 타임아웃 처리 누락 |
| Stage 3 | 모든 버그 수정 | Rapfi 5:0 | 정상 결과 |
AI는 정상적인 흐름의 코드는 빠르게 구현했다. 하지만 파일 포맷 호환성이나 예외 처리 같은 엣지 케이스는 사람이 함께 검증해야 했다.
예상보다 너무 좋은 결과가 나왔다면, 환경을 의심해볼 필요가 있다.
성능이 갑자기 두 배가 나오면 "내가 천재인가?"가 아니라 "어디 버그 난 거 아니야?" 부터 생각하는 게 개발자의 습관이다. 이번 실험은 그 습관이 얼마나 중요한지 직접 경험하게 해준 사례였다.
7. 이제부터가 진짜 시작
이제부터는 버그를 잡는 단계가 아니라 실력을 키우는 단계다.
AI가 만든 오목 엔진은 과연 Rapfi를 상대로 단 1승이라도 거둘 수 있을까?
그 실험은 다음 편에서 이어진다.
실험 엔진: Deepseek v4 Flash (OpenCode)
상대 엔진: Rapfi by dhbloo (github.com/dhbloo/rapfi)
하드웨어: NVIDIA DGX Spark (ARM64, Grace ARM CPU, 128GB RAM)
전체 코드: 추후 오픈소스 공개 예정
DevSnack AI Lab — AI를 소비하는 채널이 아니라, AI를 실험하는 연구실. 실패와 시행착오도 기록합니다.