토스 SLASH 24 정리

토스 SLASH24 중 일부 영상을 정리한 글입니다.

리플레이 검증으로 새로운 금융 시스템 안전하게 도입하기

Verifier 개발

  • 토스에서는 국내원장 차세대 프로젝트를 진행
    • 운영중인 기존 C언어, Monolithic으로 구현된 원장 시스템을 Kotlin, MSA로 전환
    • 다음과 같은 제약사항을 두고 전환
      • API 스펙유지
      • DB 스키마 유지
      • 주요 비즈니스 로직 유지
    • 기존 원장 시스템을 사용하
    • 필요시 기존 원장으로 롤백 가능
    • 어려움
      • 기존 시스템 변경
      • 테스트 코드 작성에 대한 리소스 부족
      • 한번 통합 테스트를 위해 많은 선행 작업 필요
  • Read Verifier
    • Read API 검증 가동하ㅗ
    • 기존 원장에 대한 요청와 응답을 비동기로 신규 원장 호출,
    • 위 그림의 Verifier가 Kotlin기반 MSA의 요청, 응답 비교 결과를 저장
    • 어드민에서 API별 verifier 사용여부, 사용시간, 트래픽 비율, 재시도 여부
    • 일별 리포팅
  • Write Verifier
    • 그림
    • 기존 원장에 보내기 전에 차세대 원장에서 처리
    • 트랜잭션을 마치기 전에 트랜잭션 내에서 실행된 CUD 쿼리를 조회 쿼리로 변경, 조회 결과를 저장
      • 조회 쿼리, 결과를 레디스에 저장
    • 트랜잭션 롤백
    • CUD 쿼리 -> 조회 쿼리
      • P6Spy
        • 쿼리 로깅
        • 실행되는 쿼리를 수집하는데 활용
      • ANTLR
        • 수집된 CUD쿼리를 분석해 조회 쿼리로 변환하는데 활용
    • 기존 원장의 요청 처리
    • 요청과 응답을 Verifier로 전송
      • 레디스에 저장된 쿼리, 처리결과와 비교
    • 정리
      • 요청을 미리 처리해보고 롤백하는 방식
      • 동기식으로 동작하기 때문에 성능에 영향을 주어 개발 환경에서만 사용
      • 검증을 위한 기능을 라이브러리로 제공
    • 결과 리포팅

생애 주기가 긴 대출 상품

  • 대출 기간이 10년인 상품이 존재
  • 약정서에 명시된 약정을 향후 10년동안 정확하게 무리없이 수행하는 시스템

  • 발생가능한 이벤트
    • 기준금리 변경
      • 기준금리만 변경되고 가산금리는 유지
  • 개발단계에서 작성된 로직이 향후 10년동안 문제없이 동작하는것을 테스트하는 방법
  • 종단 테스트에서는?
    • 대출 실행, 해지, 상환 등 은 테스트가능
    • 장기적인 기간에 대한 테스트
  • 미래에 실행될 로직을 지금 테스트 하는 방법
    • 대출 시스템이 모놀리식이라는 것을 활용
      • 하나의 시스템, 하나의 데이터베이스
      • 복잡하다는 단점이 있지만 한번 설정으로 대출거래 시스템 세팅 가능
      • 모든 시간관련 로직이 한곳에서 제어
    • 비즈니스
      • 실시간 거래
      • 배치 거래
      • 테스트하려는 거래를 테스트환경에서 순차적으로 수행하면 동일한
  • 독립된 테스트 환경에서 시간을 바꿔가며, 거래실행(실시간, 배치), 검증

구현 레벨

대출 시스템, 데이터베이스 대출 시스템과 제어하는 에이전트는 하나의 pod에서 실행 각 pod별 독립된 테스트환경 구축 가능

시뮬레이션 마다 독립된 데이터베이스 사용

  • 프로시저를 통한 복제
  • 3분이내

