event-driven-architecture

3 개의 포스트

네이버 TV (새 탭에서 열림)

VLOps는 학습, 평가, 배포 과정을 Typed Message 단위로 정의하고 이를 감지해 자율적으로 실행하는 이벤트 기반 MLOps 시스템입니다. 기존 파이프라인 방식의 복잡성을 해결하고 시스템 간 느슨한 결합을 통해 클라우드 호환성과 기능 확장성을 극대화한 것이 특징입니다. 이를 통해 사용자는 내부의 복잡한 오케스트레이션 구조를 몰라도 메시지 발행만으로 효율적인 모델 관리 파이프라인을 구동할 수 있습니다. **이벤트 기반 MLOps의 핵심 구조** * 학습, 평가, 배포 등 MLOps의 각 단계를 Typed Message라는 독립적인 데이터 단위로 정의하여 관리합니다. * Event Sensor가 발행된 메시지를 실시간으로 감지하고, 정의된 로직에 따라 적절한 작업을 자율적으로 수행하는 구조를 가집니다. * 메시지 중심의 설계를 통해 각 시스템 간 의존성을 낮추는 느슨한 결합(Loose Coupling)을 실현하여, 특정 클라우드 환경에 종속되지 않는 호환성을 확보했습니다. **기존 파이프라인 방식과의 차별점** * Kubeflow와 같은 전통적인 파이프라인 도구와 달리, 전체 워크플로우에 대한 엄격한 버전 관리가 강제되지 않아 운영의 유연성이 높습니다. * 새로운 기능을 추가할 때 전체 시스템을 재설계할 필요 없이, 단순히 새로운 메시지 타입을 정의하고 추가하는 것만으로 기능을 확장할 수 있습니다. * 사용자는 복잡한 내부 인프라 로직을 이해할 필요 없이 표준화된 메시지만 발행하면 동일한 파이프라인 결과를 얻을 수 있어 개발 경험이 개선됩니다. **Omni-Evaluator와 대시보드를 통한 통합 관리** * Omni-Evaluator는 파편화된 다양한 모델 엔진과 벤치마크 도구들을 하나로 통합하여 일관된 평가 환경을 제공합니다. * VLOps Dashboard를 통해 전체 작업의 진행 상태를 실시간으로 모니터링하고 시각화된 결과 지표를 한눈에 파악할 수 있습니다. * 시스템에 의한 자동 트리거뿐만 아니라, 사용자가 필요 시 직접 이벤트를 발생시켜 특정 평가나 배포를 수행할 수 있는 사용자 주도적 제어 기능을 지원합니다. 모델의 규모가 커지고 복잡해지는 멀티모달 LLM 환경에서는 경직된 파이프라인보다 이벤트 기반의 비동기 아키텍처가 변화에 더 유연하게 대응할 수 있습니다. 인프라의 복잡도를 추상화하고 메시지 기반의 확장성을 확보하려는 조직에게 VLOps와 같은 접근 방식은 매우 실용적인 대안이 될 것입니다.

레거시 결제 원장을 확장 가능한 시스템으로 (새 탭에서 열림)

토스페이먼츠는 20년 된 레거시 결제 원장의 구조적 한계와 도메인 간 강한 결합을 해결하기 위해 MySQL 기반의 신규 원장 시스템을 구축했습니다. 데이터 불변성을 보장하는 INSERT-only 원칙과 이벤트 기반 아키텍처를 도입하여 복합 결제 지원 등 비즈니스 확장성을 확보했습니다. 이 과정에서 발생한 데이터 불일치와 타임아웃 문제를 해결하며 시스템의 자가 회복 능력을 강화하고 안정적인 운영 환경을 마련했습니다. ### 레거시 원장 시스템의 한계와 과제 - **데이터 구조의 불일치:** 결제수단별로 테이블 구조가 다르고, 동일한 성격의 데이터가 서로 다른 테이블에 저장되어 유지보수와 온보딩에 큰 비용이 발생했습니다. - **도메인 간 강한 결합:** 결제, 정산, 회계 등 여러 서비스가 하나의 원장 테이블과 컬럼을 공유하여, 작은 기능 수정 시에도 전사적인 영향도 분석이 필요했습니다. - **구조적 확장성 부족:** 결제와 결제수단이 1:1 관계로 묶여 있어, 더치페이나 복합 결제(카드+포인트)와 같은 현대적인 결제 시나리오를 지원할 수 없었습니다. ### 신규 원장 설계의 3가지 전략 - **데이터 불변성과 일관성:** 모든 승인 내역을 공통 테이블(`approve`)에 저장하고, 수정 대신 INSERT-only 방식을 채택하여 데이터의 정합성을 높이고 데드락을 방지했습니다. - **이벤트 기반의 도메인 분리:** 각 도메인이 직접 DB를 조회하는 대신 Kafka 이벤트를 구독하여 데이터를 처리하게 함으로써 도메인 간 의존성을 제거했습니다. - **결제와 승인 개념의 분리:** '결제'는 주문의 상태를, '승인'은 실제 결제수단의 실행을 의미하도록 분리하여 하나의 결제에 여러 승인 수단이 연결될 수 있는 유연한 구조를 만들었습니다. ### 무중단 마이그레이션 및 정합성 검증 - **비동기 점진적 적재:** 실서비스 장애를 방지하기 위해 기존 원장에 먼저 저장한 후, 신규 원장에는 별도의 ThreadPool을 통한 비동기 방식으로 데이터를 적재했습니다. - **검증 배치 운영:** 비동기 적재 중 발생할 수 있는 누락을 방지하기 위해, 매 5분마다 Read-Only DB를 기반으로 기존 원장과 신규 원장의 데이터를 비교하고 보정하는 배치를 실행했습니다. - **고성능 이관 작업:** 수억 건의 데이터 이관을 위해 Bulk Insert를 도입하고, 네트워크 지연 최소화를 위해 마이그레이션 서버를 DB와 동일한 가용 영역(AZ)에 배치했습니다. ### 운영 중 장애 대응과 시스템 고도화 - **쿼리 최적화:** 옵티마이저의 판단 오류로 발생한 풀 스캔(Full Scan) 문제를 인덱스 힌트(Index Hint) 추가와 롤백 시스템을 통해 빠르게 해결했습니다. - **타임아웃 및 정합성 관리:** MSA 구조에서 서버 간 타임아웃 설정을 일치시키고, 외부 원천사와의 상태 불일치를 해결하기 위한 망취소(Network Cancellation) 로직을 강화했습니다. - **이벤트 처리의 신뢰성:** 아웃박스(Outbox) 패턴과 로그 기반 복구를 통해 이벤트 누락을 방지하고, 헤더에 멱등키를 포함해 중복 이벤트 처리 문제를 해결했습니다. 신규 시스템으로의 전환은 단순한 DB 교체가 아니라 시스템의 지속 가능성을 확보하는 과정입니다. 초기 설계의 완벽함보다 중요한 것은 운영 중 발생하는 예외 상황에 시스템이 스스로 대응하고 회복할 수 있는 '자가 회복 구조'를 갖추는 것이며, 이를 위해 데이터 보정 배치와 로깅 시스템 같은 안전장치를 반드시 고려해야 합니다.

