1P by GN⁺ | ★ favorite | 댓글 1개
  • CobolCraft는 COBOL로 구현된 Minecraft 서버로, 작성 시점 최신 버전인 Minecraft 1.21.4를 지원함
  • 이미 무한 지형 생성, 동적 청크 로딩, 월드·플레이어 데이터 디스크 저장, 기존 월드 가져오기, 멀티플레이, 서버 상태 표시, 블록 파괴·설치, 인벤토리, 제작, 아이템 줍기, 채팅, 명령어 등을 구현함
  • 다중 상태·방향·상호작용을 가진 블록은 동작을 제대로 구현하려면 전용 코드가 많이 필요하며, 아직 지원되지 않는 블록이 많음
  • Linux x86_64 또는 arm64에서 GnuCOBOL로 개발됐고, Docker를 이용한 배포도 가능하지만 Windows 같은 다른 운영체제 지원은 테스트되지 않음
  • Minecraft의 기본 datapack과 공식 서버·클라이언트 .jar에서 JSON 데이터를 추출해 컴파일 시 COBOL 코드 생성과 런타임 데이터 로딩에 사용함

CobolCraft가 구현한 Minecraft 서버 기능

  • CobolCraft는 COBOL로 작성된 Minecraft 서버이며 Minecraft 1.21.4를 지원함
  • 구현된 기능은 다음을 포함함
    • 무한 지형 생성과 동적 청크 로딩
    • 월드와 플레이어 데이터의 디스크 저장
    • Minecraft 파일 포맷 지원과 기존 월드 가져오기
    • 동시 접속 플레이어 수를 설정할 수 있는 멀티플레이
    • 서버 목록에서 온라인으로 보이게 하는 ping/server status
    • 블록 파괴와 설치, 자동 생성된 loot table 코드
    • 오른쪽 클릭 기반 블록 상호작용
    • 플레이어 인벤토리
    • 2x2와 3x3 제작
    • 아이템 엔티티와 아이템 줍기
    • 채팅
    • 게임 내 명령어와 대화형 콘솔 명령어
    • server.properties 기반 설정
    • whitelist.json에 저장되는 지속형 whitelist
    • 매우 기본적인 블록·플레이어 충돌과 엔티티 물리
    • 낙하 피해, void 피해, 사망, 리스폰

블록 지원 범위와 한계

  • 상태, 방향, 상호작용을 여러 개 가진 블록은 올바른 동작을 위해 전문화된 코드가 많이 필요함
  • 아직 지원되지 않는 블록이 많음
  • 동작하는 블록에는 다음이 포함됨
    • torches
    • slabs
    • stairs
    • logs 같은 rotated pillars
    • 비상호작용 buttons
    • doors
    • trapdoors
    • beds
    • signs

빌드와 실행 환경

  • CobolCraft는 GnuCOBOL로 개발됐으며 Linux에서 실행하는 것을 목표로 함
    • 대상 아키텍처는 x86_64와 arm64
    • Windows 같은 다른 운영체제 지원은 테스트되지 않음
    • Docker를 사용하면 플랫폼 독립 배포가 가능함
  • Linux 배포에 필요한 항목은 다음과 같음
    • GnuCOBOL 3.1.2 이상
    • 성능상 GnuCOBOL 3.2 이상 권장
    • make
    • gcc, g++
    • zlib
    • 공식 서버 .jar 다운로드에 필요한 curl
    • 서버 .jar에서 데이터를 추출하는 데 필요한 Java 21 이상
  • 빌드와 실행 명령은 다음과 같음
make --jobs=$(nproc)
make run
  • Docker Hub 이미지를 사용하거나 직접 빌드해서 실행할 수 있음
docker pull meyfa/cobolcraft:latest

git clone https://github.com/meyfa/CobolCraft.git cobolcraft && cd cobolcraft
docker build --tag meyfa/cobolcraft .

서버 설정과 네트워크 접근

  • 서버 설정은 server.properties 파일을 수정해 수행함
  • 이 파일은 첫 실행 시 지원되는 모든 옵션의 기본값과 함께 자동 생성됨
    • server-port: 기본값 25565
    • level-name: 기본값 "world"
    • white-list: 기본값 false
    • motd: 기본값 "CobolCraft"
    • max-players: 기본값 10, 최대 100
  • 기본적으로 서버는 localhost:25565를 통해 자기 시스템에서만 접근 가능함
  • 로컬 네트워크, VPN, 포트 포워딩, 임대 서버 등 외부에서 접근 가능하게 하려면 Docker 실행 시 0.0.0.0:25565:25565로 포트를 바인딩할 수 있음
