좀비지구 개발일지 (4)

다른 일이 많아서 요즘 개발 진척이 좀 더뎠다.

학교를 세우고 수업을 듣게 만들었다. 학교의 종을 울리면 선생님(?)과 학생(?)이 학교 안으로 모여든다.

원래서 선생님 한 명, 학생 네 명 이렇게 수업이 진행되어야 하지만, 기존에 학교에서 떠돌던 아이를 내보내는 기능이 없어서 교탁 옆에서 수업을 방해하는 모습이다.

그나저나 대체 왜 수업 듣는데 통나무를 다 들고 온 것이냐…

그리고 네비게이션 메시 기능도 써 봤다. 잘 작동하는 것 같다.



좀비지구 개발일지 (2)

실내와 실외를 연결하는 기능을 정리했다. 위 스크린샷의 하단부는 실외이고, 초가집 내부 모습이 상단에 나타나있다. 문을 통해서 두 공간을 오갈 수 있다. 독(dock) 모드에서는 위와 같고, 전체 화면으로 했을 때는 아래와 같은 모습이다.

이번에 코드를 완전히 다시 작성하게 된 계기가 이 실내/실외 이동 관련한 구현이 버그가 워낙 많았기 때문인 것도 있다.

  1. 독 모드에서는 실내 팝업이 독자적인 윈도우로 나와야 한다.
  2. 전체화면 모드에서는 실내 팝업이 게임 내 팝업으로 나와야 한다.

말로 하면 참 쉽고 간결했고, 바이브 코딩으로 구현을 시킬 때도 잘 되는 것처럼 보였다. 그러나 몇 번 전체화면 모드와 독 모드를 토글링하면 런타임 퍼포먼스(즉, fps)가 극단적으로 내려갔고 이를 수정하지 못했다.

이번에는 모든 클래스 목록을 내가 직접 정했고, 각 클래스의 책임과 한계에 대해서 하나씩 구현해나가며 최대한 알려주는 방향으로 훨씬 더 좁은 보폭으로 AI에게 일을 시켰다. 예를 들어, 예전 바이브 코딩에서는 “실내로도 들어갈 수 있게 하는데, 문으로 가서 페이드아웃되고 실내 문에서 페이드인되면 된다.” 수준이었다면 이번에는 “각 공간은 ZPlace란 클래스로 표현된다. ZPlace는 ZPortal이라는 자식을 가질 수도 있다. 서로 다른 ZPortal은 서로 연결되며, 이에 따라 서로 다른 두 ZPlace가 ZPortal에 의해 연결되는 구조이다. 폰(pawn)은 ZPortal 근처로 가서 거기에 연결된 다른 ZPortal로 순간이동할 수 있는데, 순간이동은 연출 절차는 페이드인/페이드아웃이다.” 정도로 자세히 안내했다. 이동 좌표에 대해서도 예전엔 아무 이야기 안해서 도대체 어떻게 구현했는지 실외 이동 범위를 자꾸 벗어나서 어디론가 가는지도 몰랐는데 이번에는 “이동 보간은 ZPlace의 로컬 좌표로서만 처리한다” 등 좀 더 자세한 지침을 바로바로 알아듣는 상태가 되었다.

실내-실외의 연결을 그래프로 이해하는 것은 간단히 키워드만 던져주니 알아서 잘 하는 것으로 보였다. 예를 들어 실내에 있을 때는 ‘벌목’을 하고 싶어도 할 수가 없다. 실내라는 ZPlace안에 나무가 없기 때문이다. 그러나 존재하는 ZPortal을 탐색해서 이동 가능한 다른 ZPlace까지도 검색 범위를 넓히라고 했더니, 실외의 나무까지 탐색이 됐고, 이동을 위해 만든 ZMoveJob의 복잡화된 버전인 ZComplexMoveJob을 만들라고 해서 임의의 ZPlace의 임의 로컬 좌표를 목적지로 하는 작업도 한번에 잘 만들었다.

여전히 모든 코드는 내가 코드 리딩하고 리뷰하면서 작업하고 있어서 개발 속도는 4-5배는 느려진 것 같으나, 결과적으로 어떤 일이 일어나고 있는지를 다 알고 진행하고 있기 때문에 괴상하고 도저히 알아볼 수 없는 이상한 코드로 발산하는 것은 선제적으로 막을 수 있게 됐다.

코드 리뷰 과정에서 내가 AI에게 자주 묻는 질문과 답은 다음과 같은 카테고리 중 하나다.

  • “이 멤버 변수가 꼭 필요한가요?” => “꼭 필요하진 않습니다”
  • “이 프로퍼티에 true를 설정한 이유가 있습니까?” => “반드시 그래야만 하는 것은 아닙니다”
  • “이 값은 다른 값에 이미 참조가 걸려 멤버 변수로 따로 들고 있을 필요가 없어 보입니다.” =>”그 참조가 불변이라는 가정이 있다면 필요 없는 것이 맞습니다”

