개발 노트
야호는 어떻게 수를 고를까
pqp Team ·
규칙 판정과 AI 탐색, 화면의 기다림은 서로 다른 역할입니다. 웹 워커를 활용한 연산 분리와 자연스러운 착수 템포를 조율하는 설계 원리를 살펴봅니다.
규칙 판정과 탐색 엔진의 2계층 분리 구조
pqp 미니게임 플랫폼에서 AI 봇 '야호'와 대국할 때 가장 먼저 체감되는 특징은 화면이 단 1프레임도 버벅거리지 않고 매끄럽게 반응한다는 점입니다. 복잡한 오목 수읽기나 체스 탐색을 브라우저에서 돌리면서도 사용자 인터페이스가 쾌적하게 유지되는 비결은 철저한 '2계층 아키텍처 분리'에 있어요. pqp 도구는 탐색 조율기와 엔진 관리자를 통해 이 분리 원칙을 매우 명확하게 구현하고 있어요.
첫 번째 계층은 '규칙 판정 계층'입니다. 이 계층은 오목의 렌주룰 금수 판정, 리버시의 돌 뒤집기 및 합법수 검사, 커넥트4의 중력 낙하와 4목 승리 체크처럼 게임의 물리적 규칙만을 담당해요. 순수 함수와 동기식(synchronous) 코드로 작성되어 부수 효과(side-effect)가 전혀 없으며, 판면 상태가 주어지면 마이크로초 단위의 극히 짧은 시간에 즉각적인 참과 거짓을 반환합니다.
두 번째 계층은 '인공지능 탐색 계층(백그라운드 웹 워커)'입니다. 알파베타 가지치기, 미니맥스, 몬테카를로 트리 탐색(MCTS), 비트보드 연산 등 깊은 수읽기를 전담하는 무거운 엔진들이 여기에 속해요. 체스 스톡피시나 오목 랩피(Rapfi) 같은 전문 분석 엔진은 메인 UI 스레드가 아닌 백그라운드 웹 워커(Web Worker) 내부에서 완전히 격리되어 비동기로 실행됩니다. 메인 스레드는 웹 워커에 '현재 기보'만을 메시지로 전달하고, 워커가 수천만 개의 노드를 탐색하는 동안에도 브라우저는 60프레임의 부드러운 렌더링을 변함없이 유지합니다.
pqp 엔진 관리자는 난이도에 따라 워커 엔진에 주어지는 연산 시간 예산(time budget)을 엄격하게 제한해요. 초급 모드는 500밀리초(0.5초), 중급 모드는 3,000밀리초(3초), 고급 모드는 30,000밀리초(30초)의 타임아웃을 강제하여 브라우저 메모리 폭주와 배터리 과소비를 철저히 방어합니다.
다음 표는 야호 시스템의 2계층 구조와 스레드 분리 역할을 비교한 명세표입니다.
| 계층 구분 | 담당 모듈 | 실행 스레드 | 주요 역할과 연산 특성 |
|---|---|---|---|
| 규칙 판정 계층 | 규칙 판정 모듈 | 메인 UI 스레드 | 동기식 순수 함수, 합법수 판정, 승패 및 무승부 확인 |
| 탐색 엔진 계층 | 탐색 연산 모듈 | 백그라운드 웹 워커 | 비동기 탐색, 비트보드 연산, 수읽기 평가치 산출 |
| 템포 조율 계층 | 착수 템포 조율 모듈 | 메인 UI 스레드 | 엔진 연산과 착수 연출 분리, 인간적 호흡 지연 적용 |
이러한 계층 분리가 완성되어 있기에 고난도 인공지능을 웹 브라우저 환경에서도 부담 없이 구동할 수 있습니다.
인간적 착수 템포와 25퍼센트 망설임 알고리즘
체스나 오목 엔진은 단순한 외길 수순이나 당연한 한 수를 만났을 때 단 5밀리초 만에 계산을 끝마칩니다. 하지만 AI가 플레이어의 착수가 끝나자마자 0.005초 만에 빛의 속도로 돌을 얹어버리면, 사람은 기계적인 위압감을 느끼고 대국의 흥미를 잃게 돼요. 반대로 복잡한 형세에서 3초 동안 아무런 반응 없이 화면이 굳어 있으면 프로그램이 멈춘 것인지 착각하게 됩니다. pqp는 이 간극을 메우기 위해 인간적 착수 템포 조율 모듈을 도입하여 엔진 계산 시간과 화면 착수 시점을 의도적으로 분리했어요.
첫 번째 예시로 리버시 중반에서 외길 강제수가 발생한 상황을 추적해 보겠습니다. 플레이어가 착수한 뒤 야호 봇이 둘 수 있는 합법수가 단 한 칸뿐인 경우, 웹 워커 엔진은 8밀리초 만에 다음 착수 좌표를 메인 스레드로 전송합니다. 이때 착수 템포 조율 모듈은 엔진의 조기 응답을 그대로 화면에 그리지 않고 외길 강제수 지연 범위(500밀리초~1,200밀리초)를 스케줄러에 적용해요. 플레이어가 방금 둔 돌의 그래픽 애니메이션이 끝나고 숨을 고를 수 있도록 800밀리초 안팎의 시점에 부드럽게 착수를 연출하는 방식이에요.
두 번째 예시로 오목이나 체스의 치열한 중후반 접전 상황을 살펴보겠습니다. 외길 강제수가 아닌 일반 착수 국면에서는 25퍼센트(0.25)의 확률로 '망설임(hesitation)' 난수 조건이 발동해요. 이때 착수 지연 범위는 난이도에 따라 2,000밀리초에서 최대 6,000밀리초까지 넓어지며, 망설임이 켜지면 착수 손길 연출에 250밀리초가 추가되어 마치 사람이 신중하게 고민하다 돌을 내려놓는 듯한 자연스러운 리듬을 자아냅니다. 반면 상대의 5목 공격을 즉각 차단해야 하는 절체절명의 외길 수비수 상황에서는 망설임 조건을 제외하고 강제수 지연 범위(500밀리초~1,200밀리초)에 맞춰 단호하게 대응하도록 설계되어 있어요.
반대로 게임 초반 포석 단계에서는 800밀리초에서 2,000밀리초 사이의 경쾌한 딜레이 밴드로 맞받아쳐 실제 캐주얼한 대면 대국을 치르는 듯한 안정적인 리듬감을 선사해요. 이처럼 수학적 확률과 밴드 지연을 조합하여 기계 특유의 차가운 반응성을 지우고 살아 숨 쉬는 인공지능의 호흡을 빚어냈습니다.
웹 워커 엔진 연동 시 겪는 기술적 난제
브라우저 기반 AI 엔진을 구축할 때 개발자들이 흔히 저지르는 실수는 메인 스레드와 웹 워커 간에 너무 방대한 객체 데이터를 매 턴 문자열로 직렬화하여 주고받는 것입니다. 매 착수마다 전체 탐색 트리나 수만 개의 보드 상태 배열을 복사하면 구조화된 복제(structured clone) 과정에서 가비지 컬렉션(GC) 병목이 발생해 화면 프레임이 뚝뚝 끊기게 돼요.
pqp는 이를 방지하기 위해 워커 간 통신 메시지를 FEN 문자열이나 16진수 비트보드 숫자, 착수 히스토리 배열과 같이 필요한 핵심 데이터만 담은 가벼운 자바스크립트 객체 형태로 전달하도록 최적화했어요.
또 다른 난제는 사용자가 대국 도중 '무르기'를 누르거나 판을 리셋했을 때 발생하는 레이스 컨디션(race condition)입니다. 이전 판의 30초짜리 장고 연산이 백그라운드 워커에서 뒤늦게 끝나 메인 스레드로 전달되면, 새로 시작된 대국 판면에 이전 판의 착수가 엉뚱하게 덮어씌워지는 치명적인 버그가 생길 수 있습니다. pqp는 요청 식별자와 판면 수정 번호, 세대 식별자를 대조하는 다중 검증 시스템을 도입했어요. 워커가 연산을 마쳤더라도 현재 판면의 식별자와 일치하지 않으면 결과를 즉시 폐기하고, 사용자가 무르기를 누르거나 취소하면 실행 중인 워커를 강제 종료하여 동시성 안전성을 확립했습니다.
pqp에서 야호 봇의 생각 리듬 관찰하기
pqp 오목이나 리버시 게임을 실행하고 야호 봇의 난이도를 초급, 중급, 고급으로 변경해 가면서 대국을 진행해 보세요. 하단에 표시되는 AI 생각 게이지와 실제 돌이 놓이는 시간 간격을 눈여겨보는 훈련입니다.
초반 몇 수에서는 야호가 거침없이 빠른 속도로 응수하다가, 전투가 치열해지는 중반 요충지에 이르면 잠시 호흡을 멈추고 장고에 들어가는 템포의 완급 조절을 관찰할 수 있습니다. 특히 외길 강제수가 아닌 팽팽한 호각 국면에서 간헐적으로 터져 나오는 25퍼센트 망설임 연출 구간을 찾아보세요.
엔진이 단순히 정답 좌표만을 찾는 기계가 아니라 플레이어와 교감하는 상대방으로 느껴지도록 조율된 내부 알고리즘의 묘미를 음미하면서 더욱 깊이 있는 대국 경험을 즐겨 보세요.
확인한 자료와 정정 문의
이 글은 아래 구현과 예시를 기준으로 썼습니다. 도구의 모형과 실제 게임의 최신 규칙이 다른 경우에는 게임 공지를 먼저 확인해주세요. 잘못된 설명은 운영자에게 알려주세요.
- pqp 미니게임의 엔진 총괄 매니저와 작업 분배 구조
- 웹 워커 백그라운드 탐색 연산 스레드 구현
- 인간적인 착수 호흡과 망설임 딜레이를 조율하는 템포 제어 시스템
해보기
설명한 규칙을 직접 확인해보세요.