AngelList의 Ruby on Rails 모놀리스: 아키텍처, 개발 관행 및 도전 과제

Alexander Stathis: Scaling a Modular Rails Monolith at AngelList

작성자
Ruby on Rails Youtube
발행일
2025년 10월 21일

핵심 요약

  • 1 AngelList는 복잡한 Rails 모놀리스를 Packwerk로 모듈화하고, Active Record 콜백 등 Rails '마법'을 지양하며 명시적인 서비스 객체 중심의 비즈니스 로직을 구축했습니다.
  • 2 비동기 작업 처리를 위해 Sidekiq, Good Job, Temporal 등 다양한 솔루션을 문제 유형에 따라 복합적으로 활용하며, 단일 '완벽한' 솔루션이 아닌 다중 접근 방식을 채택합니다.
  • 3 Sorbet를 통한 점진적 타입 시스템 도입과 Tapioca 컴파일러 확장 Gem인 Boba 개발로 코드 안정성과 리팩토링 용이성을 확보하고, 신규 엔지니어 온보딩 시 학습 능력을 중시합니다.

도입

이번 'On Rails' 팟캐스트에서는 AngelList의 수석 소프트웨어 엔지니어인 Alexander Status와 함께 AngelList의 복잡한 Ruby on Rails 애플리케이션 아키텍처와 개발 철학에 대해 심도 깊은 대화를 나눴습니다. AngelList는 수년간 복잡한 Rails 모놀리스를 발전시켜 왔으며, 투자, 회계, 뱅킹 분야의 정교한 비즈니스 로직을 처리하면서도 Ruby on Rails에 대한 확고한 신념을 유지하고 있습니다. 본 에피소드에서는 AngelList가 직면한 기술적 결정과 그들이 채택한 실용적인 솔루션들을 상세히 조명합니다.

AngelList의 Rails 아키텍처 및 모듈화

AngelList는 약 40여 명의 엔지니어로 구성된 팀을 운영하며, 핵심 제품은 Rails 모놀리스 기반입니다. 최근 인수한 회사의 Node.js 기반 제품도 일부 사용하고 있으나, 주력은 Rails입니다. 특히, 과거 마이크로서비스로 분리되었던 기능을 Rails 엔진 형태로 모놀리스 내부에 통합하는 과정을 거쳤습니다. 이는 두 시스템 간의 복잡한 네트워크 통신 및 통합 문제를 해결하고 Ruby 코드 직접 호출의 효율성을 높이기 위함입니다.

모놀리스 내부의 모듈 간 의존성 관리를 위해 Shopify에서 개발한 정적 분석 도구인 Packwerk를 도입했습니다. Packwerk는 각 모듈의 개념적 경계를 명확히 하고, 의도치 않은 의존성 발생을 방지하여 코드베이스의 응집도를 유지하는 데 핵심적인 역할을 합니다. 이러한 접근 방식은 복잡한 비즈니스 도메인(법률 및 경제 구조)을 효과적으로 분리하고 관리하는 데 기여합니다.

Rails ‘마법’ 회피 및 명시적 코드 작성

AngelList 팀은 Active Record 콜백, 메타프로그래밍, Monkey Patching 등 Rails의 ‘마법’으로 불리는 암묵적인 동작들을 의도적으로 지양합니다. 이는 디버깅의 어려움과 코드 이해도를 낮추는 요소를 제거하고, 특히 Ruby/Rails에 익숙하지 않은 신규 엔지니어들의 온보딩을 용이하게 하기 위함입니다. 대신, 비즈니스 로직은 다음과 같은 방식으로 구현됩니다.

  • 서비스 계층 중심: 대부분의 비즈니스 로직은 Service 모듈 내 클래스 메서드 형태로 정의됩니다. 예를 들어, ObjectCreateService.create와 같은 명시적인 패턴을 사용합니다.

  • 씬 모델/컨트롤러: Active Record 모델과 컨트롤러는 최소한의 로직만 포함하며, 비즈니스 규칙은 서비스 계층으로 분리됩니다.

  • 트랜잭션 관리: 데이터 일관성이 중요한 작업(예: 여러 모델 생성/업데이트)은 명시적인 데이터베이스 트랜잭션으로 묶어 원자성을 보장하고, 실패 시 전체 롤백을 통해 데이터 무결성을 유지합니다.

  • GraphQL Ruby 활용: 클라이언트(Next.js 프론트엔드)와의 통신은 GraphQL Ruby를 통해 이루어지며, 클라이언트가 필요한 데이터를 직접 정의할 수 있어 유연하고 효율적인 데이터 페칭이 가능합니다. N+1 쿼리 문제를 해결하기 위해 GraphQL Batch Loader와 같은 Gem을 사용합니다.

다중 데이터베이스 및 비동기 작업 솔루션

