1. Spring Integration 개요와 동작 방식
1-1. Spring Integration이란
1-2. 기본 동작 방식
2. 일반 Spring 대신 Spring Integration을 사용하는 이유
2-1. 일반 Spring과의 추상화 레벨 차이
2-2. 일괄된 외부 시스템과의 연결
3. Spring Integration이 적합한 상황과 주의점
3-1. 시스템 간 잦은 연동과 데이터 이동 과정이 복잡한 경우
3-2. 일반 Spring이 더 보편적인 이유
4. 주요 구성 요소
4-1. 주요 구성 요소
1. Spring Integration 개요
1-1. Spring Integration이란
실무에서는 외부 시스템으로부터 데이터를 받아 가공한 뒤 저장하거나 다른 곳으로 전달해야 하는 경우가 있다.
예를 들어 SFTP 서버에 구매 내역 파일이 생성되면 이를 가져와 한 줄씩 읽고 객체로 변환한 뒤 저장한다거나,
저장 후 알림 시스템에 해당 데이터를 가공해서 메시지를 던져야 할 수도 있다.
물론 이런 로직을 일반 Spring으로도 구현할 수 있지만 파일 확인, SFTP 연결, 데이터 변환, 분기, 재시도, 다음 시스템 호출 등
연동 흐름을 개발자가 직접 연결하고 제어해야 한다.
이런 연동 단계가 많아질수록 실제 처리 로직과 시스템 연결 코드가 섞이고 입력 방식이나 처리 순서가 바뀔 때 여러 코드를 함께 수정해야 한다.
Spring Interation은 이러한 시스템 간 데이터 연동 흐름을 정형화하여 구성하기 위한 프레임워크다.
비즈니스 로직 자체를 구현하기 위한 기술이라기보다, 여러 시스템 사이에서 데이터가 이동하고 처리되는 과정을 용이하게 관리하기 위한 기술이다. 이를 통해 비즈니스 로직과 연동 흐름을 분리해서 외부 시스템 종류가 바뀐다거나 순서가 변경될 때 수정 범위를 줄일 수 있다.
1-2. 기본 동작 방식
Spring Integration의 전체 흐름은 크게 세 단계로 볼 수 있다.
1. Adapter 또는 Gateway가 외부 시스템으로부터 데이터를 받아 Message로 만든다.2. Message가 Channel을 통해 이동하며 변환, 분리, 필터링 등의 처리를 거친다.3. Service Activator가 비즈니스 메서드를 호출하거나, 가공한 값을 바로 외부 시스템으로 전달한다.
간략한 흐름 예시
외부 시스템이 HTTP로 호출 -> adapter/Gateway -> Channel -> 데이터 처리 -> Channel -> 비즈니스 로직 or 외부 시스템
2. 일반 Spring 대신 Spring Integration을 사용하는 이유
2-1. 일반 Spring과의 추상화 레벨 차이
나는 Spring Integration을 처음 보고 이런 의문이 들었다.
일반 Spring에서도 인터페이스를 만들고 구현체를 의존 주입하면 파일 처리 구현체를 Kafka 처리 구현체로 교체할 수 있지 않나
외부 시스템이 연동에 대해 충분히 유연하게 처리 가능한데?
근데 핵심은 구현체가 아닌 흐름 자체(호출 순서)를 별도의 구성 요소로 관리할 수 있다는 거였다.
즉 일반 Spring은 bean과 DI를 활용해 객체 수준의 추상화를 제공한다면 integration은 그에 더해 그 객체의 흐름 자체를 추상화하여 외부에서 조립할 수 있게 해 준다.
예를 들어
일반 Spring에서 A 서비스가 B 서비스를 사용한다면 구현체를 인터페이스로 분리하더라도 A는 결국 B의 메서드를 호출해야 한다.
public class OrderProcessor {
private final OrderSender orderSender;
public void process(OrderDto order) {
validate(order);
orderSender.send(order);
}
}
OrderSender의 구현체는 바꿀 수 있지만 validate() 이후 send()를 호출한다는 흐름은 자바 코드 안에 남아 있다.
실제 요구사항이 아래처럼 복잡해지면 흐름을 제어하는 코드도 함께 늘어난다.
- 주문 데이터를 검증한다.
- VIP와 일반 고객을 서로 다른 처리기로 보낸다.
- 실패하면 재시도한다.
- 계속 실패하면 별도의 에러 저장소로 보낸다.
- 처리 결과를 다시 합쳐 후속 작업을 실행한다.
일반 Spring으로도 모두 구현할 수 있지만 누군가는 if, try-catch, 반복문, 비동기 실행 코드 등을 작성하여 전체 순서를 통제해야 한다.
Spring Integration은 이러한 흐름을 Router, Filter, Retry Advice, Error Channel 같은 이미 구현된 패턴으로 구성할 수 있게 해 준다.
2-2. 일괄된 외부 시스템과의 연결
다른 외부 시스템에서 우리 시스템을 호출할 경우 항상 Rest API 형식으로 호출할 수 있는 건 아니다.(보안정책상 http 호출금지 등)
그럴 경우 Spring에서 직접 구현한다면 각 기술에 맞는 클라이언트 코드와 예외 처리 방식이 곳곳에 생길 수 있다.
Spring integration은 이런 외부 시스템의 차이를 Adapter가 담당하고 내부에서는 공통적으로 Message, Channel을 사용한다.
예를 들어 외부 시스템이 주문 데이터를 우리 시스템에 넘겨주는 방식이 기존 REST API 호출 방식에서 Kafka로 바뀐다면
입력 Adapter와 메시지 변환 부분을 교체하고 이후 기존 DTO로 처리 흐름을 그대로 사용할 수 있다.
3. Spring Integration이 적합한 상황과 주의점
3-1. 시스템 간 연동과 데이터 이동 과정이 복잡한 경우
Spring Integration은 도메인 자체가 복잡할 때 사용하는 프레임워크가 아닌 잦은 시스템 간 연동과 데이터 이동 과정이 복합할 때 유리하다.
비즈니스 규칙이 복잡하더라도 대부분이 사용자의 요청을 받아 DB 상태를 변경하고 결과를 반환하는 구조라면 일반적인 Spring 프레임워크 구조가 더 적합하다.
3-2. 일반 Spring이 더 보편적인 이유
개발에 있어 모든 것이 그렇듯 결국 트레이드오프지만 Integration 보다 일반 Spring 프레임워크가 더 보편적인 이유를 나름 생각해 봤다.
1. 대부분의 웹 애플리케이션이 메시지 파이프라인보다 요청과 응답 그리고 DB 상태 변경을 중심으로 동작하기 때문
단순한 회원 등록 기능을 아래처럼 구현할 수 있는데
Controller → MemberService → MemberRepository
이를 굳이 여러 Message와 Channel로 나누면 코드 실행 경로를 파악하기 어려워지고 설정만 늘어날 수 있다.
내가 해당 프레임워크를 CRM 회사로 이직한 후 처음 접한 이유가 이것이라고 생각한다.
기존 진행했던 프로젝트에선 대부분 해당 시스템 안에서 데이터가 움직이며 ERP, 트래킹 시스템 등 연동 시스템이 많지 않았다.
특히 외부 시스템에서 우리 시스템으로 들어오는 상황은 거의 전무했다.
그런데 CRM 특성상 결제를 하는 Pos기기 서버, 이커머스, ERP, 알림 시스템 등 정말 많은 외부 시스템과 연동된다.
이러한 이유로 적합한 프레임워크가 아닐 수 없다.
2. 흐름 추적과 디버깅이 어려워질 수 있다.
비동기 채널이 여러 개 연결되면 하나의 메서드 호출 스택만 보고 전체 실행 과정을 파악하기 어렵다.
사실 비동기 처리 로직이 아니어도 메서드 호출을 객체 간 직접 하는 게 아니기 때문에 흐름 추적과 디버깅이 매우 불편하다.
(이 때문에 처음 봤을 때 매우 짜증 나고 일반적인 계층 구조가 그리웠다..)
4. 주요 구성 요소
4-1. 주요 구성 요소
Message
파이프라인을 통해 전달되는 데이터. 실제 데이터인 payload와 파일명, 생성 시간 등의 부가 정보인 header로 구성된다.
Channel
Message가 이동하는 내부 통로. 채널 종류에 따라 같은 스레드에서 다음 단계를 실행하거나 별도 스레드 또는 큐를 통해 처리할 수 있다.
input-channel과 output-channel
- input-channel: 컴포넌트가 Message를 전달받는 통로
- output-channel: 컴포넌트가 처리 결과를 다음 단계로 보내는 통로
Inbound Gateway와 Outbound Gateway
- Inbound Gateway: 외부 요청을 받아 내부 흐름을 시작하고 처리 결과를 외부에 응답
- Outbound Gateway: 내부 Message로 외부 시스템을 호출하고 그 응답을 다시 내부 흐름으로 전달
외부 요청 -> Inbound Gateway -> 내부 처리 → 외부 응답
내부 Message -> Outbound Gateway -> 외부 시스템 → 응답 Message 수신
Channel Adapter
- Inbound Channel Adapter: 파일, FTP, Kafka 등 외부 데이터를 받아 Channel로 전달
- Outbound Channel Adapter: Channel의 Message를 외부 시스템으로 전송
Transformer
Message의 형태를 변환한다. 예를 들어 CSV 문자열을 OrderDto로 바꾼다.
Splitter와 Aggregator
Splitter는 하나의 Message를 여러 개로 나누며 Aggregator는 여러 Message를 하나로 합친다.
Router와 Filter
Router는 조건에 따라 Message를 서로 다른 Channel로 보내고, Filter는 조건에 맞지 않는 Message를 흐름에서 제외한다.
Service Activator
Channel에서 Message를 받아 일반 자바 객체의 메서드를 호출한다. 메시지 흐름과 실제 비즈니스 로직을 연결하는 역할이다.
'Spring' 카테고리의 다른 글
| Spring @TransactionalEventListener AFTER_COMMIT 주의점 (0) | 2026.02.13 |
|---|---|
| Spring 의존 주입 에러 상황 (0) | 2026.01.29 |
| Spring REST API @Valid (0) | 2024.03.06 |
| Spring 비지니스 로직 위치 (0) | 2024.02.25 |
| Springboot ftp 파일 업로드/다운로드 (0) | 2023.08.25 |