CSS로 플래피 버드를 플레이하는 신경망을 돌리고 있음. 진짜로, CSS로 말이야.
CSS is running a neural network to play Flappy Bird. Yes, actual CSS.
핵심 요약
CSS의 연산 기능을 활용해 플래피 버드를 플레이하는 신경망을 구현한 독창적인 프로젝트.
- CSS 신경망 구현 — CSS의 calc, max, exp 함수를 사용해 신경망 추론을 수행함.
- 플래피 버드 학습 — PPO 강화학습을 통해 6-16-1 구조의 MLP 모델을 학습시킴.
- 실시간 시각화 — 브라우저에서 신경망 활성화 상태를 실시간으로 확인 가능함.
- 성능 검증 — 파이썬 모델과 비교하여 오차 없는 정확한 추론 결과를 보여줌.

신경망 추론이 전부 CSS에서 돌아가는 플래피 버드 클론을 만들어 봤다.
오픈 소스: https://github.com/veuler/flappynn
TensorFlow.js도 없고, WebGPU도 없다. 숨겨진 자바스크립트 추론 같은 것도 당연히 없음.
자바스크립트는 그냥 게임 돌리고 현재 상태를 CSS로 넘겨주는 역할만 한다. 신경망 자체는 CSS의 calc(), max(), exp()를 써서 가중치 합산, ReLU 활성화 함수, 그리고 최종 시그모이드 출력까지 다 처리함.
자바스크립트 코드는 ChatGPT한테 도움 좀 받았고, 메인 아이디어는 내가 짰다. 플래피 버드 게임 부분도 ChatGPT랑 같이 만들었음.
뉴런 하나를 CSS로 옮기면 대충 이런 식이다:
--h1-z: calc(
var(--bird-y) * 0.72 +
var(--velocity-y) * -0.31 +
var(--pipe-distance) * 0.18 +
var(--gap-y) * 0.44 +
var(--pipe-speed) * 0.27 + 0.14 );
--h1: max(0, var(--h1-z));
--jump-probability: calc(1 / (1 + exp(-1 * var(--output-z))));
이번에 만든 모델은 129개의 학습 가능한 파라미터를 가진 6 → 16 → 1 MLP 구조다.
입력값은 다음과 같음:
새 위치 + 수직 속도 + 다음 파이프 거리 + 다음 틈새 위치 + 파이프 속도 + 그다음 파이프의 틈새 위치
→ 16개의 은닉 뉴런
→ 점프 / 대기
여섯 번째 입력값이 작지만 꽤 흥미로운 변화인데, 이제 네트워크가 바로 앞 파이프만 보고 반응하는 게 아니라 두 개의 틈새를 미리 볼 수 있게 됐다.
추론은 20Hz, 즉 1초에 20번씩 신경망이 판단을 내린다. 새 모델은 순전파 한 번당 112번의 가중치 곱셈을 수행하니까, CSS 연산으로 초당 약 2,240번의 가중치 곱셈을 하는 셈이다.
학습은 PPO 강화학습으로 돌렸다. CPU에서 512개의 게임 환경을 병렬로 돌리는 중이다. 얘네들이 전부 같은 액터/크리틱 쌍을 위해 데이터를 뽑아내고, 최종적으로 학습된 액터만 CSS로 내보낸다.