AngelList는 MySQL과 PostgreSQL 등 여러 데이터베이스를 혼용하고 있습니다. 이는 과거 기술 부채(레거시 MySQL)와 특정 Gem(Good Job) 사용 목적 등 다양한 이유에서 비롯되었으며, 다중 데이터베이스 환경에서의 트랜잭션 관리(예: 중첩 트랜잭션)는 복잡성을 야기합니다.

비동기 작업 처리에 있어서는 Sidekiq, Good Job, Temporal, Delayed Job 등 다양한 도구를 실험하고 활용했습니다. 이들은 단일 솔루션으로는 모든 비동기 작업 요구사항을 충족하기 어렵다는 결론에 도달했습니다.

  • Sidekiq의 한계: Redis 기반의 Sidekiq는 빠른 처리에 유리하지만, 작업 후 가시성(observability)이 부족하고 특정 기능(unique jobs)에서 문제가 발생했습니다.

  • Good Job의 장단점: PostgreSQL 기반의 Good Job은 작업 가시성이 뛰어나지만, 대량의 작은 작업 처리 시 성능 문제가 있었습니다.

  • Temporal의 역할: 복잡하고 장기 실행되며 높은 신뢰성과 가시성이 요구되는 워크플로우에는 Temporal을 도입했습니다. Temporal은 워크플로우 오케스트레이션 도구로, 작업의 실패 시 복구 및 진행 상황 추적에 매우 효과적입니다. 간단하고 빠르게 처리되는 ‘fire and forget’ 방식의 작업(예: 이메일 발송)에는 Good Job이나 SolidQueue와 같은 다른 솔루션을 고려하고 있습니다.

Sorbet를 활용한 정적 타이핑 및 Boba Gem 개발

AngelList는 Ruby에 Sorbet라는 점진적 타입 시스템을 도입하여 코드의 안정성과 개발 생산성을 높였습니다. Sorbet는 Ruby의 동적 특성으로 인해 발생하는 일부 표현의 어려움이 있지만, 타입 안정성을 통해 리팩토링을 용이하게 하고 잠재적 버그를 사전에 방지하는 데 큰 도움이 됩니다.

Sorbet의 정적 분석 도구는 Rails와 같은 DSL(Domain Specific Language)이나 Gem에 대한 타입 파일(RBI)이 필요합니다. Shopify의 Tapioca Gem은 이러한 RBI 파일을 자동으로 생성해 주는 강력한 도구입니다. 그러나 Tapioca의 기본 Active Record 컴파일러는 모든 필드를 nilable로 추론하여 코드 작성 시 불필요한 T.must 호출을 강제하는 불편함이 있었습니다. 이를 해결하기 위해 Alexander Status는 Boba Gem을 직접 개발했습니다. Boba는 Tapioca의 확장으로, Active Record 모델의 유효성 검사(presence validator) 및 데이터베이스 제약 조건(not-null index)을 기반으로 nilable이 아닌 필드를 정확하게 추론하는 커스텀 컴파일러를 제공합니다. 이는 코드의 가독성과 개발 경험을 크게 개선했습니다.

개발 환경 및 온보딩

신규 엔지니어 온보딩을 위해 AngelList는 ASDF, Docker를 활용하여 일관된 로컬 개발 환경을 구축합니다. 특히, Tonic이라는 데이터 스크러빙(scrubbing) 솔루션을 사용하여 프로덕션 데이터베이스의 PII(개인 식별 정보)를 제거하고 서브셋을 생성하여 로컬 개발 환경에 로드합니다. 이는 실제와 유사한 복잡한 데이터를 PII 노출 없이 활용할 수 있게 하여, 신규 엔지니어들이 복잡한 데이터 그래프를 빠르게 이해하고 작업할 수 있도록 돕습니다.

AngelList는 신규 엔지니어 채용 시 Ruby/Rails 경험보다는 뛰어난 학습 능력과 문제 해결 능력을 가진 인재를 선호합니다. Rails의 높은 생산성과 학습 용이성 덕분에, 경험이 없는 엔지니어들도 한두 달 안에 코드베이스에 기여할 수 있다고 강조합니다.

결론

AngelList는 복잡한 금융 도메인에서 Ruby on Rails를 성공적으로 활용하며, 단순한 기술 스택 사용을 넘어 비즈니스 요구사항에 최적화된 아키텍처와 개발 문화를 구축했습니다. Packwerk를 통한 모듈화, Rails '마법'을 지양하는 명시적 코드 작성, Sorbet 및 Boba Gem을 통한 타입 안정성 확보, 그리고 다양한 비동기 솔루션의 전략적 활용은 그들의 실용적인 접근 방식을 보여줍니다. 특히, 신규 엔지니어의 빠른 온보딩과 생산성 유지를 위해 학습 능력과 적응력을 중시하는 채용 철학은 Rails의 본질적인 장점과 결합되어 AngelList가 지속적으로 혁신을 이룰 수 있는 원동력이 되고 있습니다. 이는 Ruby on Rails가 여전히 강력하고 유연한 웹 개발 프레임워크임을 입증하는 사례라 할 수 있습니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!