피드로 돌아가기
Symfony Messenger: A Great Servant, But a Terrible Master (Or How Asynchrony Cost Me Half My Beard)
Dev.toDev.to
Backend

Race Condition과 외부 제약을 초래한 비동기 처리의 오용 및 동기화 해결

Symfony Messenger: A Great Servant, But a Terrible Master (Or How Asynchrony Cost Me Half My Beard)

Jozef Môstka2026년 4월 23일6intermediate

Context

Symfony Messenger를 활용한 비동기 아키텍처 설계로 응답 속도를 개선했으나, 분산 환경의 데이터 일관성 및 외부 시스템 제약 사항을 간과함. 특히 데이터베이스 Transaction Commit 전 Message Handler가 먼저 실행되는 Race Condition과 SFTP 단일 연결 제한으로 인한 리소스 접근 실패 문제가 발생함.

Technical Solution

  • DB Transaction 완료 전 Handler 실행으로 인한 Resource Not Found 방지를 위해 비동기 처리를 동기 방식으로 전환
  • 즉각적인 데이터 가시성 확보를 위해 DelayStamp 도입 대신 Synchronous Processing을 채택하여 정합성 보장
  • 외부 SFTP 서버의 1-Connection 제한이라는 인프라 제약을 고려하여 병렬 처리 구조를 제거하고 순차적 처리 방식으로 변경
  • 단순 예외 처리로 치부했던 'Resource Not Found' 상태를 시스템 장애 징후로 재정의하여 무분별한 Message Discarding 로직 제거
  • 비동기 처리의 성능 이득보다 데이터 무결성이 우선시되는 도메인 특성에 맞춰 아키텍처 단순화 수행

1. DB Write 작업 후 비동기 메시지를 발행할 때 Transaction Commit 완료 시점을 보장하는지 확인

2. 외부 API/SFTP 연결 시 동시 접속 제한(Concurrency Limit) 수치를 파악하고 이에 맞는 Worker 수 설정

3. 'Not Found' 상태 발생 시 단순 Return null 처리 대신, 재시도 전략(Retry Strategy)이나 명확한 에러 로그 기록 체계 구축

4. 비동기 도입 전, 비즈니스 요구사항이 '즉각적인 가시성'과 '강한 일관성'을 필요로 하는지 검토

원문 읽기