개발

개인 서버는 러스트로 개발하는 이유

마지막 수정

요즘에는 개인적으로 러스트를 주력 언어로 사용하고 있다.

물론 회사에서는 자바/코틀린을 사용한다. 대부분의 경우에서는 당연히 자바가 좋다고 생각한다. 물론 스프링에 한정된 말이긴 하다. 스프링은 추상화가 잘 되어 있고, 읽기가 쉽고, 개발도 빠르면서도 객체 지향적으로 깔끔한 코드를 만들어 낼 수 있다.

다만 나의 홈 서버에서 사용하기는 조금 부적절했다. 돈 아껴가며 조심스럽게 산 미니PC라서, 메모리가 그렇게 여유롭지 않다. 램이 16GB 정도 되는데, traefik 띄우고 자바/베드락 에디션 마인크래프트 서버 띄우고, 개인 애플레이케이션(스프링) 여러개 띄우니까 메모리가 점점 차오르는게 눈에 보였다.

솔직히 아직 문제는 없었다. 그런데 앞으로 여러 개 더 띄우면 간당간당할 것 같았다. 간단한 기능의 서버도 한번 띄우면 600MB를 먹고 있으니 그게 참 아쉽더라.

어차피 사용자가 많지도 않고, 내 가족과 친구들과 같이 사용하려고 띄우는 서버인데, 메모리를 많이 쓰게 두고 싶지 않더라. 뭐... 어차피 나 혼자 유지보수 할 것이기도 하고.

그래서 다른 언어로 눈을 돌렸다. 컴파일 언어에 빠르게 동작하는 언어를 사용하고 싶었다.

  • Node.js, Python : 컴파일 언어 아니라서 고려하지 않음.
  • Go : 후보 중 하나였음. 컴파일 언어이고, 별도 가상 머신 없고, 가볍고 빠르고, 비동기(goroutine 과 channel)를 정말 쉽게 쓸 수 있다는 점에서 좋았음. GC가 있다는 점과 덕타이핑만 지원한다는 게 뭔가 좀 별로였음.
  • C, C++ : 속도나 메모리 생각하면 정말 좋다고 생각함. 그런데 라이브러리 관리나 메모리 관리에 시간을 너무 많이 쓸 것 같아서 포기.
  • Rust : 컴파일 언어이고, 빠르고, 메모리 관리 편한데 메모리도 아낄 수 있어서 좋음. 근데 초반 학습이 힘들고, 개인적으로 코드가 장황해지는 느낌을 받기는 함. &str과 String이 구분되는게 참 귀찮긴 하고, 소유권/빌림 때문에 추가되는 코드들이 많음. 예를 들어 무언가 가져오는 메서드도 get()get_mut() 이렇게 두 개를 만들어야 하는 경우가 생김.

내 선택은 러스트였다. 학습 곡선은 솔직히 어느 언어를 배울 때 다 있었던 것이라서 상관없다고 생각했고, 어느정도 익숙해진 지금도 사실 큰 단점이라고 생각하지 않는다.

오히려 익숙해지고 나니까 메모리 관리는 전혀 신경쓰지 않아도 되어서 편하더라.

특히 제일 만족스러운건, 메모리 사용량이었다.
아래 내용은 첫 부팅 이후 IDLE 상태의 메모리 기준이다.

  • 자바(스프링) : 600MB
  • 러스트(axum) : 3MB
  • GO(net/http) : 15MB

이거 보니 참.. 황당하긴 했다. 이렇게까지 차이가 날거라고는 정말 생각하지 못했다.
어쨌든 메모리가 감소된 걸 보니 기분은 좋더라. 앞으로도 혼자 사용하는 서버는 Rust 사용하기로 했다.

그렇지만 단점도 분명히 있다.

  • axum 사용
    • routing이 불편
      • 사실 이건 스프링을 쓰다 와서 그런 것도 있다. 일일히 라우팅 코드를 작성해줘야 해서 옛날 느낌이 들었다.
      • 좋게 생각하면 오히려 명확한 느낌이 있어서 좋긴하다.
    • DI 컨테이너 부재
      • 이것도 스프링을 쓰다와서 그런 것이다. 직접 일일히 다 의존성 주입을 코드로 진행한다.
      • 근데 이것도 나름 주입 흐름이 눈에 다 보여서 좋다고는 생각한다. 불편한건 여전하지만.
  • 비동기를 외부 라이브러리에 의존
    • tokio 라는 async 라이브러리를 사용한다. 사실 이건 러스트가 async 관련해서는 인터페이스만 제공하고, 실제 구현은 외부 라이브러리에게 맡기기 때문이다. 향후 tokio가 어떻게 될지는 아무도 모르니 조금 걱정이 되기는 한다.
  • 소유권/빌림 때문에 메서드가 많아지고, 코드가 장황해지는 기분이 든다. 메모리 관리가 좋아진 대신 가독성이 조금 불편한 정도.

그래도 뭐, 서버 리소스 절약했고 새로운 언어도 사용할 수 있게 되었으니 좋은 것 아닐까. 아마 앞으로도 큰 장애물이 없다면 러스트로 구현할 것 같다.