grpc

2 개의 포스트

일 평균 30억 건을 처리하는 결제 시스템의 DB를 Vitess로 교체하기 - 2. 개발 및 운영기 (새 탭에서 열림)

LINE Billing Platform 팀은 일 평균 30억 건의 요청을 처리하는 대규모 결제 시스템을 운영하기 위해 기존 Nbase-T에서 Vitess로 성공적인 데이터베이스 마이그레이션을 수행했습니다. 이 글에서는 성능 문제와 개발 편의성을 고려해 gRPC 대신 MySQL 프로토콜을 선택한 과정과 효율적인 데이터 처리를 위한 샤딩 전략을 상세히 다룹니다. 또한 VTOrc와 Prometheus를 활용한 자동 복구 및 모니터링 체계를 구축하여 분산 데이터베이스 환경에서도 높은 안정성을 확보한 실무 노하우를 공유합니다. ### 프로토콜 선정 및 개발 환경 구축 * VTGate는 gRPC와 MySQL 프로토콜을 모두 지원하지만, gRPC 사용 시 `http2: frame too large` 에러와 CPU 오버헤드가 발생하여 최종적으로 MySQL 프로토콜을 채택했습니다. * Java 클라이언트 사용 시 gRPC 프로토콜은 쿼리 결과를 객체로 변환하는 과정이 번거롭고 Vitess 측에서도 현재 MySQL 프로토콜 사용을 권장하고 있습니다. * 익숙한 MySQL 프로토콜을 사용함으로써 기존 개발 경험을 유지하면서도 Vitess의 샤딩 기능을 안정적으로 활용할 수 있게 되었습니다. ### 키스페이스 설계 및 데이터 처리 방식 * 시스템은 크게 두 개의 키스페이스로 분리되어 있습니다. '글로벌 키스페이스'는 단일 샤드로 구성되어 자동 증가(Auto-increment)하는 샤딩 키를 관리합니다. * 실제 데이터가 저장되는 '서비스 키스페이스'는 N개의 샤드로 분산되어 있으며, 코인 잔액 및 충전/사용 내역 등의 데이터를 저장합니다. * 서비스 키스페이스는 'Hash Vindex'를 사용하여 데이터를 균등하게 분산하며, 애플리케이션이 쿼리에 샤딩 키를 포함하면 VTGate가 해당 샤드를 자동으로 특정해 효율적인 요청 처리가 가능합니다. ### MySQL 호환성 및 주요 기능 활용 * 트랜잭션 격리 수준은 단일 샤드일 경우 `REPEATABLE READ`, 다중 샤드일 경우 `READ COMMITTED`가 적용됩니다. * Vitess는 MySQL 프로토콜을 지원하지만 일부 쿼리 제약 사항이 존재하므로, `unsupported_cases.json`을 통해 사전에 호환성을 확인해야 합니다. * 분산 샤드 간 트랜잭션을 지원하는 'Two-Phase Commit(2PC)' 기능과 쿼리 실행 계획을 분석하는 'VEXPLAIN/VTEXPLAIN' 등을 통해 분산 환경의 제약을 보완하고 있습니다. ### 안정적인 운영을 위한 모니터링 및 장애 복구 * 자동 복구 도구인 'VTOrc'를 도입하여 토폴로지 서버와 VTTablet의 데이터를 기반으로 문제를 자동 감지하고 복구합니다. * Prometheus를 통해 VTOrc의 지표(Metrics)를 수집하며, 장애 발생 시 이메일과 Slack으로 알람이 전달되도록 구성했습니다. * VTAdmin 웹 UI를 활용해 복구 내역을 시각적으로 확인하고, `tablet_alias`를 통해 문제가 발생한 MySQL 노드를 즉각적으로 식별하여 운영 효율성을 높였습니다. 대규모 분산 환경에서 Vitess를 도입할 때는 성능과 유지보수를 위해 gRPC보다는 MySQL 프로토콜 사용을 우선적으로 고려하는 것이 좋습니다. 또한 단일 샤드와 다중 샤드 간의 트랜잭션 격리 수준 차이 및 쿼리 제약 사항을 면밀히 검토하여 애플리케이션 로직을 설계해야 하며, VTOrc와 같은 도구를 적극 활용하여 고가용성 운영 체계를 구축하는 것이 중요합니다.

