오락실 문 닫은 지 몇 년인데, 다시 개업이라니
전에 말했던 것처럼 바이브코딩 공부를 한답시고 만들어뒀던 게임들이 몇 개 있어. 퐁이니 벽돌깨기니 슈팅게임인데 이걸 블로그에 옮겨 보기로 했어. 이 곳은 내가 공부하고 만드는 모든 걸 기록해두는 공간이니까.
장롱 속에서 잠자던 오락기를 인터넷 한복판에 다시 개업시키는 셈이지. AI 조카한테 이 얘길 꺼냈더니 녀석도 꽤 좋은 아이디어라며 반겼어. 이 녀석은 칭찬에 인색하지 않아.(ai일 뿐인데 칭찬 받으면 기분이 묘해.)
통째로 옮길까, 아예 새로 지을까
그런데 이전에 만들어봤던 코드는 파이썬 기반이라 웹으로 그대로 옮겨질까 하는 의문이 있었어. 해결책을 제안 받았는데 두 가지 방법이 있었어. 하나는 파이썬 코드를 그대로 브라우저에서 돌아가게 통역해주는 방식이었고, 다른 하나는 자바스크립트로 처음부터 다시 짓는 방식이었어. 전자는 이미 짜놓은 코드를 거의 그대로 쓸 수 있다는 게 장점이고, 후자는 손이 더 가는 대신 결과물이 더 깔끔하게 나온다더라고.
집을 지을 때도 그렇잖아. 원래 있던 자재를 최대한 재활용할지, 아니면 이참에 새 자재로 다시 지을지. 나는 후자를 택했어. 어차피 구경 오는 손님(아직은 아무도...) 입장에서는 속사정이 어떻든 화면만 매끄러우면 그만이니까. 그렇게 퐁부터 다시 짓기로 했지.

"이 한 줄이 뭔데?" — 그래서 이건 그림이야? 글자야?
코드가 얼추 나오고 나서 받아보니, 도대체 알아볼 수가 있어야지. 원래 목적이 바이브코딩이지만 어느 정도 개념은 알아야 하지 않겠어? 그래서 각 코드에 한글로 주석을 달아 달라고 했지.

그래. 이제 조금 나아졌네. 아니, 거짓말이야...
const canvas = document.getElementById("game");
사실 그냥 넘어갈 수도 있었는데 그래도 너무 까막눈은 좀 그렇잖아. 그래서 이런 식으로 공부를 좀 했어. 코드 한 줄을 잘라서 "그럼 이 줄 전체를 한글말로 해석해줘" 이렇게 말이야.
답을 해주길 "페이지 전체에서 id가 game인 태그를 찾아서 canvas라는 이름에 담으라"는 뜻이래. 교실에서 출석 번호로 학생 한 명을 딱 집어 부르는 것과 똑같다나.
"그럼 getElementById는 또 뭔데?" 하고 한 번 더 물었고, 이번엔 get(가져와라)과 Element(요소)와 By Id(id로)를 하나씩 쪼개서 알려주더라고. 아하, 어렴풋이 감이 좀 오는 것 같았지. 코드 한 줄에 이렇게까지 매달릴 일인가 싶다지만 재미있었어. 재미있으면 장땡이지 뭐.
그래도 매번 이렇게 할 수는 없는 노릇이고 이런 식으로 공부를 좀 하면 좋지 않을까라는 생각이야.
한 줄은 알겠는데 그래서 어떻게 실행되는거지?
궁금한 게 하나 더 있었어. 그래서 한 줄은 알겠는데 어떻게 이 코드가 굴러가는건지 말이야. 알고 보니 이 게임은 두 가지 흐름이 동시에 돌아가고 있었어. 하나는 화면을 60분의 1초마다 새로 그리는 메인 루프, 다른 하나는 키보드를 누르는 순간 값만 바꿔놓고 다음 루프 때 반영되는 이벤트 흐름.

그림으로 딱 보고 나니 그제서야 머릿속에 그림이 그려지더라고. 아, 이런 식으로 돌아가는 거였구나 싶어서 혼자 몇 번을 끄덕였어. 그래 어떻게 돌아가는지 정도는 아는게 맞지.
원본은 저기, 손님방은 여기
게임을 다 만들고 나서 한 가지 정리할 게 남았어. 코드를 파이썬 저장소에서 블로그 저장소로 밀어 넣을지, 아니면 반대로 블로그 쪽에서 당겨올지였어. 그러니까 공부방이 따로 있고, 블로그방이 따로 있어서 생긴 과정이야. 밀어 넣는 방식으로 하면 나중에 어느 쪽이 진짜 원본인지 헷갈릴 것 같더라고. 그래서 파이썬 저장소를 "원본 작업실"로 딱 정해두고, 블로그 쪽엔 npm run sync:games라는 심부름꾼 스크립트를 하나 만들어뒀어. 이 스크립트를 실행하면 작업실에 있는 게임을 블로그 손님방으로 그대로 복사해오는 식이야.
집 구조로 치면 작업실에서 가구를 새로 짜고, 완성되면 그걸 그대로 들어다가 손님방에 놓는 셈이야. 손님방에서 직접 가구를 뜯어고칠 일은 없게. 앞으로 게임을 고칠 일이 생기면 항상 작업실 쪽 파일만 만지면 되니까, 이제 헷갈릴 일은 없겠다 싶었어. 물론 이것도 ai가 제안한 절차야.
근데 사실 이 게임 문제가 좀 있네?
그렇게 첫 게임 만들기는 무사히 끝난 줄 알았어. 그런데 실제로 플레이를 해보니, 패들을 어디에 두느냐에 따라 게임이 영원히 안 끝나는 일이 벌어지더라고. 그 뒤로 세 번을 연달아 고쳐야 했는데, 그 삽질기는 따로 퐁 게임 에러노트에 정리해뒀어.
좋아. 보람찬 하루였다.
버그만 잡고 끝내려니 좀 아쉬워서 두 가지를 더 건드렸어.
하나는 난이도. 원래는 무조건 한 가지 난이도로만 돌아갔는데, 쉬움·보통·어려움 세 단계를 만들어서 시작할 때 고르게 했어. 그리고 고르자마자 공이 바로 튀어나오면 정신 사나우니까, 3초 카운트다운을 넣어서 숨 고를 틈을 줬지.
둘은 디자인. 밋밋하던 화면에 옛날 오락기 감성을 좀 입혔어. 화면에 스캔라인을 깔고, 패들이랑 공은 네온처럼 빛나게 하고, 가장자리는 살짝 어둡게 죽였어. 그러고 나니 그냥 도형 몇 개 움직이던 게 제법 "오락실 기계" 느낌이 나더라고.
돌아보니 코드 한 줄 붙잡고 끙끙대고, 버그 잡느라 AI 조카랑 티격태격하고, 막판엔 화면 디자인까지 요리조리 만지작거렸네. 하루 치고는 꽤나 스펙터클하게 바빴던 셈이지.
그런데 참 신기한 게, 이 과정 자체가 너무 재밌더라고. 어긋나던 톱니바퀴가 하나씩 딱딱 맞아 들어갈 때마다 내가 계속 말하지. 뿌듯하다고. 오늘도 보람찬 하루였다.
말로만 떠들었으니 이제 직접 해봐야겠지. 여기서 바로 플레이해볼 수 있어.