SSH로 즐기는 멀티플레이어 스네이크 게임, 1초에 1억 픽셀 렌더링!
SSH를 통해 접속 가능한 멀티플레이어 스네이크 게임 'snakes.run'의 기술적 구현 방식을 소개함
터미널 렌더링(Terminal Rendering)을 위해 유니코드 블록 요소(Unicode Block Elements)를 활용하여 픽셀 표현의 효율성을 높임
초기 대역폭 문제(Bandwidth Problem) 해결을 위해 VT100 시퀀스(VT100 Sequences)를 활용한 상태 기반 렌더링(Stateful Rendering) 기법을 적용
성능 최적화(Performance Optimization)를 위해 문자열 할당 최소화 및 SSH 클라이언트의 키 입력 시간 난독화(Keystroke Timing Obfuscation) 제거
터미널 렌더링 최적화: 유니코드 블록 요소와 VT100 시퀀스
저자는 터미널 기반 렌더링에서 유니코드 블록 요소(Unicode Block Elements)를 사용하여 픽셀 밀도를 높였다. 특히, 수직/수평 이동 시 부자연스러운 움직임을 개선하기 위해 상/하 블록(Upper/Lower Block)을 활용하여 2개의 픽셀을 표현했다. 또한, VT100 시퀀스(VT100 Sequences)를 사용하여 변경된 셀만 업데이트하는 방식으로 대역폭을 절감했다. 이러한 접근 방식은 SSH 환경에서 효율적인 렌더링(Efficient Rendering)을 가능하게 한다.
대역폭 절감을 위한 상태 기반 렌더링
초기 렌더링 방식은 각 프레임마다 전체 화면을 다시 전송하여 과도한 대역폭을 사용했다. 이를 해결하기 위해 저자는 상태 기반 렌더링(Stateful Rendering)을 도입하여 변경된 부분만 전송하는 방식으로 개선했다. 구체적으로, VT100 시퀀스(VT100 Sequences)를 활용하여 커서를 이동시키고, 특정 위치의 문자를 변경하는 방식을 사용했다. 그 결과, 대역폭 사용량을 획기적으로 줄일 수 있었다.
성능 향상을 위한 문자열 할당 최소화
성능 프로파일링 결과, 문자열 처리 관련 함수에서 많은 CPU 시간을 소비하는 것을 확인했다. 이를 해결하기 위해 저자는 문자열 할당(String Allocation)을 최소화하는 방식으로 최적화를 진행했다. 구체적으로, 자주 사용되는 문자열을 미리 할당하여 캐싱(Caching)하고, 런타임 시 동적 할당을 피했다. 이러한 방법은 가비지 컬렉션(Garbage Collection) 시간을 줄여 전반적인 성능을 향상시켰다.
SSH 클라이언트 최적화: 키 입력 시간 난독화 제거
저자는 SSH 클라이언트의 키 입력 시간 난독화(Keystroke Timing Obfuscation) 기능이 성능 저하의 원인임을 파악했다. 이 기능은 보안을 위해 추가되었지만, 불필요한 패킷 전송을 유발하여 서버의 성능을 저하시켰다. 저자는 해당 기능을 제거하기 위해 go의 암호화 라이브러리(Crypto Library)를 포크(Fork)하여 수정했다. 그 결과, 게임의 성능이 약 2배 향상되었다.