시스템 아키텍트System Architect

행성 규모의 이질적인 메시징 패브릭을 매개하여 레거시 기업 메시지 버스(**IBM MQ**, **TIBCO Rendezvous**)와 클라우드 네이티브 이벤트 스트리밍 플랫폼(**Apache Kafka**, **AWS EventBridge**)을 연결하고, 금융 거래 명령에 대해 정확히 한 번만 처리되도록 하며, 대기열 깊이 원격 감시를 기반으로 한 자율 어댑터 탄력성을 구현하고, 하이브리드 네트워크 토폴로지에서 선두 차단 없이 유해 메시지 격리를 보장할 수 있습니까?

Hintsage AI 어시스턴트로 면접 통과

질문에 대한 답변

질문의 배경

기업 현대화 이니셔티브는 재작성 없이 수십 년 된 IBM MQTIBCO 인프라를 Apache KafkaAWS EventBridge와 통합할 것을 점점 더 요구합니다. 금융 서비스는 구체적으로 거래 명령에 대해 정확히 한 번의 의미가 필요하며, 중복 실행은 실제 위험과 규제 위반으로 이어질 수 있습니다.

문제

레거시 메시지 버스는 본래의 멱등성 원시가 없고 파괴적 읽기를 포함한 강제적인 FIFO 순서를 사용하며, 클라우드 네이티브 스트림은 오프셋 기반 재생을 위해 불변 로그를 선호합니다. 프로토콜 불일치—고정 폭 COBOL 복사본과 설명이 훌륭한 Avro—과 이질적인 전달 보장으로 인해 어댑터 확장 이벤트 또는 일시적인 네트워크 분할 동안 메시지 손실 또는 중복이 발생합니다.

해결책

Kubernetes 내에서 Apache Camel 또는 Spring Cloud Stream을 실행하는 상태 비저장 프로토콜 어댑터 파드를 배포하여 시스템 간의 중재를 수행합니다. 처리된 메시지 UUID를 TTL 만료와 함께 추적하기 위해 Redis 또는 Amazon DynamoDB를 사용하여 멱등 소비자 패턴을 구현합니다. 원자적 오프셋 커밋 및 메시지 생성을 보장하기 위해 읽기_커밋 격리 수준과 함께 Kafka 트랜잭션을 활용합니다. Prometheus를 통해 내보낸 IBM MQ 대기열 깊이 메트릭을 기반으로 KEDA(클라우드 이벤트 기반 자동 확장)를 사용하여 어댑터를 자동 확장합니다. 헤드오브 라인 차단을 방지하기 위해 Amazon SQS 또는 Apache Pulsar에서 구현된 **Dead Letter Queues (DLQ)**에 유해 메시지를 격리합니다.

실제 상황

1티어 투자 은행은 IBM MQ를 실행하는 z/OS 메인프레임에서 AWS MSK(Kafka)로 실시간 거래 실행 흐름을 중단 없이 마이그레이션해야 했습니다. 레거시 시스템은 매수/매도 주문을 나타내는 COBOL 복사본 인코딩 메시지를 게시하는 반면, 현대 Java 마이크로서비스는 Avro 직렬화 이벤트를 소비했습니다. 시장 변동성 동안 메시지 속도가 50,000 TPS로 급증하여 초기 브리지 구현이 불충분한 TCP 버퍼 크기와 백프레셔 부족으로 인해 메시지를 드롭했습니다.

해결책 1: 이중 기록 및 조정. 이 접근 방식은 메인프레임을 수정하여 IBM MQApache Kafka에 동시에 기록한 다음 격차를 수정하기 위해 야간 조정 작업을 실행합니다. 장점으로는 최소한의 인프라 변경과 빠른 구현 기간이 있습니다. 단점으로는 거래 중복이 발생하면서 정확히 한 번의 의미를 위반하고, 조정 지연으로 인해 규제 감사 문제가 발생하며, 갈등 해결을 위한 수동 개입이 자동화 SLO를 위반하게 됩니다.

해결책 2: 저장 및 전달과 XA 트랜잭션. 두 단계 커밋 경계를 따라 Kafka 트랜잭션 생산자와 조정되는 WebSphere MQX/Open XA 리소스 관리자로 구현합니다. 장점으로는 원자적 커밋 프로토콜을 통한 강력한 일관성을 제공합니다. 단점으로는 지역 간 복제를 진행하는 동안 WAN 링크 전반에 걸쳐 밀리초 동안 잠금을 유지하고, 100ms 미만의 지연 SLO를 위반하는 차단 동작 등입니다.

