왜 나는 익숙한 Spring을 두고 Armeria를 선택했을까? (feat. 2년 전의 고민)

왜 나는 익숙한 Spring을 두고 Armeria를 선택했을까? (feat. 2년 전의 고민)
Armeria 로고

때는 2023년 4월, 지금으로부터 약 2년 전의 일입니다. 개인적으로 운영하는 토이 프로젝트용 API 서버를 새롭게 구상하고 있었죠. 제 손에는 이미 익숙하디 익숙한 Spring Boot라는 강력한 무기가 들려 있었습니다. 대한민국 개발자라면 누구나 한 번쯤은 거쳐 갔을, 혹은 지금도 애용하고 있을 바로 그 프레임워크 말입니다. 그런데 저는 어째서인지 그 익숙함을 뒤로하고, 당시 저에게는 다소 생소했던 Armeria라는 프레임워크에 손을 뻗었을까요?

오늘 그 이야기를 조금 길게 풀어보려 합니다.

익숙함의 안락함, 그리고 작은 물음표: Spring Boot

제 개발 여정에서 스프링 부트는 언제나 든든한 동반자였습니다. 방대한 생태계, 풍부한 레퍼런스, 강력한 커뮤니티 지원까지. 복잡한 웹 애플리케이션도 "뚝딱" 만들어낼 수 있을 것 같은 마법 같은 생산성을 선사했죠. DI, AOP, PSA 등 스프링의 핵심 철학은 이미 제 사고방식의 일부가 되어 있었습니다.

제가 만들고자 했던 개인 API 서버는 사실 그리 복잡한 물건은 아니었습니다. 주로 하는 일이라고는 외부에 공개된 여러 API들을 호출해서 가져온 데이터를 제 입맛에 맞게 가공하고, 다시 저만의 엔드포인트로 재생산하는 역할이 전부였죠. 이를테면, 여러 곳에 흩어진 정보를 한데 모아 일관된 포맷으로 제공하거나, 특정 조건에 따라 필터링하고 조합하는 식입니다. 데이터베이스 연동도 복잡하지 않았고, 사용자 인증 같은 헤비한 기능도 필요 없었습니다.

스프링 부트로 이 정도 API를 만드는 건 식은 죽 먹기였습니다. @RestController, @GetMapping, RestTemplate (혹은 WebClient) 몇 개면 금방 프로토타입이 나올 수 있었죠. 하지만 문득 이런 생각이 들었습니다.

이 작은 프로젝트에 스프링 부트는 조금 과분하지 않을까?
정말 스프링 부트의 모든 기능을 필요로 할까?
혹시 더 가볍고, 이 프로젝트의 목적에 더 부합하는 다른 선택지가 있지는 않을까?

솔직히 말하면, 새로운 기술에 대한 약간의 갈증도 있었습니다. 익숙한 것만 반복하다 보면 어느새 우물 안 개구리가 될 수 있다는 작은 위기감 같은 것이었죠.

새로운 만남: Armeria의 등장

그러던 중, 라인(Line)에서 개발하고 오픈소스로 공개한 Armeria라는 프레임워크를 알게 되었습니다. 처음에는 '라인에서 만들었다고? 뭔가 특별한 게 있나?' 정도의 가벼운 호기심이었습니다. 하지만 조금 더 자세히 들여다보니, 제 고민에 대한 해답이 될 수도 있겠다는 생각이 들기 시작했습니다.

Your go-to microservice framework for any situation
- Armeria

Armeria는 스스로를 "Your go-to microservice framework for any situation"이라고 소개합니다. Asynchronous, Reactive를 핵심으로 삼고, Netty 기반으로 구축되어 고성능을 지향하는 프레임워크였죠. HTTP/2, gRPC, Thrift 등 다양한 프로토콜을 네이티브하게 지원한다는 점도 눈에 띄었습니다.

내가 Armeria를 선택한 결정적인 이유들

Spring Boot라는 걸출한 대안을 두고 Armeria를 선택한 데에는 몇 가지 분명한 이유가 있었습니다.

태생부터 비동기 & 리액티브: 외부 API 호출에 최적화