특히나 세 번째가 좀 재밌었는데, 의외로 내가 암묵적인 가정을 많이 하고 있다는 점이었다. 예를 들어 아까 이야기한 “ZPortal을 통해 ZPlace가 연결된다”는 부분에서 ZPortal과 연결된 ZPlace가 불변이라는 가정을 나는 당연히 했는데, AI는 그런 가정을 하지 않아서 발생한 문제였다. 결과적으로는 과한 구현이었지만, 명시적이지 않은 부분에 대해 매우 방어적으로 구현하고, 그에 따라 나중에 걷잡을 수 없는 이상한 버그를 만들 가능성도 있는 그런 부분이긴 하지만… 암묵적 가정을 나도 모르게 정해둔 부분을 잘 잡아내는 것이 AI의 장점이 극대화된 부분인 것 같기도 하다.


좀비지구 개발일지 (1)

한국어로는 좀비지구, 영어로는 Zombieearth다. 한 단어처럼 쓰면 더 멋있어 보여서 영어로는 한 단어로 만들었다!

어디에 개발일지를 쓸까 고민하다가 무려 유료로 서버를 운영 중인 이곳이 가장 돈을 덜 쓰는 방법이란 판단이 들어서 작성한다.

2026-07-27에 비버롹스 출품을 하기 전 1주일 가량을 Codex로 바이브코딩했으나, 출품 직전 막바지에 AI가 너무나 바보짓을 많이하는 바람에(=내가 마감 직전 이것저것 갑자기 많이 시키는 바람에) 굉장히 아슬아슬하게 되던 기능도 많이 망가진 상태로 제출할 수 밖에 없게 되었다.

2026-07-28 이후부터 바이브코딩은 혼자 기능을 보기에는 좋지만 누군가에게 보여주기에는 확실히 부족한 점이 많다고 판단하여 코드를 100% 검수하는(이상적으로는 내가 작성했다고 말할 수 있을 정도로) 방식으로 처음부터 다시 코드를 작성하기 시작했다.

사용하는 엔진은 Godot인데, gdscript를 제대로 읽어보는 것이 이번이 처음이었다. 올해 3월부터 쓰기 시작했지만 이제서야 진지하게 읽어보고 있다.

원대한 계획은 itch.io에 빌드를 올리며 업데이트 노트를 쓰는 겸 개발일지를 쓰는 것이었지만, 그건 던전 지도 제작자 개발하며 그 실행이 꽤 너무나 어려움을 느끼고(이것도 100% 바이브 코딩이었는데, 버그 때문에 막혔다기보다 기획 및 스토리 때문에 막혔다) 일단 가볍게 글만 싸질러도 괜찮은 블로그 형태로 남겨보려고 한다.

과연 이것은 몇 회까지나 쓸 것인가…?




지난 1년 간 있었던 일

공교롭게도 작년에 포스팅을 마지막으로 남긴지 딱 1년만에 다시 포스팅을 남길 수 있게 되었는데, 그 1년간 있었던 일을 딱 정리하기 적절한 타이밍인 것 같아 간략히 남긴다.

그동안 다른 프로그래머 한 분과 아티스트 한 분을 모아 새 게임을 만들어 출시했다. Google Play, Apple App Store, Steam 이렇게 세 개 마켓에 공개했다. Steam은 Windows, macOS 모두 지원한다. 그래서 기기 종류로 보면 무려 4개에 출시한 셈이다. (ㅎㅎㅎ)

Google Play: https://play.google.com/store/apps/details?id=top.plusalpha.ripper

Apple App Store: https://apps.apple.com/kr/app/id6504069833

Steam: https://store.steampowered.com/app/2282770

마켓 페이지에 가장 공을 들이고 가장 최신인 것은 Steam이니, 셋 중 하나를 고르라면 마지막 링크를 추천한다.

그동안 열심히 개발했으나 유입은 거의 없는 편이다. 그래도 2025년 10월까지는 지난 1년간 해 온 것처럼 개발해보고자 한다.

조금씩 조금씩 게임이 발전해나가는 것을 보고, 또 참여하는 경험이 역시 재밌다.

유튜버 리뷰도 무려 있다. 후후…

<킷싱>님

<Rhode Gamer>님

<강타몬>님

<숲속의늑대>님

<아기강무무>님


워드프레스 글을 다시 올리며…

그간 포스트를 두어차례 쓰고 싶었지만 쓸 수 없었다.

IPv4 유료화 이후 서버 한 대로 IPv4 할당을 줄인 후 거기에 워드프레스 서버를 리버스 프록시로 연결해서 쓰는 방식을 썼었다. (워드프레스 서버는 IPv6만 할당받음)

그런데 이렇게 하니까 워드프레스 페이지 접속은 전혀 문제 없었지만, /admin 페이지만 404 오류가 발생하는 문제가 있었다.

워드프레스 서버에 IPv4를 할당해서 직접 접속하면 나지 않는 오류였다.

