User. 스트랭글러 피그 패턴이 뭐야?

🤖 Gemini:

스트랭글러 피그(Strangler Fig) 패턴은 이름에서 알 수 있듯이, 거대한 나무를 감싸며 자라 결국은 나무를 완전히 대체해버리는 ‘교살자 무화과나무’의 생태에서 착안한 아키텍처 이주 전략입니다.

한마디로 요약하면 **“한 번에 다 갈아엎지(Big Bang) 말고, 야금야금 갉아먹듯 바꿔라”**는 뜻입니다.

1. 서비스화

금융권은 레거시 코드가 많아서 전통적인 방식으로 구현된 곳이 많다. 다만 이러한 방법론을 바탕으로 오랜시간동안 안정화를 해왔지만 기본 구조 자체가 문제가 되어 고질적으로 문제를 일으키는 시스템이기도 하다.

1.1. Message Queue는 전문가에게

주식주문 및 체결 등의 부하분산은 Producer Consumer 구조의 병렬처리로 해결한다. 이때 사이 통신의 매개체는 MQ로 구성되어 있으며 고성능을 위해 직접 구현 커스터마이징 되어있다. 문제는 모니터링이 힘들다는 것과. 그리고 결합도가 높다는 점이다.

결합도를 낮추고 응집도를 높여라 (lower coupling and higher cohesion.)

Ex)

graph LR FEP1 --> Queue[[Queue 1500개]] --> 처리프로세스N FEP2 --> Queue 처리프로세스N --> Queue1[[Queue 300개]] --> 매체통보 주문프로세스 --> Queue1 매체_HTS --> Queue2[[Queue 500개]] --> 주문프로세스

MQ 쓰는 쪽과 읽어가는 쪽이 같이 구성되어야 full나지 않고 잘 굴러가는데 조작 실수 혹은 로직의 이슈로 느려지면서 쓰는쪽이 많아지는 경우 Full의 위험성이 있다.

  • 모니터링: 어디의 MQ가 얼마나 원활하게 처리되는지 알기가 힘들다. 별개 모니터링 툴이 존재하여야 함.
  • 결합도 : MQ를 읽어가는 쪽이 마비되면 쓰는 쪽도 즉각 영향을 받는다.

(결합도의 경우 MQ 인터페이스가 blocking이면 더욱 심각하다. timeout으로 회피하는 경우도 있으나. 어느 정도 수준으로 timeout 판단할지 어렵다.)

결합도를 낮추고 응집도를 높이는 것 소프트웨어 설계 기본정신이다. MQ는 결합도가 올라가 문제가 생긴다.

사실 MQ를 가장 잘 다루는 것은 서비스엔진이다. 전문가에 맡기는 형태로 변경하는 것이 낫다. 서비스엔진이 Async 및 응답무시 기능이 있다면 완벽하게 queue와 같다고 볼수 있다.

1.2. 야금야금 부분적용

1차

graph LR FEP1 --> |call| 처리서비스([처리서비스]) FEP2 --> |call| 처리서비스([처리서비스]) 처리서비스 --> Queue1[[Queue 300개]] --> 매체통보 주문프로세스 --> Queue1 매체_HTS --> Queue2[[Queue 500개]] --> 주문프로세스

Queue와 그걸 읽어서 처리하는 부분 한 쌍은 사실 엔진의 서비스하나랑 동등하다. 이러한 패턴을 찾은 뒤에 Strangler Fig 방법론 처럼 일부분 적용

2차

graph LR FEP1 --> |call| 처리서비스([처리서비스]) FEP2 --> |call| 처리서비스([처리서비스]) 처리서비스 --> Queue1[[Queue 300개]] --> 매체통보 주문서비스 --> Queue1 매체_HTS --> |call| 주문서비스([주문서비스])

3차

graph LR FEP1 --> |call| 처리서비스([처리서비스]) FEP2 --> |call| 처리서비스([처리서비스]) 처리서비스 --> |call|매체통보서비스([매체통보서비스]) 주문서비스 --> |call|매체통보서비스([매체통보서비스]) 매체_HTS --> |call| 주문서비스([주문서비스])

야금야금 적용되어 전체가 바뀐다.

불안하고 항상 모니터링이 힘들었던 MQ는 이제 걷어낸다. 그러면 “서비스는 요청-응답 으로 기다리는데 Queue보다 훨씬 느린거 아닌가요?” 할수 있지만 Async 서비스로 요청하면 되며 특히 응답을 의도적으로 무시하는 기능과 자체 에러복구하는 로직까지 (모든 증권사에 구현되어 있다.) 있으면 완전히 MQ는 없어지며 서비스 모니터링에 노출되어 즉각 통계치부터 시작하여 운영자의 인지가 빨라진다. 그리고 동적으로 서비스의 수준을 변경하여 대응을 할수있다는 장점이 생긴다.

1.3. 서비스의 연쇄적 호출

서비스화 되면 생기는 장점은 서비스가 연속적으로 호출되어 어떤 한 고객을 중심으로 발생한 모든 이벤트를 추적하기 쉽다는 점이다.

TXT
1. 주문
2. SOR 처리
3. MTS에 통보
4. KRX에서 수신
5. NXT에서 수신
6. NXT에서 체결발생
7. MTS에 통보

2. MSA와는 무엇이 다른가?

공유데이터베이스를 이용한 트랜잭션이 대표적이다. 이는 전통적인 금융권 시스템으로 워낙 많은 비즈니스가 녹아있어서 이를 분리하는것도 쉽지 않으며 굳이? 분리를 해야하나 싶은 것이다. 모놀리딕으로도 회사 역사상 최대 이벤트도 버텼는데 금융에서 가장 중요한 정합성에 대한 위험을 키울 필요는 없을 것이다.

🤖 Gemini:

사용자님의 아키텍처는 **“서비스 지향적으로 진화한 모듈형 시스템”**이라고 볼 수 있습니다.

  • MSA인가? 절반의 성공입니다. 서비스의 분리와 비동기 통신은 MSA답지만, 데이터베이스 레벨에서의 강한 결합(트랜잭션)은 MSA의 완전한 독립성과는 거리가 있습니다.
  • 나쁜 것인가? 전혀 아닙니다. 오히려 모든 것을 처음부터 MSA로 만들려다 데이터 정합성이 깨져 고생하는 것보다 훨씬 현명한 **‘현실 타협안’**입니다.

💡 한 줄 요약: “기술적 구현(Async, 비동기 복구)은 MSA를 닮았고, 데이터 관리(Shared DB Transaction)는 모놀리스의 안정성을 택한 실무 최적화형 하이브리드 구조입니다.”


다음 단계로 고민해보실 점: 만약 나중에 이 ‘핵심 로직’마저 쪼개야 하는 상황이 온다면, 그때는 DB 트랜잭션 대신 **‘보상 트랜잭션(Compensating Transaction)’**이나 **‘Saga 패턴’**을 공부해보시는 것이 좋습니다.

현재 이 구조에서 배포할 때, 핵심 로직(DB)과 외부 서비스들 간에 배포 순서나 의존성 때문에 고생하신 적은 없으신가요? 이 부분에 대해 말씀해주시면 배포 전략에 대해서도 이야기를 나눠볼 수 있을 것 같습니다.

3. 스트랭글러 피그는 계속 진행된다

현재는 공유DB트랜잭션을 기반으로 한 레거시의 거대한 서비스 2개 그리고 작게 쪼개져서 외부와의 연결을 담당하는 작은서비스 여러개가 혼용되어 있지만 거대한 서비스는 점차 작아질 것이다. 이미 몇부분이 분리되었으며 계속 작은서비스로 분화될 것이다.