DDD를 Merchant 시스템 구축에 활용한 사례를 소개합니다 (새 탭에서 열림)

기존의 음식 배달 중심 시스템에서 벗어나 소매 상품 판매에 최적화된 새로운 Merchant 시스템을 구축하기 위해 도메인 주도 설계(DDD)를 도입했습니다. 이번 프로젝트는 DDD가 단순히 코드 구현 기술이 아니라, 도메인의 역할과 책임을 명확히 정의하고 이를 바탕으로 조직 구조와 협업 방식을 설계하는 방법론임을 보여줍니다. 클린 아키텍처와 비동기 이벤트 기반의 모듈 구성을 통해 시스템의 확장성을 확보하고, 글로벌 팀 간의 원활한 협업 체계를 마련하며 성공적으로 시스템을 론칭했습니다. **소매 플랫폼으로의 전환과 도메인 정의** * 기존 시스템의 '음식점 기반 소매 판매' 한계를 극복하기 위해 독립적인 Merchant 시스템을 설계했습니다. * Merchant 시스템은 점포, 상품, 재고 등의 정보를 제공하고, 실제 판매는 '소비자 플랫폼'에서 담당하는 구조로 역할을 분리했습니다. * 핵심 도메인을 점포(shop), 상품(item), 카테고리(category), 재고(inventory), 주문(order)의 다섯 가지로 정의하여 복잡도를 낮추었습니다. **클린 아키텍처를 활용한 시스템 설계** * 도메인 엔티티가 외부 환경의 변화에 영향을 받지 않도록 클린 아키텍처를 채택했습니다. * 모든 팀원이 쉽게 이해하고 따를 수 있는 명확한 계층 구조를 통해 유지보수 편의성을 높였습니다. * 의존성 방향을 내부(도메인)로만 허용하여 비즈니스 로직의 순수성을 유지했습니다. **비동기 기반의 모듈 및 통신 구조** * 시스템을 외부 요청을 받는 'API' 모듈과 비즈니스 로직을 처리하는 '엔진' 모듈로 분리하여 가용성을 높였습니다. * gRPC를 통한 API 제공과 Apache Kafka 기반의 내부 통신을 결합했으며, Decaton 라이브러리를 사용해 파티션 대비 높은 처리량을 확보했습니다. * 플랫폼 특성을 고려하여 즉각적인 응답보다는 최종 일관성(Eventual Consistency)과 빠른 API 응답 능력에 초점을 맞춘 비동기 구조를 설계했습니다. **글로벌 협업과 조직의 일치(Conway's Law)** * 한국 팀은 핵심 도메인(Core)을, 일본 팀은 현지 시스템 연계(Link, BFF)를 담당하도록 조직을 구성해 콘웨이의 법칙을 실천했습니다. * 의사결정 과정과 논의 배경을 기록하는 ADR(Architectural Decision Record)을 활용해 조직 간의 공감대를 형성하고 불필요한 재논의를 방지했습니다. * 추상화된 연계 계층을 통해 새로운 소비자 플랫폼이 추가되더라도 핵심 도메인의 변화는 최소화되는 유연한 구조를 만들었습니다. 성공적인 DDD 적용을 위해서는 헥사고날 아키텍처와 같은 기술적인 구현에만 매몰되지 않는 것이 중요합니다. 도메인의 역할과 책임을 먼저 명확히 정의하고, 그 경계에 맞춰 팀 조직과 소통 구조를 설계할 때 진정한 설계의 이점을 얻을 수 있습니다. 시스템의 아키텍처가 조직의 소통 구조를 반영한다는 점을 인지하고, 기술과 조직 관리의 균형을 맞추는 접근이 권장됩니다.