Next 코어뱅킹, MSA와 MySQL로 여는 평생 무료 환전 시대

  1. 토스뱅크의 기술 전환 배경

일반적인 은행시스템은 고객 -> 채널계 -> 코어뱅킹(계정계)

  • 채널계: 고객의 트래픽을 받아 코어뱅킹에 전달하는 시스템
  • 코어뱅킹 (계정계): 금원과 관련된 메인 비즈니스 로직을 처리하는 시스템 (모놀리식, Oracle)

[초창기 아키텍처]

코어뱅킹 자체는 레거시(모놀리식)

  • 장점
    • 트랜잭션 처리 용이
  • 단점
    • 한개의 서버에서 모든 트래픽 처리
      • 단일 장애 지점
  • 모놀리식 -> 마이크로서비스
  • 각 서비스들은 마이크로서비스로 분리되었지만 DB는 여전히 Oracle을 공유해서 사용
    • Oracle이 단일 장애지점
  • Oracle을 분리
    • 비용문제 Oracle 장점
  • 신뢰성과 안정성
  • 확장성
  • 성능
  • 오랜기간 축적된 (금융)노하우 단점
  • 단일장애지점
  • 비싼 비용
  • 제한적인 Scale-out
  1. 기술 비교: 원화예금 VS 외화예금 시스템 구조

  2. 외화예금 트랜잭션 아키텍처

동기 비동기로 분리

  1. 외화예금 API 뜯어보기

입금

  • 잔액 변동을 막는 동시성 제어가 필수
  1. 24/365 무중단 환전 서비스 구현 방법

토스뱅크가 차세대를 하지 않는 이유: 지속 가능한 마이그레이션 전략

  • Strangler Fig Pattern

  • 대상선정
  • 분석
  • 설계
  • 구현
  • 검증

대규모 사용자 기반의 마이데이터 서비스 안정적으로 운영하기

  • 70,000TPS를 처리중인 마이데이터 서비스를 다음 관점에서 소개
    • 장애 대응
    • 토스 시스템 부하 개선
    • 피크 트래픽 제어

