HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤩
개발
/
Spring Projects
Spring Projects
/
Spring Integration
Spring Integration
Spring Integration

Spring Integration

Spring Integration은 잘 알려진 Enterprise Integration Pattern을 지원하기 위해서 Spring 의 프로그래밍 모델을 messaging domain 까지 확장한 것
Enterprise Integration Pattern
  • Patterns and Best Practices for Asynchronous Messaging
  • Messaging Patterns in Today's World: Microservices and Serverless
  • 비지니스 로직이 언제 실행되어야 하는지, 응답이 어디로 보내져야 하는지와 같은 내용들에 대해 Inversion of Control이 적용되면서 메시지 주도 아키텍처를 지원
  • 메시지의 라우팅과 변환을 지원함 → different transport 와 서로 다른 데이터 형식이 테스트 용이성을 떨어뜨리지 않으면서 통합 가능함. 즉, 메시징과 통합에 대한 관심사를 프레임워크가 관리해줌
  • 비지니스 컴포넌트들은 인프라에서부터 독립되어서 개발자들은 복잡한 통합과 관련된 작업을 할 필요가 없어지게 됨
  • Spring Integration의 주요 목적은 지속가능하고 테스트 가능한 코드의 핵심인 관심사 분리를 유지하면서 Enterprise integration solution을 구현하기 위한 간단한 모델을 제공하는 것임
  • Messaging 과 Integration concern이 Spring Integration Framework에 의해서 다루어짐. 그래서 개발자는 비지니스 로직 구현만 하면 되고 복잡한 integration 책임을 Spring Integration framework에게 넘길 수 있음

Goals and Principles

목표
  • 복잡한 Enterprise integration solution을 구현하기 위해 간단한 모델을 제공해줌
  • 스프링 기반의 어플리케이션에서 비동기, 메시지 주도 작업을 용이하게 해줌
  • 기존의 스프링 유저에게 직관적이고 점진적인 도입을 촉진시켜줌
원칙
  • 컴포넌트들은 서로 유연하게 결합되어 있어 modularity와 testability를 저해하지 않아야 함
  • 프레임워크는 비지니스 로직과 통합 로직 사이의 관심사 분리를 철저하게 해야 함
  • 재사용성과 이식성을 향상시키기 위해 확장 포인트는 본질적으로 추상적이어야 함(그러나 잘 정의된 경계 안에서)

Main Components

  • 수직적 관점에서, 계층적 아키텍처는 관심사 분리를 촉진시키고, 계층 사이에서 인터페이스 기반의 계약으로 인해 느슨한 결합을 증진 시켜줌 ⇒ 스프링 기반의 어플리케이션은 전통적으로 이러한 방식으로 디자인 됨
  • 메시지 주도 아키텍처는 동일한 목표를 유지하면서 수평적 관점을 추가시켜 줌
  • 계층적 아키텍처가 극단적으로 generic하고 abstract한 패러다임인 것과 같이 메시징 시스템은 비슷한 추상화인 “pipes-and-filters” 모델을 따름
    • filters : 메시지를 생산하고 소비할 수 있는 임의의 컴포넌트
    • pipes : 메시지를 필터 사이에서 운송하는 역할을 함. 그리하여 컴포넌트 그 자체는 느슨한 결합(loosely-coupled)을 유지할 수 있게 해줌
    • 이 두개의 고수준의 패러다임은 상호 배타적이지 않음
    • pipe를 지원하는 기반 메시징 인프라는 레이어 안에 캡슐화되어 있어야 함. 그리고 각각의 레이어는 interface로 서로 계약을 함
    • 마찬가지로 filters는 논리적으로 어플리케이션의 서비스 레이어보다 위에 있는 레이어 안에서 관리되어야 함 → 그리하여 서비스 레이어와 interface를 통하여 상호작용을 하게 됨

Message

Java object와 프레임워크에 의해 사용되는 meta data를 포함하는 wrapper라고 생각하면 됨
  • payload와 header로 구성되어 있음
  • payload는 어떠한 타입도 가능하고, header는 ID, timestamp, correlation ID, return address와 같은 일반적으로 필요한 정보들을 갖고 있음
  • 예를 들어 전달되어 온 파일로 부터 메시지를 만들 때, 파일의 이름은 다운스트림에서 사용될 수도 있기 때문에 헤더에 포함되어야 할 수 있음
  • 마찬가지로, 메시지의 내용은 외부의 메일 아답터로부터 전송될 수 있고, 여러 다양한 프로퍼티들(to, from, cc, subject, and others)이 upstream component에서 메시지 헤더 값으로 구성될 수 있음

Message Channel (pipe)

notion image
  • 메시지 채널은 pipes-and-filters 아키텍쳐에서 pipe에 해당하는 컴포넌트임
  • Producer는 메시지를 채널에 보내고 Consumer는 메시지를 채널에서 받음 ⇒ 메시지 채널이 메시징 컴포넌트들을 decouple 시키고 message의 intercept, monitoring을 할 수 있음
  • 메시지 채널은 point-to-point(consumer가 1명)일 수도, publich-subscribe(broadcast 방식. consumer가 여러 명) 일수도 있음
  • Spring Integration에서 pollable channel은 Message의 버퍼링을 큐 안에서 진행할 수 있음
    • 버퍼링의 장점은 인바운드 메시지의 스로틀링을 가능케 하여 consumer의 오버로딩을 방지할 수 있다는 점임(하나의 큐로만 작업들을 받게 되기 때문에 감당 불가능한 만큼의 작업이 들어오는 것을 방지할 수 있음)
    • 그러나 이름에서 알 수 있듯이, 이는 복잡성을 더하게 됨. 왜냐하면 consumer가 poller가 구성된 채널에서만 메시지를 받을 수 있기 때문임.
    • 반면, subscribable channel에 연결된 consumer는 단순한 메시지 주도 방식임