docker run --rm -it -p 0.0.0.0:25565:25565 meyfa/cobolcraft

COBOL로 Minecraft 서버를 만든 이유

  • 개발자는 이전에 COBOL 경험이 전혀 없었지만, COBOL에 대한 소문과 낙인을 보고 언어를 더 알아보고 싶어 했음
  • 언어를 배우는 가장 좋은 방법으로 무언가를 직접 작성하는 방식을 택함
  • Minecraft 코드의 복잡성과 규모 때문에 COBOL로 Minecraft 서버를 작성하는 선택은 좋으면서도 나쁜 아이디어였다고 평가함
  • 다른 언어에서는 쉬운 작업을 처음부터 만들어야 했음
    • JSON 파싱과 인코딩
    • 여러 종류의 바이너리 데이터 처리
    • 실시간 멀티플레이 네트워킹
    • 객체지향적인 Minecraft 시스템을 절차형 언어로 옮기는 작업
  • 급격한 학습 곡선은 COBOL과 그 개념을 깊이 조사하고 이해하게 만들었고, 그 과정이 보람 있었다고 밝힘
  • COBOL을 처음 쓰는 사람에게는 GnuCOBOL Programmer's Guide를 권장함
  • Minecraft 프로토콜 학습 자료로는 wiki.vg documentation을 참고할 수 있음
  • 경우에 따라 Wireguard 같은 도구로 실제 서버 트래픽을 보는 것도 정보 흐름을 이해하는 데 도움이 될 수 있음

소스 구성과 실행 바이너리

  • COBOL 소스 코드는 주로 src/ 디렉터리에 있음
    • src/main.cob이 진입점
    • src/server.cob에는 서버 시작 코드와 게임 로직이 있음
  • codegen/ 디렉터리에는 COBOL로 작성된 코드 생성기가 있음
    • Minecraft 기본 datapack 같은 JSON 데이터에서 추가 소스 코드를 생성함
  • cpp/ 디렉터리에는 COBOL로 처리하기 어려운 운영체제 연동을 위한 C++ 소스가 있음
    • 저수준 TCP 소켓 관리
    • 정밀 타이밍
    • 프로세스 시그널 처리
  • 모든 COBOL과 C++ 소스는 하나의 cobolcraft 바이너리로 컴파일됨

Minecraft 데이터 추출과 JSON 처리

  • 공식 Minecraft Java Edition 서버와 클라이언트 애플리케이션에는 많은 데이터가 들어 있음
    • 블록, 아이템, 엔티티 타입
    • biomes
    • 패킷 protocol ID
    • 곡괭이로 캘 수 있는 블록 같은 tags
    • recipes
    • 블록을 부쉈을 때 어떤 조건에서 어떤 아이템이 떨어지는지 나타내는 loot tables
  • CobolCraft의 Makefile에는 공식 .jar를 다운로드하고 데이터를 JSON으로 추출하는 대상이 있음
  • 추출된 JSON 데이터는 두 방식으로 사용됨
    • 컴파일 시 블록 loot table 같은 COBOL 코드를 자동 생성
    • 런타임에 데이터를 메모리로 로드
  • 두 작업 모두 COBOL로 작성되고 유닛 테스트가 완료된 범용 JSON 파서를 사용함

테스트와 업데이트

  • 유닛 테스트는 tests/ 디렉터리에 있음
  • 테스트는 copybook 기반의 커스텀 테스트 프레임워크를 사용함
    • 테스트 스위트, 유닛, assertion을 추적함
    • 실행 끝에 요약을 제공함
  • 테스트 실행 명령은 make test
  • 테스트의 주된 목표는 디버깅이 어려운 JSON·바이너리 데이터 인코딩과 디코딩 같은 영역을 검증하는 것임
  • 게임 로직 자체 테스트는 그만큼 중요하지 않다고 봄
  • 새 Minecraft 버전으로 서버를 업데이트하는 절차와 테스트 단계는 Updating.md에 있음

