Go언어로 갑니다! (Goodbye, Bun!)

2024-10-229 분 소요2

시리
시리니

저는 10년 만에 웹 개발을 다시 시작하면서, 자바스크립트 생태계의 천지개벽에 적잖게 당황했고 또 놀랬습니다.


React는 세상을 점령한 것처럼 보였고, 백엔드에서는 Node와 Deno의 등장으로 정말 어디서나 자바스크립트를 볼 수 있게 된 세상이 신기했습니다. 비동기 I/O가 주는 장점들을 십분 발휘 하면서도 다른 성능들과 개발 편의성도 동시에 급진적으로 개선되는 게 경이로웠고, 열광적으로 빠져들었던 기억이 납니다. 특히나 Node에서 Bun으로 런타임을 교체하며 동시에 타입스크립트로의 도전은 보다 큰 규모의 프로젝트를 무리없이 구성할 수 있겠다는 자신감까지 심어줬습니다. TSBOARD 개발은 전적으로 이 새로워진 자바스크립트 생태계 덕분입니다.


그렇지만, 길다면 길고 짧다면 짧았던 저의 자바스크립트(혹은 타입스크립트) 백엔드 개발은 이제 곧 끝날 예정입니다. 저는 곧 Go언어로 백엔드를 완전히 재작성 할 예정이고, 다시 자바스크립트 생태계로 돌아오진 않을 겁니다. (토이 프로젝트나 시간이 정말 급박하다면 또 얘기가 다르겠지만요…! 😉)


나는 왜 JS/TS 런타임으로부터 떠나는가?

사실 지금의 TSBOARD를 만들 수 있게 해준 건 전적으로 타입스크립트와 JS/TS 런타임인 Bun 덕분입니다. 이 개발 스택을 선택한 건 지금도 후회하지 않고, 만약 처음으로 다시 돌아간다고 해도 저는 똑같은 선택을 할겁니다. 특히 Node의 부족한 성능을 정말 획기적으로 개선해준 Bun, 그리고 그런 Bun에 최적화된 웹 프레임워크를 제작해준 ElysiaJS팀에 감사한 마음을 가지고 있습니다.


그럼에도, 여전히 마음 한구석에는 결국 싱글 스레드의 한계와 비동기 I/O 구조에만 지나치게 의존하는 런타임의 성능이 못내 아쉬웠습니다. 물론 트래픽이 엄청나게 적은 이곳 같은 경우에는 전혀 문제 될 것이 없고, 아마 동시 접속자수가 30여명이 넘어간다 하더라도 크게 무리가 되진 않을 겁니다. Bun이라면… 어쩌면 그 이상 해낼 지도 모르구요.


그렇지만, 자바스크립트 런타임은 결국 자바스크립트를 처리하는 엔진의 구조나 성능에 크게 제약을 받게 됩니다. 구글 크롬의 V8 엔진이 아무리 괴물같은 최적화를 통해 미친 성능을 보여 준다고 하더라도, 결국은 나의 자바스크립트 코드를 인터프린팅 해줘야 합니다. Bun은 분명 Node보다 빠르고, Zig 언어를 이용해서 세부적으로 더 고성능의 동작이 가능하도록 API를 잘 다듬었지만, 어쨌든 JavaScriptCore에 의존합니다. 특정 케이스에서는 높은 성능을 보여줄 수 있지만, 전반적으로 컴파일 언어 대비 느릴 수 밖에 없습니다. 또한 아무리 비동기 I/O 방식이 백엔드로 쓰기에 효과적이라 해도 싱글 스레드로 동작하는 이상 성능 저하는 피할 수가 없습니다. (내 서버의 여러 CPU core들을 효과적으로 괴롭혀주지 못하는 것도 아쉽죠!)


