Bloomo는 사용자가 투자 포트폴리오를 구축하고, 미국 주식 및 ETF에 투자하며, 자동 리밸런싱 및 배당금 재투자를 수행하고, 모든 거래를 대리 실행할 수 있는 모바일 앱을 제공합니다. 특히 사용자 90% 이상이 포트폴리오 복사를 통해 투자를 시작하여 진입 장벽을 낮춥니다.
핵심 아키텍처 원칙
Bloomo는 “고객 자금에 직접적으로 영향을 미치는지 여부에 따라 시스템을 분리한다”는 단일 원칙을 정의했습니다. 이는 엄격한 시스템 분리로 이어집니다.
-
Ruby on Rails: API, 사용자, 관리, 신원 확인, 유효성 검사
-
Go: 거래, 포트폴리오, 자금, 결제
Ruby on Rails의 역할 및 선택 이유
Rails는 자금 이동을 제외한 모든 영역에 선택되었습니다.
-
선택 이유: ORM, 마이그레이션, 인증, 테스트 기능 기본 제공; 빠르게 변화하는 비즈니스 및 관리 인터페이스에 적합; 풍부한 Rails 엔지니어 풀; 성숙한 보안 기본 요소.
-
실제 역할:
- 계정 생성 및 신원 확인: 이름, 주소, 신원 데이터, eKYC 통합, 동의 흐름 관리.
attr_encrypted를 사용하여 레코드별 암호화 키를 보장합니다. - 인증 게이트웨이: Go 서비스 앞에 위치하여 보안 게이트웨이 역할 수행. 초기 Devise에서 Firebase Authentication으로 마이그레이션하여 2FA를 지원합니다. Go 서비스는 인증되지 않은 트래픽을 처리하지 않습니다.
- 증권 운영 및 관리: 계정 승인, 거래 모니터링, 규제 준수 문서 관리, 유지보수 모드, 기능 플래그, 강제 클라이언트 업데이트.
motor-admin-rails와 Sidekiq을 활용합니다.
- 계정 생성 및 신원 확인: 이름, 주소, 신원 데이터, eKYC 통합, 동의 흐름 관리.
Go의 역할 및 자금 안전성 확보
Go는 포트폴리오 계산, 매수/매도 주문, 리밸런싱, 배당금 재투자, 거래 결제, 현금 조정, Alpaca Securities와의 통신 등 핵심 자금 관련 작업을 처리합니다. 시스템은 속도보다는 정확성에 최적화되어 있습니다.
- 자금 안전성 확보 방안:
- 멱등성(Idempotent) API: 동일한 요청이 두 번 처리되지 않도록
IdempotencyKey를 사용합니다. - 데이터베이스 행 잠금: 자금 변경 작업 시 원본 레코드를 먼저 잠가 경쟁 상태(race condition)를 방지합니다.
- 일관성 검증: 배치 작업을 통해 자산 총액, 포트폴리오 비중, 현금 잔액 등을 재검증합니다.
- 멱등성(Idempotent) API: 동일한 요청이 두 번 처리되지 않도록
성과 및 도전 과제
-
성과: 책임의 명확한 분리, Rails와 Go의 독립적인 배포, 엔지니어의 인지 부하 감소, 팀 내 강력한 기술 다양성.
-
도전 과제: 복잡한 통합 테스트, 두 언어에 걸친 모니터링, 채용 및 교육 비용, 시스템 간 데이터 중복.
-
완화 전략: 계정 생성부터 거래 실행까지의 엔드투엔드 테스트, OpenTelemetry, Sentry, SLI/SLO 대시보드를 활용한 관측 가능성(Observability) 강화, 언어가 아닌 고객 문제 중심의 팀 구성, 지속적인 리팩토링을 통한 데이터 중복 제거.