잘 되는 경우가 있기에 별 문제 아니겠거니하고 그 때마다 잠깐 잠깐 인터넷 검색해서 해결해보려고 했으나 늘 잘 안됐다.

그러다가 오늘 좀 제대로 살펴봐야겠다하면서 점심 식사 직전부터 문제를 진지하게 파기 시작했다.

nginx 리버스 프록시가 문제를 유발하는 것은 확실했다. 그쪽 로그를 보니 힌트를 얻을 수 있었다. 결정적 힌트였지만, 결정적 오해를 하는 바람에 3시간 가까이를 날려먹고 겨우 해결했다. 그 로그란…

2025/06/28 05:28:20 [error] 25456#25456: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream [이하 생략]

일반 페이지 접근 시에는 나지 않고, /admin 접근 할때만 났으니 이 메시지가 관련 있음은 명백했다.

cgi는 대학생 때 들어나 보고, PHP도 그냥 튜토리얼만 본 수준의 나로서는 FastCGI는 완전히 모르는 키워드였다.

그래서 열심히 구글링도 해보고 AI한테도 물어보고 해서 시키는대로 이게 뭔지도 모르고 다 해봤는데, 해결이 되지 않았다. 그래도 진전이 있었는데, 최소한 404 오류가 나던 것을 nginx 오류로 바꿨다는 점이다.

영향을 주는 부분을 건드리고 있다는 것에 확신이 찬 나머지 많은 시간을 써서 여러 시도를 해 봤지만 해결되지 않았다.

구글링 키워드는 리버스 프록시, nginx, bitnami wordpress, fastcgi 등 핵심 키워드라고 생각하는 것을 넣었는데, 위 로그 메시지와 동일한 질문도 몇 건 보여서 하라는대로 했지만 역시 잘 안됐다.

키워드를 잘못 골랐음이 점점 분명해졌다. 나처럼 bitnami wordpress를 다른 서버에서 리버스 프록시로 접근하는 사례도 거의 없을거고 (취미의 영역)

그리고 reverse proxy란 건 매우 단순해서 그냥 모든 요청을 릴레이해주고, 응답을 릴레이해주면 끝인데, 대체 FastCGI 오류가 날 이유가 뭐가 있단 말인가? 백엔드 서버가 어떻게 구성되었든 리버스 프록시는 그 설정에 영향이 없었어야 함이 맞는데, 그걸 잊고 내가 겪는 문제와는 상관 없는(하지만 대다수의 사람들이 고생하는 일반적인 FastCGI 설정 오류와 직결되는) 것에 빠져든 것이다.

이상한 걸 느끼며 키워드를 이것저것 빼가며 검색해보던 중 “결정적 제보”를 발견하고야 말았다.

https://www.zabbix.com/forum/zabbix-help/461821-zabbix-behind-nginx-reverse-proxy-proxy_pass

zabbix는 전혀 모르는 것이지만, 오류 메시지가 동일해서 검색되었다.

거기에 답변 중 하나로 발견하게 되었다… “nginx의 설정 중 .php 파일을 로컬에서 처리하는 부분을 삭제해봐라”였다.

정확히 그 문제였다. 내가 php, fastcgi 설정을 미비해서 오류가 난 게 아니라, 내가 하지 않은 어떠한 다른 설정이 영향을 줘서 문제가 일어난 것이었다.

.php의 특별 처리는 nginx 기본 설정에 들어있었기 때문에 항상 적용 중이었고, 내가 추가한 리버스 프록시 설정에도 당연히 이 설정이 포함되었던 것이다. 그간 .php를 내가 직접 다뤄본 적은 없기에 이번이 첫 사례가 되었다.

/etc/nginx/default.d/php.conf 파일이 범인이었으며, 내용을 모두 커맨트 처리해서 문제가 수정됨을 확인했다.

이렇게 /admin 페이지가 다시 열리게 되었고(IPv4 주소를 버린 이후 처음 열린 것), 그 기쁨에 본 포스팅을 남긴다…


AWS IPv4 유료화

AWS 환경에서 사용하는 모든 IPv4 주소에 대해 별도 추가 요금을 걷기 시작함에 따라, 취미용으로 쓰고 있는 EC2 및 IPv4를 정리할 필요성을 느꼈다.

  1. 볼 럼블 서버
  2. 초밥키우기 서버
  3. 블로그 서버

이렇게 EC2 세 대가 운영되고 있었는데, 모든 EC2에 Elastic IP가 붙어 있었다. (무료였기 때문…)

반드시 필요하지 않은 1번 EC2 한 대를 정리해서 그 기능을 모두 2번으로 옮기고, 3번에는 IPv4를 떼 버렸다. 그리고 2번에 nginx를 만들어 3번으로 SSL 포워딩만 하도록 바꿨다. (내부 연결은 IPv6로)

잘 된다. 후후…



Copyright © 2026. All Rights Reserved. PAGS by Flytonic.