무엇보다, TSBOARD와 같은 도구를 실제 사용자에게 배포하는 과정이 간단하지 않습니다. 일단 전달 받는 쪽은 Bun이든 Node든 미리 설치해 두어야 합니다. 그리고 사용에 필요한 라이브러리들을 npm 등의 패키지 매니저를 통해 따로 내려 받아야 합니다. 또한 라이브러리들의 크기가 상당히 크고, 혹시나 버전이 꼬일 경우에는 이걸 처리하는 것만으로도 난감해집니다. 서버 환경에 따라서 라이브러리를 다르게 받아야 할 수도 있구요.


저의 경우 Bun 런타임이 한동안 가상 CPU에서는 제대로 동작하지 않는 버그가 있어서 이 배포 과정이 정말 힘들었습니다. (다행히 지금은 고쳐졌습니다!) 저조차도 특정 환경에서는 TSBOARD를 사용하지 못해 대체 솔루션을 찾아야 했을 정도니 그 스트레스가 이루 말할 수 없었죠. 사실 이 점이 저에게는 가장 크게 다가온 현실적인 문제이기도 했습니다. 내가 만든 프로젝트를 내가 쓰고 싶은 곳에 못썼던 시간이 너무 길었기에 대책을 세워야만 했거든요.


왜 Go언어인가?

자바스크립트 런타임이 가지는 한계를 점점 명확히 인식하면서, 저는 대안을 고민했습니다. 가장 좋아 보였던 선택은 의외로 러스트(Rust) 언어 였습니다. 메모리 안정성부터 C++과 맞먹는 성능, 그리고 많은 개발자들이 사랑하는 언어라서 가장 먼저 고민을 했습니다. 그러나 웹 개발을 하면서 메모리 문제까지 고민하며 진행하기에는 제 내공도 부족하고, 회사에서 어차피 써야하는 C++만으로도 이미 충분히 괴로웠기 때문에 아쉽지만 제외했습니다.


다음으로 떠올린 대안들은 그누보드가 선택한 파이썬(Python)이었습니다. 하지만 파이썬 언어도 사실 만만치 않게 성능 관점에서 약점이 있다고 생각했고, 회사에서 업무용으로 써본 경험에 비춰보면 웹에서까지 쓰고 싶다는 생각은 들지 않았었습니다. 언어 자체가 강타입 언어도 아니고 배포 과정이 Node나 Bun에 비할 바는 아니겠지만 그래도 간단하지는 않은 것 같았습니다. (어쨌든 파이썬이나 필수 라이브러리들을 받긴 해야 하니까요)


마지막으로 고려한 건 코틀린(Kotlin)과 스프링의 조합이었습니다. 정부 표준 프레임워크에 빛나는 자바 생태계에 마음이 끌리지 않았다면 솔직히 거짓말이고, 잠깐이나마 코틀린을 배워본 경험에 의하면 언어 자체가 자바 대비 선녀처럼 보였기 때문에 쓰고 싶었습니다. 그러나 아무리 스프링 프레임워크 설정이 쉬워졌다고 하더라도 여전히 저에겐 개발 환경 셋업도 어려웠습니다. Gradle 같은 빌드 도구들에도 솔직히 좋은 기억이 없어서 사실 가장 적합한 대안이라 생각했지만 제외했습니다.


그리고 나서 문득, Go언어는 어떨까 싶어 이것 저것 기웃 거리면서 알아봤는데… 제가 원하는 것들이 대부분 포함되어 있었습니다! 어째서 이제서야 이 언어를 고려하게 되었나 하는 자책을 할 정도로 마음에 쏙 들었습니다.


  • Go언어는 강타입의 컴파일 언어입니다. 타입 안정성이야 두말 할 필요가 없습니다.

  • 컴파일이 정말 빠릅니다. 인터프린터 언어에 비할 바는 아니라도 정말 빨라서 개발 생산성이 높습니다.

  • 배포 과정이 깔끔합니다. 크로스 컴파일도 잘되고, 생성된 바이너리 파일 하나만 있으면 바로 실행됩니다.

  • GC를 지원합니다! 물론 매뉴얼로 메모리를 관리하는 것 대비 느려지는 시점이 간간히 있지만 그래도 감수할 만 합니다.

  • 언어 자체가 간결함을 지향해서 배우기가 쉽습니다. 덕분에 빠르게 적응할 수 있습니다.