Message Endpoint ( filter )

  • Spring Integration을 사용하는 이유는 IoC를 위함이고, 그럼으로써 producer와 consumer를 직접 구현할 필요가 없어지는 것임. 그리고 message의 빌드와 message channel에 전송, 수령하는 operation도 굳이 할 필요 없음
  • 대신 domain object에 집중하여 로직을 구성한 후 configuration을 통해서 messaging infrastructure에 연결하는 데 이 연결을 담당하는 컴포넌트가 message endpoint임
    • 이 말이, 직접 어플리케이션 코드를 작성해서 연결을 해야 한다는 것은 아님. 실제적으로 쓰이는 어떠한 enterprise integration solution도 통합을 위한 명시적인 코드(routing & transformation)들을 필요로 함
    • 어플리케이션 코드는 메시지 오브젝트와 메시지 채널에 대해 전혀 몰라야 함. (MVC 패러다임과 비슷함. Controller가 http rqeuet를 핸들하는 것을 전혀 신경 안 쓰듯이)
  • pipes-and-filters 아키텍처에서 filter의 역할을 함
  • controller가 HTTP request를 url pattern으로 매칭하여 받듯이, message endpoint는 message channel에 매핑됨

Message Endpoints

Message Transformer

  • 메시지의 내용과 구조를 변환하고 변경된 메시지를 반환하는 역할을 담당함

Message Filter

  • 메시지가 아웃풋 채널로 전달되어야 하는지 말아야 하는지를 결정함. 이를 위해 간단한 boolean test method가 필요
  • 메시지가 accepted되면 아웃풋 채널로 보내지게 됨. 그렇지 않으면 버려지게 됨(또는 더 엄격한 구현에서는 예외를 던질 수도 있음)
  • 메시지 필터는 pub-sub channel과 함게 주로 자주 사용됨 (예로, 다수의 consumer가 같은 메시지를 받았을 때, 필터를 이용하여 처리할 메시지의 집합을 걸러낼 수 있음)
💡
pipe-and-filter 아키텍처 패턴에서의 filter와 이 필터를 헷갈리지 말기. pipe-and-filter 개념에서의 filter는 Spring Integration에서 Message endpoint 의 개념에 더 가까움

Message Router

notion image
  • 어떤 채널에서 해당 메시지를 받아야 할지를 결정하는 역할을 담당함
  • 보통, 해당 결정은 메시지의 content나 header를 기반으로 내려지게 됨

Splitter

  • message를 인풋채널에서 받아서 해당 메시지를 다수의 메시지로 분리하여 각각을 해당하는 아웃풋 채널로 보내는 역할
  • 이 컴포넌트는 주로 복합적인 payload object를 여러개의 메시지 그룹으로 나누어서 전송할 때 쓰이게 됨

Aggregator

  • Splitter의 반대 역할로 다수의 메시지를 받아서 하나의 메시지로 합치는 역할을 수행함

Service Activator

notion image
  • 서비스 인스턴스를 메시징 시스템에 연결하는 generic endpoint임
  • 인풋 메시지 채널이 꼭 구성되어야 하고, 호출되는 서비스 메서드가 반환값이 있다면 아웃풋 메시지 채널 또한도 제공되어야 함
  • Service activator는 요청 메시지를 처리하기 위해 서비스 오브젝트의 연산을 호출하게 되고 요청 메시지의 본문을 빼내어 변환하는 과정을 진행함
    • 서비스 오브젝트의 메서드가 값을 반환한다면 해당 값은 필요하다면 응답 메시지로 변환 되어야 함(그것이 이미 message type 이 아니라면)
    • 아웃풋 채널이 구성되어 있지 않다면 메시지에 명시되어 있는 return address로 응답이 보내지게 됨

Channel Adapter

  • 메시지 채널을 다른 시스템 혹은 transport로 연결짓는 엔드포인트임
  • 보통, 채널 아답터는 message 와 다른 어떠한 오브젝트 혹은 리소스(file, HTTP Request, JMS message, and others) 사이에서의 매핑을 수행함

Messaging Gateway

  • Spring Integration에 의해서 제공되는 메시징 api를 숨겨주는 역할을 함. 어플리케이션 비즈니스 로직 코드가 Spring Integration API를 모르도록 해줌. generic Gateway를 사용함으로써 사용자의 코드는 간단한 인터페이스로만 소통함
  • 즉, 하는 역할은 message를 보내주는 역할.
 

Configuration

  • @IntegrationComponentScan :  classpath scanning을 하지만 Spring Integration과 관련된 컴포넌트와 어노테이션만 스캔을 진행함. 일반 @ComponentScan 으로는 안되는 곳까지