제가 만들려는 서비스의 핵심은 '외부 API 호출'이었습니다. 즉, Network I/O Task가 주를 이루는 서비스였죠. 이런 I/O-bound Task에서는 비동기 Non-Blocking 방식이 빛을 발합니다. 요청을 보내고 응답을 기다리는 동안 스레드가 묶여있지 않기 때문에, 적은 수의 스레드로도 많은 동시 요청을 효율적으로 처리할 수 있습니다.

Armeria는 Netty를 기반으로 하며, 설계 초기부터 비동기 및 Reactive Programming Model을 염두에 두고 만들어졌습니다. Reactor나 RxJava 같은 리액티브 라이브러리와의 통합도 자연스러웠죠. 반면, 전통적인 Spring MVC는 Servlet 기반의 Sync-Blocking 방식에 더 가까웠습니다. 물론 Spring에도 WebFlux라는 훌륭한 리액티브 스택이 있지만, Armeria는 프레임워크 자체가 Reactive Stream을 중심으로 더욱 긴밀하게 설계되었다는 인상을 받았습니다. 외부 API 호출이 잦은 제 서비스의 특성상, 이는 매우 매력적인 장점이었습니다.

가벼움과 성능: 개인 서버의 한정된 리소스를 위하여

개인적으로 운영하는 토이 프로젝트 서버는 리소스가 넉넉하지 않습니다.
어느 정도냐고요? i7 8세대에 16GB DRAM을 가진 노트북인데다, 다른 서비스도 구동중이기에 더더욱 리소스가 넉넉치 못합니다.

Spring Boot는 물론 훌륭하지만, 때로는 그 자체로 필요 이상의 기능을 품고 있어 무겁게 느껴질 때가 있었습니다. 반면 Armeria는 MSA를 지향하며 상대적으로 가볍고 빠르게 동작하도록 설계된 점이 마음에 들었습니다. 실제 구동 시에도 Spring Boot에 비해 초기 구동 속도나 메모리 점유율 면에서 이점을 보일 것이라 기대했습니다. (그리고 2년이 지난 지금, 이 기대는 어느 정도 충족되었다고 생각합니다.)

직관적인 API와 설정: Spring만큼이나 편리한 개발 경험

새로운 프레임워크를 선택할 때 우려되는 점 중 하나는 학습 곡선과 개발 편의성입니다. 하지만 Armeria는 이 부분에서도 만족스러웠습니다. Spring MVC에 익숙한 개발자라면 @Get, @Post, @Param, @Path 와 같은 어노테이션 기반의 API 정의 방식이 매우 친숙하게 느껴질 것입니다.

또한, 서버 설정이나 다양한 컴포넌트(예: Circuit Breaker, Rate Limiter, 다양한 응답 포맷 컨버터)를 추가하는 방식도 프로그래밍적으로 명확하게 정의할 수 있어 좋았습니다. Spring Boot의 'Convention over Configuration'도 훌륭하지만, 때로는 Armeria처럼 명시적인 설정이 내부 동작을 이해하는 데 더 도움이 되기도 합니다.

새로운 패러다임 학습의 기회

솔직히 이 부분도 무시할 수 없는 동기였습니다. Spring이라는 거대한 생태계에 익숙해지는 것도 중요하지만, 때로는 다른 관점과 철학을 가진 기술을 경험함으로써 시야를 넓힐 필요가 있다고 생각했습니다. Netty 기반의 비동기 네트워크 프로그래밍, 리액티브 시스템 설계 등에 대해 더 깊이 이해할 수 있는 좋은 기회가 될 것이라 판단했습니다.

2년이 지난 지금, 나의 선택은 옳았을까?

Armeria를 선택하고 API 서버를 개발하여 운영한 지 어느덧 2년이 흘렀습니다. 그동안 크고 작은 기능 변경과 유지보수를 거치면서 Armeria에 대한 이해도도 많이 깊어졌습니다.