배포할 때 바이너리 파일 하나만 있으면 되고, 메모리 관리를 직접 하지 않아도 되는데다 배우기 쉽고 타입스크립트 언어와 약간 유사한 면도 있습니다. 덕분에 적응하는데도 그리 오래 걸리지 않아서 결과적으로 대 만족입니다. 이 Go언어 자체가 제가 가지고 있는 요구사항을 딱 맞춰서 개발한 것 같은 느낌도 들었습니다.


물론 가장 강력한 장점이라 할 수 있는 고루틴(Goroutine)은 정말 백번 얘기해도 부족하지 않을 정도로 큰 장점입니다. 자바스크립트 런타임이 싱글 스레드의 제약에 묶여 있는 것이 내내 마음에 걸렸었기 때문에, 고루틴의 존재는 그 자체로 정말 반가웠습니다. 아무리 비동기 I/O 방식으로 동작한다고 해도 역시 여러 CPU 코어를 동시에 괴롭혀 줄 수 있다면 성능이 더 오를 수 있겠죠…!


TSBOARD 백엔드는 언제 Go언어로 완전히 전환되나?

현재 목표는 올해 12월 말까지 작업을 마무리하고, v1.0.0 배포 시점에 맞춰서 공표하는 것입니다. 아마 12월 전에는 마무리가 될 수 있을 것 같고, 전환한 이후에는 다시 Bun 런타임 기반의 코드로 돌아가진 않을 것 같습니다. 다만 제가 Go언어를 제대로 공부하고 난 후에 개발을 하는 게 아니라 배우면서 동시에 개발을 하는 상황인지라 테스트 및 성능 개선 부분에 좀 더 시간이 소요될 수는 있겠습니다.


Go언어로의 전환이 완료되면 기존 TSBOARD의 server 폴더쪽 코드는 모두 제거될 예정이고, goapi (github.com/sirini/goapi) 의 OS별로 컴파일된 바이너리 파일만 추가되어서 배포될 겁니다. 물론 TSBOARD 사용자 분들 중에서 직접 백엔드를 고쳐서 쓰고 싶은 분들을 위해 goapi 코드 역시 Github에 계속 공개할 예정입니다. 만약 커스텀을 고려중이라면 걱정하지 않으셔도 된다고 말씀드리고 싶습니다.


이만하면 되었다, 를 경계하며…

TSBOARD를 만들면서 늘 경계하고자 했던 것 하나가, 바로 ‘이만하면 되지 않았나?’ 하는 생각입니다. TSBOARD 백엔드를 지탱해주고 있는 Bun, 그리고 ElysiaJS는 정말 기대 이상으로 잘해주고 있지만, 더 큰 기대를 품기에는 한계가 있습니다. 그 한계를 정확히 인식하고, 뛰어넘을 수 있도록 계속해서 노력해야 한다고 생각합니다. 그 것이 결국 TSBOARD를 사용하는 저나 다른 분들에게 더 큰 만족으로 돌아올테니까요.


무사히 전환할 수 있도록 응원을 부탁드립니다!

tsboard
golang
bun
elysia
백엔드
전환

최근 댓글들

바나나머스탱
24/10/30 16:34:01

조용히 응원하고 있습니다 저는 프로젝트에 영감을 받아 nextjs + nestjs + prisma로 연습해보고 있습니다. go로 서버를 만든다는건 아쉽지만 ㅠ 이것도 보면서 공부해보겠습니다

긱뉴스에서 보고나서 응원하고 프로젝트입니다! 저두 이거에 반만이라도 만들면 좋겠네요. 이제 gots 보드인가요 ㅋㅋ

시리니
24/10/30 20:28:57

응원에 감사드립니다! 😆 바나나머스탱님께서 만드시는 것도 구경해보고 싶네요! ㅎㅎ

이름을 바꿔야하나? 고민을 잠시 했지만 ㅎㅎ Type Safety 의 약자로 밀고 나가보려고 합니다. ㅎㅎㅎ