해결책 3: 외부화된 중복 제거를 가진 상태 비저장 프로토콜 브리지. COBOLAvro로 변환하는 Apache Camel 브리지를 Kubernetes 배포로 배포하되, DynamoDB에서 고유한 UUID 체크를 사용하여 메시지를 생산하기 전에 처리합니다. KEDAMQSC 명령에 의해 보고된 대기열 깊이를 기반으로 파드를 확장합니다. 장점으로는 멱등성을 통해 정확히 한 번을 보장하는 수평 확장 가능한 비차단 아키텍처입니다. 단점으로는 DynamoDB 용량 계획 및 Camel 경로 모니터링을 위한 운영적 성숙도가 필요합니다.

선택된 해결책 및 결과

해결책 3이 주 선택되었고, 50ms 미만의 종단 간 지연을 유지했습니다. 블랙 프라이데이 거래량을 시뮬레이션하는 스트레스 테스트 중, 시스템은 중복 없이 250만 개의 메시지를 처리했습니다. 잘못된 형식의 메시지(필수 CUSIP 필드 누락)가 나타난 경우, 서킷 브레이커(Resilience4j)가 열리며 잘못된 메시지를 Amazon SQS DLQ로 우회시키고 합법적인 거래가 흐르도록 하여 초기 파일럿에서 경험한 재앙적인 백로그를 방지했습니다.

후보자들이 자주 놓치는 것

레거시 MQ가 메시지 중복 제거가 부족하고 Kafka 소비자가 오프셋 커밋 실패로 인해 메시지를 재처리할 수 있을 때 정확히 한 번의 의미를 어떻게 유지합니까?

후보자들은 종종 Kafka 멱등 프로듀서만 제안하는데, 이는 MQ-to-Kafka 경계를 초월한 중복 제거 문제를 해결하지 않습니다. 올바른 접근 방식은 메인프레임이 메시지를 자신의 DB2 데이터베이스 내에서 트랜잭션적으로 아웃박스 테이블에 기록하고, 그런 다음 CDC(Change Data Capture) 커넥터인 Debezium이 변경 사항을 Kafka에 스트리밍하는 아웃박스 패턴을 결합해야 합니다. 소비자 측에서는 멱등성을 보장하기 위해 소비자가 로컬 데이터베이스 트랜잭션을 사용하여 UUID를 저장소에 원자적으로 기록합니다.

프로토콜 어댑터 브리지를 재배포하지 않고 COBOL 복사본 스키마 진화를 어떻게 처리합니까?

대부분 후보자들은 COBOL 복사본에서 정적 코드 생성을 제안하는데, 이 과정에서는 스키마 변경마다 재배포가 필요합니다. 강력한 해결책은 Runtime Schema Resolution을 사용하여 메시지 헤더에 있는 버전 ID를 참조하여 Git 또는 AWS S3에 복사본 정의를 저장하는 것입니다. Apache Camel 경로는 메시지 헤더에 지정된 스키마 버전을 기반으로 메시지를 파싱하기 위해 JRecord와 동적 클래스 로딩을 사용합니다. Kubernetes ConfigMap 또는 AWS AppConfig를 결합하여 포드 재시작 없이 스키마를 새로 고치고 이로써 메인프레임 릴리스 주기를 클라우드 배포 파이프라인과 분리할 수 있습니다.

클라우드 목적지의 장기 중단 동안 레거시 MQ 대기열이 최대 깊이에 도달하는 것을 어떻게 방지합니까?

후보자들은 종종 무한 버퍼링이나 MQ 디스크 확장을 제안하는데, 이는 단지 불가피함을 지연시킬 뿐입니다. 올바른 전략은 IBM MQ 응용 프로그램 메시지 라우팅 또는 MQIPT(MQ 인터넷 통과)를 구성하여 대기열 깊이가 80%를 초과할 때 임계값 알람을 트리거하는 것입니다. 브리지는 읽기를 중지(역압력을 적용)하고 저장 및 전달 모드로 전환하여 수신 메시지를 Amazon S3 또는 Azure Blob Storage에 직렬화된 파일로 기록합니다. 연결이 복원되면 사이드카 컨테이너가 AWS SDK 다중 파트 업로드를 사용하여 S3 객체를 Kafka로 재생하여 백로그를 소모하면서 MQ 디스크 고갈이나 메시지 손실 없이 처리합니다.