라이선스와 상표

  • CobolCraft는 MIT License로 배포됨
  • “Minecraft”는 Mojang Synergies AB의 상표임
  • CobolCraft는 Mojang과 제휴하거나 Mojang의 보증을 받은 프로젝트가 아님

댓글과 토론

Hacker News 의견들
  • COBOL을 둘러싼 소문과 낙인이 많은데, 실제로 어떤 통찰을 얻었는지 글로 써주면 좋겠음
    나도 그런 얘기만 들어왔고, COBOL 입문자가 꽤 복잡한 첫 프로젝트를 구현하면서 무엇을 마주쳤는지 궁금함

    • COBOL의 객체지향 변종은 이름이 ADD ONE TO COBOL YIELDING COBOL이라는 다루기 힘든 형태라는 농담 섞인 낙인이 있음
      그래도 예전 FORTRAN처럼 공백을 무시해서 DO 10 I=1.10이 루프 문법 오류가 아니라 DO10I = 1.10 대입문으로 조용히 컴파일되는 일은 없었음. 의도한 코드는 DO 10 I=1,10이었을 텐데 말임
    • 이런 통찰이 좋음
      관심 있다면 COBOL에서 C#으로 가는 컴파일러를 만들며 얻은 내용이 여기 있음: https://github.com/otterkit/otterkit-cobol/issues/40
      이제 COBOL은 고수준 어셈블러일 뿐이라고 확신하게 됨
  • 정말 멋짐
    고등학교 졸업 프로젝트로 축구 베팅 배당률을 자동화하는 전체 COBOL 시스템을 만들었음. 이미 한물간 기술이었지만 학교는 아직 시대를 따라잡지 못한 상태였음
    말도 안 되게 어울리지 않았지만, 한 줄 한 줄이 좋았음. 타이핑할 때마다 “천공카드 기억나?”라고 속삭이는 언어에는 이상하게 만족스러운 구석이 있음

    • 고등학교 프로젝트에 대문자 COBOL을 썼다는 게 정말 시대감이 잘 맞음. 훌륭한 고등학교 추억거리가 됐을 듯함. 변수 이름은 전부 그리스 신 이름으로 지었기를 바람
  • 착각일 수도 있지만, C나 여기서의 COBOL처럼 단순하고 평범한 언어로 작성된 작지만 인상적인 사이드 프로젝트를 꽤 자주 보는 느낌임
    반대로 비슷한 Rust 프로젝트는 코드 줄 수가 10배쯤 되는데도 거의 동작하지 않는 경우가 많아 보임
    내 가설은 단순한 언어가 아이디어를 청사진처럼 빠르게 잡고 지저분한 코드베이스라도 일단 돌아가게 만들기 쉽다는 것임. 반면 현대 언어는 더 오래 버틸 코드를 쓰도록 강제함. 아니면 현대 언어들이 뭔가 잘못하고 있는 걸지도 모름

    • Minecraft 서버는 정확히 말해 작은 사이드 프로젝트가 아님
      3~5년째 개발 중인데도 완성되지 않은 서버들이 있고, https://github.com/MCHPR/MCHPRS처럼 레드스톤 전시용으로 특정 기능에 집중한 것도 있음
      이 COBOL 서버는 아직 조명 처리를 구현하지 않았고, 몹 생성도 거기에 의존하므로 가장 어려운 부분 중 하나임. 일부 블록도 완전히 구현되지 않았음. Minecraft 서버를 끝내려면 몇 년이 필요하니, 빨리 뭔가 만드는 게 항상 좋은 길은 아님
    • 그게 꼭 착각은 아니라고 봄
      Rust로 작업 중인 게임이 2개 있는데, 적절한 엔진을 고르면 아주 최소한의 게임플레이 프로토타입은 꽤 쉬웠음. 하지만 기능을 추가할수록 코드가 크게 불어났고, 싱글플레이에서 멀티플레이로 바꾸는 과정은 난장판이었음. 유행을 따라갔다가 다시 제거하느라 시간을 낭비하기도 했음
      Rust는 게임 객체들이 복잡하게 연결된 그래프 구조를 정말 싫어함. 게임 이벤트 하나가 여러 타입의 갱신으로 이어지는 상황마다 마찰이 생김. 그냥 받아들이고 코드를 조금 더 쓰는 선택지도 있었고, 초기에 더 많은 코드를 쓰더라도 나중에 시간을 아낄 체계적 해법을 찾는 선택지도 있었음
      두 번째를 골라 몇 가지 실험을 했지만, 손익분기점이 1인 소규모 프로젝트에 맞지 않을 만큼 멀리 있는 느낌임
      같은 언어 안에서도 차이가 한 자릿수 이상 날 수 있음. Rust에는 쓸 만한 3D 엔진이 2개 있는데, 하나는 유명하고 기여자도 많고 Bay Area 연봉을 대체할 만한 후원도 받음. 다른 하나는 거의 한 명이 만들며 저축으로 버티거나 풀타임 일을 번갈아 함
      그런데 첫 번째 엔진은 홍보에 크게 집중하고 여러 기능을 몇 년째 약속하지만 보여준 것이 적고, 두 번째는 기능 수와 구현 품질 모두 앞서 있음
      결국 태도의 차이라고 봄. 재미로 코딩하는 사람, 명확한 목표를 두고 달성에 집중하는 사람, 돈을 위해 하는 사람, 대중적 인정에 끌리는 사람이 있음. 지저분한 코드베이스가 꼭 필요한 건 아니지만 생산적인 중간 지대는 있음. 과시에 집중하는 사람일수록 유행과 화려한 아키텍처를 좇기 쉬움
    • Rust는 게임 개발에서 돌파구를 찾는 데 꽤 고전해 왔음
      Rust의 핵심 전제는 개발 속도와 유연성을 메모리 안전성과 맞바꾸는 것인데, 게임 개발에서는 개발 속도와 유연성이 메모리 안전성보다 훨씬 중요하다는 게 드러남
      이미 세부까지 청사진이 잡힌 형식 명세 마이크로커널이라면 Rust가 훌륭한 선택일 수 있음. 반대로 무엇이 재미있는 게임플레이가 되는지 보려고 벽에 진흙을 빠르게 던져봐야 한다면, Rust는 거의 어떤 언어보다 그 과정을 어렵게 만들고 이점도 분명하지 않음. 더 오래 걸려 만든 빠르고 지저분한 게임플레이 조각이 약간 더 메모리 안전하다는 정도임
      Rust로 게임 개발을 해본 뒤 그 용도로는 확실히 떠난 사람이 나만은 아님. 예를 들어 “Leaving Rust gamedev after 3 years” [0]가 있고, 지금까지 Rust 관련 Hacker News 글 중 가장 많이 논의되고 좋아요를 받은 글 중 하나임
      더 넓게 보면 Rust가 Cobol보다 훨씬 과장된 관심을 받는 건 명백함. 그래서 과장된 흐름에 취약한 개발자들, 보통 열정적인 초보자들이 Rust로 오픈소스나 취미 프로젝트에 용감하게 도전한 예가 많음. 반대로 Cobol로 Minecraft 서버를 쓰려면 약간 더 많은 기발함과 배짱이 필요하고, 이는 대체로 더 많은 경험과 연결됨
      [0] https://news.ycombinator.com/item?id=40172033
    • 결국 단순한 언어를 좋아하고 무엇을 줘도 우주 전체를 만들어내는 진짜 해커™ 와, 최신 유행을 좇는 코드 몽키의 차이 같음
      참고로 나는 나 자신을 두 번째 부류에 넣음
    • 일을 끝내는 사람들은 보통 코드 품질에 크게 신경 쓰지 않음
      오래 버틸 코드를 쓰려다 보니 어느 순간 아무것도 끝내지 못하는 상태가 된 적이 있음. 수년에 걸쳐 균형을 찾았고, 쓰레기 같은 코드를 반복 개선하다 보면 결국 괜찮은 것으로 바뀐다는 걸 배웠으며 그 뒤로 그렇게 하고 있음
  • https://raw.githubusercontent.com/meyfa/CobolCraft/main/src/...
    절차적 언어 배경이 있는 사람에게는 실제로 그리 이해하기 어렵지 않고, 약 20년 전에 봤던 VB로 작성된 게임 서버들이 조금 떠오름

  • 1978년에 COBOL 사용을 그만둔 뒤로는 이 언어를 안다고도 절대 인정하지 않았음
    이 코드를 보지 않기를 바라며 성호를 긋고 진한 커피를 마시러 감 :-)
    그래도 이걸 해낸 건 인상적임

  • 놀려도 좋지만, 코드는 꽤 읽기 쉬움
    무슨 일이 일어나는지 이해하려고 몇 분씩 들여다봐야 하는 일부 현대 언어와 비교됨

    • 한때 FAANG 회사에서 일하며 세계적인 C++ 전문가들에게 접근할 수 있었음. 몇몇은 국제 언어 표준 위원회 소속이었음
      내부 C++ 목록에 특정 코드 한 줄이 메모리 누수를 만들지 물어봤는데, 순수하게 STL 템플릿과 형변환을 쓰는 코드였음. 그런데 전문가들이 내가 올바르게 하고 있는지 합의하지 못했음. 누수가 날 거라는 사람도 있었고, 아니라고 보는 사람도 있었음
      이 작은 실화가 C++에 대해 많은 걸 말해줌. JavaScript도 이런 것들로 가득함
    • 그게 COBOL의 강점이었음
      1976년에 프로그래밍을 시작했고 COBOL과 ICL PLAN을 배웠으며, 천공카드를 쓰다가 교육을 마친 뒤에는 단말기를 썼음. 프로그램은 100% 배치 프로그램이었음
      누구든 소스 코드를 읽고 이해할 수 있도록 가독성에 대한 편향이 매우 컸음. 다만 프로그램이 실패했을 때 생성되는 코어 덤프를 읽고 이해해야 한다는 점이 그 가독성을 어느 정도 상쇄했음. 잘해야 실패를 특정 코드 줄까지 추적할 수 있었고, 그래서 프로그램을 머릿속으로 실행해보는 습관이 몸에 배었음
      정부 기관을 떠나 상업 프로그래밍으로 옮겼을 때도 80년대 초까지는 여전히 COBOL과 배치 프로그램이었음. 3년간 야간 지원을 했는데 그때 COBOL의 가치가 드러났음. 처음 보는 목록과 코어 덤프를 집어 들어도 대개 꽤 빨리 고칠 수 있었음. 물론 항상 전술적 수정이라는 단서는 있었음
    • 그래서 Ada와 VHDL이 좋음
      다소 장황할 수는 있지만 더 “현대적인” 언어들보다 훨씬 읽기 쉬움
    • COBOL은 프로그래머가 아닌 사람도 쓰고 읽을 수 있도록 설계됐음
      적어도 이론상으로는 그랬음
    • MOVE FUNCTION MIN(BLOCK-ENTRY-MINIMUM-STATE-ID(LK-BLOCK), STATE-ID) TO BLOCK-ENTRY-MINIMUM-STATE-ID(LK-BLOCK)
  • 고등학교 때 파키스탄의 작은 도시에서 COBOL을 조금 배웠음
    나쁘지 않았고, 재무제표를 흉내 내는 프로젝트를 했음. 괴상한 구석은 있었지만 대부분의 인간, 즉 비프로그래머에게는 어떤 프로그래밍 언어든 꽤 괴상할 테니 COBOL에 붙은 낙인은 잘 이해되지 않음
    같은 시기에 C도 배웠고, 그쪽은 계속 남았음 :-)

  • Cobol 프로그래머가 희귀해서 높은 연봉을 받는다는 얘기를 늘 들음
    이 프로젝트 때문에 일자리 제안이 쏟아졌는지 궁금함

    • 희귀한 건 Cobol 프로그래머가 아니라 비즈니스 로직을 이해하는 사람
      Cobol은 매우 복잡한 업무 운영에서 자주 쓰임
    • 다른 사람들이 말했듯이 기존 비즈니스 로직의 복잡함과, 보통 그 코드가 돌아가는 메인프레임 시스템에 대한 이해가 더 큼
      그렇지 않다면 교차 컴파일러 하나 만들고 끝내면 됐을 것임
    • 그런 사람들은 프로그래밍 실력보다 매우 복잡하고 대체로 문서화되지 않은 시스템과 그 업무 환경 지식 때문에 가치가 있음
  • COBOL은 실제로 꽤 멋진 언어처럼 보임
    코드도 정말 잘 정리돼 있음

  • 단위 테스트가 있다는 점이 마음에 듦