결론부터 말하자면, "제 개인적인 프로젝트의 맥락에서는 아주 만족스러운 선택이었다"고 말할 수 있습니다.

  1. 예상대로 외부 API 호출이 많은 서비스의 특성상, Armeria의 비동기/리액티브 아키텍처는 빛을 발했습니다. 적은 리소스로도 안정적으로 서비스를 운영할 수 있었죠.
  2. 개발 과정에서 Armeria가 제공하는 다양한 기능들(커스텀 ResponseConverter, CircuitBreaker 등)을 유용하게 활용했습니다.
  3. 무엇보다 새로운 기술을 배우고 적용하는 과정 자체가 즐거웠습니다. Spring과는 또 다른 방식으로 문제를 해결하는 방법을 고민하면서 개발자로서 성장하는 느낌을 받았습니다.

물론 아쉬운 점이 없었던 것은 아닙니다. 스프링 부트에 비해 상대적으로 커뮤니티의 크기가 작고, 한글로 된 레퍼런스가 부족하여 특정 문제를 해결하거나 고급 기능을 활용하려 할 때 조금 더 많은 시간을 투자해야 했던 경우도 있었습니다. 하지만 공식 문서가 잘 되어 있고, 공식 디스코드 채널을 통해 커뮤니티 지원도 받을 수 있어 큰 어려움은 없었습니다.

정답은 없다, 최적의 도구를 찾아서

제가 Armeria를 선택한 이야기가 "Armeria가 Spring보다 우월하다"는 결론으로 이어지는 것은 절대 아닙니다. Spring Boot는 여전히 강력하고 범용적인 프레임워크이며, 대부분의 상황에서 훌륭한 선택지가 될 것입니다.

다만, 제가 드리고 싶은 말씀은 모든 상황에 완벽한 '만능 도구'는 없으며, 프로젝트의 특성과 목적, 개발자의 성향과 학습 목표에 따라 최적의 도구는 달라질 수 있다는 것입니다. 때로는 익숙함에서 한 발짝 벗어나 새로운 가능성을 탐색하는 것이 더 큰 만족감과 성장을 가져다줄 수도 있습니다.

2년 전, 저는 '외부 API 호출이 잦은 가벼운 개인 API 서버'라는 명확한 목표 아래 Armeria를 선택했고, 그 선택은 성공적이었습니다.

여러분도 다음에 새로운 프로젝트를 시작하게 된다면, 당연하게 여겨왔던 선택지 외에 또 다른 가능성은 없을지 한번쯤 고민해보시는 건 어떨까요? 그 과정에서 분명 새로운 재미와 성장을 발견하실 수 있을 겁니다.

다시, 한번 더

Armeria와 함께한 지난 2년은 제게 비동기 프로그래밍과 마이크로서비스 아키텍처에 대한 깊은 이해를 선물했습니다. 그리고 이 API 서버는 여전히 제 개인적인 용도로 훌륭하게 작동하고 있죠. 덕분에 외부 API들을 다루는 데 있어 훨씬 효율적이고 안정적인 환경을 갖출 수 있었습니다.

하지만 개발자의 여정은 끊임없는 탐구와 새로운 도전의 연속인가 봅니다. 익숙함에 안주하기보다, 또 다른 가능성을 엿보는 것에서 오는 성장의 기쁨을 알기 때문일까요?

최근 제 시선은 Google이 개발한 Go 언어로 향하고 있습니다.
Go 특유의 간결함, 군더더기 없는 동시성 처리 모델(고루틴!), 그리고 컴파일 한 번으로 생성되는 가벼운 단일 실행 파일의 매력은, 외부 API를 집약하여 단순 재생산하는 제 서버의 본질적인 역할에 어쩌면 Armeria보다 더욱 극단적으로 부합할 수도 있겠다는 생각이 들더군요. 마치 2년 전 Spring Boot 앞에서 Armeria를 고민했던 그때처럼 말입니다.

그래서 지금, 이 작은 API 서버를 Go 언어로 새롭게 빚어보는, 또 한 번의 즐거운 리팩토링 여정을 조심스레 계획하고 있습니다. 어쩌면 2년 뒤에는 '왜 Armeria에서 Go로 넘어왔는가'라는 주제로 다시 글을 쓰고 있을지도 모르겠습니다. 😉