PHP 8: 기본으로 제공되는 (새 탭에서 열림)

비동기 이벤트 기반 아키텍처(EDA)에서 분산 추적을 효과적으로 구현하기 위해서는 추적 데이터 간의 관계를 정의하는 '부모-자식 관계'와 '스팬 링크(Span Links)'의 차이를 명확히 이해해야 합니다. 이 글은 시스템의 논리적 흐름과 데이터의 정확성을 보장하기 위해 각 방식을 언제 적용해야 하는지에 대한 기술적 기준을 제시합니다. 결론적으로, 생산자가 소비자의 완료를 기다리지 않는 비동기 패턴에서는 데이터 왜곡을 방지하기 위해 스팬 링크를 사용하는 것이 권장됩니다. ### 부모-자식 관계의 특성과 비동기 환경에서의 한계 * **직계 계층 구조:** 부모 스팬이 자식 스팬을 생성하고, 자식의 작업이 완료될 때까지 부모가 논리적으로 연관되어 있는 동기식 요청-응답(Request-Response) 모델에 최적화되어 있습니다. * **시간 지표의 왜곡:** 비동기 시스템에서 부모-자식 관계를 강제로 적용하면, 소비자의 처리 시간이 생산자의 전체 지연 시간에 포함되어 계산되는 문제가 발생합니다. 이는 시스템의 실제 성능 지표를 파악하는 데 혼선을 줄 수 있습니다. * **추적 트리의 비대화:** 하나의 이벤트가 수많은 소비자에게 전달되는 일대다(One-to-many) 구조에서 모든 관계를 부모-자식으로 묶으면 추적 데이터의 크기가 지나치게 커지고 시각화 도구에서 분석하기 어려워집니다. ### 스팬 링크를 활용한 유연한 관계 정의 * **인과 관계의 표현:** 두 스팬 사이에 직접적인 계층 구조는 없지만 서로 연관되어 있다는 인과 관계를 명시할 때 사용합니다. 이는 생산자와 소비자가 서로 독립적인 생명 주기를 가질 수 있게 합니다. * **비동기 메시징 최적화:** 메시지 큐나 Pub/Sub 시스템에서 생산자가 메시지를 발행한 후 즉시 자신의 작업을 끝내는 경우, 소비자의 작업은 생산자와 링크로만 연결하여 별도의 트레이스로 관리하는 것이 데이터의 무결성 측면에서 유리합니다. * **성능 및 분석 효율성:** 링크를 사용하면 각 마이크로서비스의 추적 데이터를 독립적으로 유지하면서도, 장애 발생 시 인과 관계를 따라 상위 또는 하위 맥락으로 이동하며 원인을 분석할 수 있는 유연성을 제공합니다. ### 아키텍처 패턴에 따른 선택 가이드 * **Fire-and-forget 패턴:** 생산자가 이벤트를 던지고 다음 작업을 수행하는 경우 스팬 링크가 적합합니다. 이를 통해 생산자의 추적 데이터는 깔끔하게 마무리되고, 소비자의 작업은 새로운 맥락에서 시작됩니다. * **브로커 개입 시나리오:** 메시지 브로커가 중간에 개입하는 경우, 브로커가 메시지를 수신하는 것까지는 부모-자식으로 연결하고, 실제 소비자가 브로커에서 메시지를 가져와 처리하는 단계부터는 링크를 사용하는 하이브리드 방식이 효과적입니다. * **도구 지원 사항 확인:** 사용 중인 분산 추적 백엔드(예: Jaeger, Honeycomb, Datadog)가 스팬 링크의 시각화와 쿼리를 어떻게 지원하는지 확인해야 합니다. 일부 도구는 링크된 트레이스 간의 탐색을 더 직관적으로 지원하여 디버깅 편의성을 높여줍니다. 실제 시스템 설계 시에는 모든 이벤트를 하나의 긴 트레이스로 묶으려는 유혹을 피해야 합니다. 시스템 구성 요소 간의 실행 맥락이 분리되는 지점을 정확히 파악하여, 생산자와 소비자의 결합도가 낮은 비동기 흐름에서는 스팬 링크를 적극적으로 활용함으로써 가독성 높고 정확한 관측 가능성(Observability)을 확보할 것을 권장합니다.