보상 트랜잭션으로 분산 환경에서도 안전하게 환전하기

  • 토스뱅크는 모놀리식의 뱅킹 시스템을 마이크로서비스로 분리
  • 팀, 도메인 등의 특성에 따라 원화계좌와 외화계좌가 분리되어 개발됨
    • 데이터베이스도 분리되어있는 마이크로서비스
  • 환전은 위와같이 서버와 데이터베이스가 분리된 환경에서 구현되어야 했음
    • 즉 데이터베이스 레벨에서 원자성을 유지할수 없음
    • 이를 위해 토스는 분산 트랜잭션을 구현해야했음
  • 분산 트랜잭션으로는 대표적으로 두 가지가 존재
    • Two Phase Commit (2PC): 두 단계로 구분해서 커밋 수행
      • Voting
        • Coordinator가 트랜잭션 참여자에게 commit 가능여부를 질의
        • 트랜잭션 참여자들은 응답
          • 모든 서비스가 트랜잭션 가능인경우 아래의 Commit단계 진행
          • 하나의 서비스라도 커밋이 불가능한 경우 모든 서비스에 Rollback 요청
      • Commit
        • Coordinator가 트랜잭션 참여자에게 commit 요청
    • Saga 패턴
      • 각 서비스들이 작은 로컬트랜잭션을 실행하면서 진행
      • 특정 단계에서 실패하면 보상 트랜잭션 실행
  • 두 가지 방식 비교

  • 토스는 환전서비스를 위해 Saga 패턴 선택
    • 높은 트래픽 처리
    • 다양한 트랜잭션 참여자들이 추가될 가능성이 존재
  • Saga는 크게 두 가지 방식으로 구분
    • [두 가지 방식의 사가 그림]
    • Choreography Saga
      • 중앙제어자 없이 메시지 브로커를 사용해서 이벤트 교환하며 진행
      • 장점
        • 단일 장애지점 없음
        • 느슨한 결합
      • 단점
        • 현재 진행중인 트랜잭션 상태 추적/디버깅 어려움
    • Orchestration Saga
      • Orchestrator가 각 서비스들에게 트랜잭션과 보상트랜잭션을 명령하며 진행하는 방식
      • 장점
        • 현재 진행중인 트랜잭션 상태 추적 쉬움
      • 단점
        • 단일 장애지점이 존재
        • 모든서비스가 결합됨
  • 토스는 Orchestration Saga를 선택
    • 클라이언트의 요청을 받는 환전 서버(Orchestrator 역할 가능)가 필요
    • 진행중인 환전들의 상태를 관리/추척
  • 환전 성공과 실패
    • 정상적인 상황에서는 환전 서버가 원화계좌, 외화계좌에 요청하고 각 서비스들이 성공하는 케이스
    • 그 외 실패 가능 케이스들이 존재
      • 정상적인 실패
      • 비정상적인 실패
    • 정상적인 실패 처리
      • 보상트랜잭션으로 성공한 서비스의 상태를 롤백
      • 출금부터 처리
        • Saga Pattern의 특징은 중간상태가 노출되는것
        • 입금된 돈이 사용되면 취소가 어려움 (보상트랜잭션 수행의 어려움)
    • 비정상적인 실패 처리
  • 서버간 통신 방식

    • 메시지방식은 메시지브로커 레벨에서 에러를 핸들링 및 재시도를 지원하기 때문에 대부분의 Saga는 메시징방식으로 구현됨
    • 입금, 출금은 HTTP
      • 입출금 결과를 알고넘어가야함 (동기)
      • 유저는 환전이 즉시 완료되기를 기대함 (HTTP는 타임아웃 구현이 쉬움)
    • 출금 취소는 Messaging (메시지 브로커에 에러핸들링을 위임)
      • 출금 취소는 마지막 과정
      • 유저가 기다릴 필요 없음(비동기)
      • 출금 취소에 에러 핸들링을 하기 싫음, 결과적 정합성 보장만 되면 됨
  • 에러 핸들링
    • 출금/입금 요청에서 타임하웃 또는 실패를 응답받는경우
      • 출금/입금 결과를 확인, 그 후속 (보상 트랜잭션) 처리 수행
    • 결과확인에서 실패하는 경우
      • 메지시를 지연해서 발행할 수 있는 Kafka Message Scheduler가 존재
      • 지연을 통해 실패한 서비스가 회복할 시간을 줌
      • 환전 서비스는 메지시를 컨슘해 보상트랜잭션 처리
    • 지연 메시지 발행이 실패하는경우
      • Batch를 통해 재처리
        • Orchestration가 마지막 환전의 상태를 저장하고 있음
        • 이후 프로세스를 배치를 통해 처리
    • 원화계좌가 출금취소 메시지를 받는것에 실패하는 경우
      • Eventually Consistency: Consumer Dead Letter (CDL) 사용
        • 원화 계좌는 메지시를 DL 서버로 전송
        • DL 서버는 서비스 메시지 브로커로 출금 취소 메시지 발생
  • Transactional Messaging
    • Saga에서는 Local Transactional commit과 Message발행이 원자적으로 이루어져야함
      • 입금 실패로 인한 환전 실패 처리와 출금 취소 메시지 발행은 항상 같이 이루어져야함
    • 이를 위해 토스는 Producer Dead Letter를 사용
      • 그 외 Outbox Pattern 등이 존재

  • 모니터링
  • 결론 및 성과
    • 손쉬운 확장 가능
      • 회계
    • 또 다른 Saga로 부족한돈 자동환전 결제
    • Trade Off
      • pros
        • MSA 로의 전환, 기존 계정계 시스템이 가지는 문제 해결
        • 계정계 시스템들과의 느슨한 결합, 확장 가능한 구조
      • cons
        • 트랜잭션 구현의 복잡도 증가

References