대규모 Rails 애플리케이션의 비즈니스 로직 분리 및 모듈화 전략

RailsConf 2025 Derailing Our Application: How and Why We... by Fito von Zastrow, Alan Ridlehoover

작성자
Ruby Central
발행일
2025년 07월 24일

핵심 요약

  • 1 대규모 Rails 애플리케이션의 복잡성과 테스트 용이성 문제를 해결하기 위해 비즈니스 로직을 Rails 컨스트럭트로부터 분리하고 모듈화하는 전략을 제시합니다.
  • 2 컨트롤러, 뷰(ERB), 모델에서 비즈니스 로직을 PORO(Plain Old Ruby Object)로 추출하고, 도메인 기반의 디렉토리 구조로 재구성하여 코드의 응집도를 높였습니다.
  • 3 도메인 경계를 설정하여 팀 자율성과 책임감을 강화하고, 이를 통해 테스트 커버리지 증가, 복잡성 감소, 문제 해결 속도 향상 등의 긍정적인 성과를 달성했습니다.

도입

본 발표는 Cisco Meraki가 대규모 Rails 애플리케이션을 운영하며 겪었던 도전 과제와 이를 해결하기 위한 전략을 다룹니다. Meraki는 2006년 설립 이후 급격한 성장을 경험했으며, 초기 Rails 개발 방식과 현대적 베스트 프랙티스 부재로 인해 거대한 모델과 컨트롤러, 그리고 뷰에까지 비즈니스 로직이 산재하는 문제에 직면했습니다. 이러한 구조는 코드의 복잡성을 증가시키고 테스트를 어렵게 만들었으며, 조직 전체의 합의 없이는 코드 개선이 불가능하여 개발 속도를 저해하는 요인이 되었습니다. 발표자들은 Rails가 더 이상 충분한 구조를 제공하지 못하고 오히려 개발을 방해한다는 인식을 공유하며, 애플리케이션의 확장 단계에서 이러한 문제를 해결하기 위한 새로운 접근 방식의 필요성을 강조합니다.

Meraki는 애플리케이션의 복잡성을 줄이고 테스트 용이성을 높이기 위해 코드베이스를 모듈화하고, 모놀리스 내부에 명확한 경계를 설정하여 팀의 자율성과 책임감을 강화하는 전략을 채택했습니다. 이 접근 방식은 주로 컨트롤러, 뷰(ERB), 모델에 흩어져 있던 비즈니스 로직을 Plain Old Ruby Object(PORO)로 추출하는 데 중점을 둡니다.

비즈니스 로직 추출 및 모듈화

  • 컨트롤러에서 추출: 대규모 컨트롤러 액션 내의 비즈니스 로직을 더 작은 객체로 분리했습니다. 이는 컨트롤러 테스트의 복잡성을 줄이고 비즈니스 로직에 대한 높은 테스트 커버리지의 투자 수익률을 극대화하기 위함입니다. 예시로, 다중 커피 머신 설정 업데이트 로직을 UpdateWaterTankSettingsUpdateCoffeeMachineSettings와 같은 전용 클래스로 분리하여 컨트롤러는 HTTP 요청 처리와 응답 생성에만 집중하도록 했습니다.
  • 뷰(ERB)에서 추출: ERB 파일 내의 비즈니스 로직은 코드 품질 도구로 분석하기 어렵고 테스트가 까다로웠습니다. 이를 PORO로 대체하여 코드 가독성을 높이고 테스트 용이성 및 코드 품질 측정을 가능하게 했습니다. 예를 들어, 커피 머신 설정 속성을 렌더링하는 로직을 CoffeeMachineConfiguration 클래스로 옮겨 뷰는 데이터 표현에만 집중하도록 했습니다.
  • 모델에서 추출: ‘Fat Model’이라는 기존의 베스트 프랙티스와 달리, 모델에 집중된 비즈니스 로직은 코드 응집도를 낮추고 암묵적 결합을 유발하여 ‘잡동사니 서랍’처럼 변질될 수 있습니다. 이를 해결하기 위해 모델의 특정 메서드 로직을 CoffeeMachineBroadcastDetails와 같은 별도 클래스로 추출하여 모델의 책임을 분리하고 테스트 용이성 및 확장성을 확보했습니다.

도메인 경계 설정 및 네임스페이스 도입

추출된 비즈니스 로직 객체들은 domain/coffee_machine과 같은 도메인 기반 디렉토리 구조로 이동되어 네임스페이스를 형성합니다. 이는 엔지니어들이 전체 400만 라인의 코드베이스를 알 필요 없이 자신의 팀이 소유한 코드에 집중할 수 있도록 인지 부하를 줄여줍니다. 또한, 이 도메인 경계는 팀이 조직 전체의 합의 없이도 자신들의 코드를 개선하고 다양한 접근 방식을 실험할 수 있는 자율성을 부여하며, 동시에 해당 코드에 대한 책임감을 강화합니다. 도메인 내부의 코드 조직 방식(예: 서브도메인 또는 패턴 기반)은 팀의 자율에 맡겨 유연성을 확보했습니다.

결론

Meraki의 사례는 Kent Beck의 3X 모델(탐색, 확장, 추출)을 통해 애플리케이션 개발 라이프사이클을 이해하고, 현재 단계에 맞는 전략적 결정을 내리는 것의 중요성을 보여줍니다. 과거의 개발 방식과 현재의 성장 궤적을 이해하는 것은 미래를 준비하는 데 필수적입니다. Meraki가 도입한 모듈화 및 도메인 경계 설정 전략은 다음과 같은 긍정적인 결과를 가져왔습니다. 모듈화된 코드의 평균 테스트 커버리지는 97% 이상으로 전체 코드베이스의 78%보다 훨씬 높았으며, 평균 메서드 복잡성은 30% 감소했습니다. 또한, 코드 소유권이 명확해짐에 따라 불안정한 테스트 및 심각도 1단계 문제(SEV1)에 대한 대응이 크게 개선되었습니다. 그러나 팀 자율성 부여는 도메인 간의 문제 발생 시 자율성의 범위에 대한 논의가 필요하다는 도전 과제도 동반했습니다. Meraki는 현재 대부분의 팀이 추출 단계에 있으며, 일부 팀은 도메인을 API로 감싸고 모놀리스에서 서비스를 분리하는 다음 단계로 나아가고 있습니다.

댓글 0

댓글 작성

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

아직 댓글이 없습니다

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