웹 서비스 배포 플랫폼 Luidium 개발기 - 4
중간 점검
모든 필수 api를 포함한 서버를 완성한 후, 최소한의 작동이 가능한 상태로 웹 클라이언트를 제작하였고, 배포를 마쳤다.
메인 화면
Application page에서 모든 인스턴스의 배포 상태와 버전, 로그를 확인할 수 있다.
업로드된 코드를 확인할 수 있는 Block Browser
(다른 건 몰라도 로딩 이미지는 괜찮게 만든 것 같다.)
왜인지 모르게 억울했던 순간. 프론트 개발이 시작되니 Rust 코드보다 Typescript가 더 많아졌다. 작성하는데 걸린 시간은 Rust가 2.5배 가량 긴 것 같다.
정말 숨 돌릴 틈 없이 개발을 하다 보니 내가 지금 뭘 하고 있는 건지 모르겠다는 느낌을 받은 적이 종종 있었고, 이에 잊어버리기 전에 프로젝트를 진행하며 느낀 점, 배운 점 등에 대한 회고를 적어보고자 한다.
- 서버 프레임워크와 언어
상용 서비스를 전제로 만드는 것이 아닌 개인적인 수요에 의한 사이드 프로젝트이기 때문에 엄청난 당위성과 퍼포먼스를 염두에 두고 선택을 하지는 않았다. 그저 Rust로 웹 서버를 만들어 보고 싶었고, node, python 기반의 서버와 어떤 차이가 있을지 순수한 궁금증이 있었다.
Rust와 Go로 이루어진 현재의 서버는 나의 예상을 상회하는 퍼포먼스를 보여주었다. 개발 외에는 트래픽이 사실상 없는 상태이고, MSA architecture를 차용했다 하더라도 각 서비스가 단일 인스턴스인 상황에서 monolithic architecture 보다는 당연히 속도 저하가 있을 것이라 생각했다. 결과는 초기 버전의 Nest.js + Neo4j 에서 현재의 Axum(Rust) 1개 + Gin(Go) 4개 + PostgreSQL + ScyllaDB 구조로 바꾼 결과 client에서 직접 느낄 수 있는 response 속도에서 적게는 2배에서 단순한 쿼리의 경우 10배까지의 속도 향상을 관찰할 수 있었다. 확실히 컴파일러 언어인 Rust와 Go의 힘을 느낄 수 있었고, 더 쾌적한 UX를 만들 좋은 조건을 형성해 주었다.
장점만 있는 것은 아니었다. Rust와 Go의 숙련도는 Javascript(Typescript) 보다 현저히 낮은 상태에서 시작하였고, Python처럼 쉬운 언어도 아니기 때문에 마치 서버의 Runtime performance를 나의 Development performance와 등가교환한 느낌을 받을 수 있었다. 개인적으로 개발자라면 유저에게 더 편하고 좋은 기능을 빠르게 개발해서 제공할 수 있는 덕목이 가장 중요하다고 생각하는데, 내가 더 나은 기능을 구상하고 빠르게 구현할 시간을 Rust의 async runtime에서 발생한 각종 문제(Node, Python이었다면 일어나지 않았을)와 작은 생태계로 인한 디버깅 지연으로 인해 소모하게 되어 생산성이 조금은 저하된 기분이 들었다. 그럼에도 compile-time에 대부분의 에러가 잡혀 runtime에 unexpected behavior가 거의 발생하지 않은 점, 그리고 빠른 응답 속도가 이를 보완하여 다시 Node.js 기반 서버를 사용하고 싶다는 생각이 들지는 않았다.(Node.js를 서버사이드에 다시 쓰느니 Java Spring을 공부할 것이다)
- 프론트엔드 - JS 생태계를 탈출할 수 있을까?
나는 React로 개발을 시작했고, Vue, Svelte, Angular(안써봤다) 보다 애정이 강한 것이 사실이다. 그리고 구현하며 모든 방면에서 부족함이 없다고 느끼기도 했다. 그래도 Rust에 빠진 최근에는 Rust로 웹을 만드는 Leptos를 꾸준히 공부하고 있다. rust macro를 이용해 jsx와 매우 유사한 syntax를 지원하며, use_signal과 같은 useState와 동일한 매커니즘의 렌더링 방식을 이용해 적응하기도 쉬웠다. 무엇보다 WASM을 이용하기 때문에 JS 기반의 다른 프레임워크와는 차원이 다른 퍼포먼스를 제공할 것이 분명했기 때문에, 클라이언트 집약적인 프로젝트를 진행하게 된다면 한 번쯤 시도해볼 만한 선택지라고 생각했다. 다만 Luidium의 경우 대부분의 병목이 서버 사이드에 존재하며 클라이언트는 사실상 control panel에 불과하기 때문에 굳이 Next.js를 버릴 이유는 없었다.
또 한 가지 고려하고 있는 선택지는 Elixir의 Pheonix와 LiveView이다. 다른 클라이언트에서 동시에 같은 화면을 볼 수 있게 하는 기능이 인상적이었는데, 시간이 될 때 Elixir를 공부해서 협업 툴 같은 서비스를 만들 때 사용하면 좋을 것 같았다.
- 바퀴의 재발명
현재의 Luidium은 객관적으로 AWS, Google Cloud, Microsoft Azure, Vercel, Github pages등의 하위 호환에 불과하다. Github Repository 연동 기능도 없으며, test를 제공하지도 않는다. 하지만 내가 Luidium을 개발한 이유는 배포를 하기 위함이 아니라 플랫폼 독립적인 배포 시스템에 원하는 기능을 붙여 클라우드 서비스 개발 분야의 end-to-end 솔루션을 제공하는 것이다. 현재는 LLM을 이용해 유저의 자연어 쿼리로부터 필요 기능을 추출하고, 기능에서 필요 인스턴스(DB, Server, Web 등)를 추출해내고, 이를 코드로 생성한 후 Luidium에 배포하여 결과물이 Fully-functional, Reachable, platform-agnositic한 cloud service가 되도록 하는 것이다. 적지만 모든 기능들이 외부 api와의 연동을 고려하여 최소한의 의존성을 갖도록 설계되었으며, 이와 같은 특수 기능 또한 luidium 상에 배포할 수 있기에 가장 근간이 되는 deploy platform인 Luidium을 개발한 것이다. 따라서 현재의 목표는 안정적으로 작동한 단일 클러스터로써의 Luidium Deployment platform를 완성하는 것이며,r 이를 바탕으로 목적 의식을 더욱 견고히 하였다.
개선 사항
- 삭제 관련 문제들
우선 하나의 Docker container라고 볼 수 있는 block을 삭제할 때 서비스 자체가 아주 잠깐 다운되는 상황이 발생했다. 521 Web server is down 이라는 에러가 발생하는데, 아무래도 서버 자체의 문제가 아니라, block에 할당된 DNS record를 관리하는 곳과, Luidium 서비스 자체를 배포한 곳이 Cloudflare로 같기 때문에 DNS record를 삭제하고 table을 update하는 과정에서 일시적으로 cloudflare 상에서 차단이 일어나는 것으로 추측된다. Cloudflare의 같은 domain을 이용하는 한 일시적으로 api 요청을 차단하거나, 배포용 domain을 따로 분리하는 것으로 해결해야 할 것 같다.
또한 Application을 삭제할 때 할당된 Block들이 같이 삭제되지 않고 있어 database에 junk data가 다수 남을 수 있는 문제가 있어 클라이언트, 혹은 서버 자체에서 하위 요소들이 같이 삭제될 수 있는 로직을 추가할 예정이다.
- UI 개선
서버 위주의 개발이었고, 프론트 UI/UX에 시간을 많이 할당하지 않다 보니 자잘한 문제들이 많이 발생하였다. 일단 Log를 불러올때 pagination을 구현하지 않았고, 이외에도 프로필 설정, Usage cap 잔여량 등 api를 구현해놓고 보여주지 않는 것들이 아직 많다.
이와 같이 margin 설정도 대충 하다 만 것이 조금 있어 최우선으로 손 볼 예정이다.
아래처럼 유저의 이메일과 이름을 확인할 수 있는 컴포넌트도 width를 고정으로 해둔건지 다 짤리고 있다. (심지어 Collaborator 추가 기능은 구현도 하지 않았다.)
잔여 작업
우선 서비스 소개와 대시보드로 이어지는 버튼을 제공할 랜딩 페이지를 구현할 예정이며, 최대한 빠른 시일 내에 CLI 배포 시스템을 구축할 예정이다.
아무래도 방학 전까지는 개발에 쏟을 시간이 많이 없을 것 같아서, CLI를 최대한 구현보는 방향으로 추진해야겠다.
Enjoy Reading This Article?
Here are some more articles you might like to read next: