분산 시스템에서 데이터를 전달하는 효율적인 방법

발표를 보기 앞서

지금은 하나 이상의 컴포넌트로 구성된 백엔드 시스템은 너무나도 자연스러운 시대가 되었습니다.

지금 우리의 삶을 풍요롭고 편리하게 만드는 IT 서비스들이 발전하면서 하나의 서버가 모든 기능을 처리하기에는 여러가지 측면에서 비 효율적입니다. 생산성과 개발 속도 그리고 처리량에서 한계가 있습니다. 코드들은 점점 복잡해져가고, 복잡해진 만큼 사용자의 요구에 맞게 빠르게 개발하기 어렵습니다. 뿐만아니라 점점 늘어나는 클라이언트의 요청 수도 많아지면서 결국 우리는 MSA 혹은 분산 시스템을 선택할 수 밖에 없습니다.

만약 마이크로 서비스 혹은 서비스 컴포넌트들이 하나의 데이터 저장소를 사용하면 어떻게 될까요?

모든 요청들이 하나의 데이터 저장소로 쏠리게 되고, 결국 데이터 저장소에 장애가 발생하면 모든 서비스는 점차 망가지게 됩니다. 데이터 저장소가 단일 장애점(SPOF : Single Point of Failure) 이 됩니다. 그러므로 자연스럽게 서비스마다 그 특성에 적합한 데이터 저장소를 사용하게 됩니다. (마이크로 서비스 아키텍터 패턴 중 Database per Service)

데이터 저장소가 서비스마다 분리되어 있더라도, 서비스들은 결국 데이터를 통합해야 합니다. 서로의 데이터를 참조(조회)하거나 전파(생성, 삭제, 변경)해야 합니다. 시스템의 데이터를 통합하는 가장 일반적인 방법은 API 나 메시지 큐를 사용하는 것입니다. 데이터 저장소가 분리되어있고, 네트워크를 사용하여 데이터를 통합하므로 모든 과정에서 데이터가 누락될 수 있습니다. 이런 현상이 발생하면 결국 서비스 사이에 데이터 불일치가 발생하여 여러분들을 괴롭힐 것입니다.

이 발표는 데이터를 전파/참조하는 과정에서 발생할 수 있는 여러 상황들을 어떻게 풀어야할지 고민한 내용을 포함하고 있습니다.

내용

다음 내용은 “분산 시스템에서 데이터를 전달하는 효율적인 방법”을 간추린 것입니다. 여러분들이 개발하는 애플리케이션 상황과 목적에 맞게 적합한 방법을 찾기를 바랍니다.

  • 데이터 전달 보장 방법론
    • At most once – Producer는 최대 한번만 전달하며 메시지가 누락될 수 있다. 하지만 간단하게 개발할 수 있어서 데이터 전달 누락이 허용하는 시스템에 적합하다.
    • At least once – Producer는 최소 한번만 전달하므로 같은 요청이 한번이상 Consumer 에게 전달될 수 있다. 최소 한번은 전달되므로 클라이언트가 먹등성있게 개발한다면, 신뢰성 있는 시스템을 구축할 수 있다.
    • Exactly once – Producer 와 Consumer 는 요청 상태를 각자 관리하고 있어서 누락과 중복없이 정확하게 한번만 전달할 수 있다. 매우 정확한 전달을 할 수 있지만, 개발 난이도가 높다.
  • RDB 와 REST-API를 사용하는 스프링 애플리케이션에서 데이터 전달 보장 방법론
    • 마이크로 서비스 패턴중 하나인 DataBase per Service 패턴을 사용할 때, 트랜잭션과 REST-API 를 동시에 사용하면서 발생하는 데이터 누락을 설명한다.
    • 데이터 누락을 방지는 첫번째 방법으로 @TransactionalEventListener, TransactionSynchronizationManager 를 사용하는 방법을 설명한다.
    • @Retryable 애너테이션을 사용하여 재시도 하는 방법을 설명한다.
    • Transactional outbox 패턴과 Polling publisher 패턴을 사용하여 At least once 를 구현하는 방법을 설명한다.
  • RabbitMQ 를 사용하는 스프링 애플리케이션에서 데이터 전달 보장 방법
    • Producer 가 정확하게 메시지 큐에 데이터를 저장하는 방법인 Producer Confirm 을 설명한다.
    • 스프링 애플리케이션에서 Producer Confirm을 구현하기 위한 CorrelationData.java 와 RabbitTemplate의 ConfirmCallback 을 사용하는 코드를 소개한다.
    • Consumer 가 정확하게 데이터를 처리하기 위한 방법인 ConsumerAck 과 Dead Letter 를 설명한다.
    • 스프링 애플리케이션에서 ConsumerAck 을 처리하는 방법과 Dead Letter 를 처리하는 코드를 설명한다.
  • Kafka 를 사용하는 스프링 애플리케이션에서 데이터 전달 보장 방법
    • 카프카에서도 Producer Confirm 과 Consumer Ack 을 처리하는 방법을 소개하며, 스프링 애플리케이션에서 적용할 수 있는 코드를 함께 설명한다.

발표자료

이 내용들은 NHN Forward 22 에서 발표했으며, 프레젠테이션 자료는 다음 링크에서 확인할 수 있습니다.

👉 https://forward.nhn.com/2022/sessions/10

이 포스트를 공유해주세요
부릉
부릉

어떻게 하면 더 오랫동안 개발할 수 있을까? 고민하는, 고기를 사랑하는 개발자입니다.
‘스프링 부트로 개발하는 MSA 컴포넌트’, '자바를 다루는 기술', '리눅스 바이블' 등 여러 책을 썼어요.

Articles: 2

의견 남기기

0