logo
Search

    #Spring-Cloud-Stream(v.4.1.3) 1. A Brief History of Spring’s Data Integration Journey

    원본 : https://docs.spring.io/spring-cloud-stream/reference/preface.html
    MYSQLRDMS
    #방장봇 · # 2024/12/2
    19 0 0 0
    좋아요
    별로
    1 번 수정된 문서입니다.
    #editor: 방장봇# 수정됨: 1
    13 0 0 0

    Spring의 데이터 통합 여정: 간략한 역사

    Spring의 데이터 통합 여정은 Spring Integration에서 시작되었습니다. 이 프로그래밍 모델은 데이터베이스, 메시지 브로커 등 외부 시스템과 연결할 수 있는 Enterprise Integration Patterns을 수용하는 애플리케이션을 구축하기 위한 일관된 개발자 경험을 제공했습니다.

    클라우드 시대에 접어들면서 마이크로서비스가 기업 환경에서 두드러지게 부각되었습니다. Spring Boot는 개발자들이 애플리케이션을 구축하는 방식을 혁신적으로 변화시켰습니다. Spring의 프로그래밍 모델과 Spring Boot가 처리하는 런타임 책임 덕분에 독립형, 프로덕션 등급의 Spring 기반 마이크로서비스를 개발하는 것이 수월해졌습니다.

    이를 데이터 통합 작업에 확장하기 위해 Spring Integration과 Spring Boot가 새로운 프로젝트로 통합되었습니다. Spring Cloud Stream이 등장했습니다.

    Spring Cloud Stream을 사용하면 개발자는 다음과 같은 작업을 수행할 수 있습니다:

    • 데이터 중심 애플리케이션을 독립적으로 구축, 테스트 및 배포합니다.
    • 메시징을 통한 조합을 포함한 현대적인 마이크로서비스 아키텍처 패턴을 구현합니다.
    • 이벤트 중심 사고를 통해 애플리케이션의 책임을 분리할 수 있습니다. 이벤트는 특정 시점에 발생한 어떤 것을 나타낼 수 있으며, 하류 소비자 애플리케이션은 그것이 어디에서 유래했는지 또는 생산자의 정체성을 알지 못한 채 반응할 수 있습니다.
    • 비즈니스 로직을 메시지 브로커(예: RabbitMQ, Apache Kafka, Amazon Kinesis)로 이전합니다.
    • 일반적인 사용 사례에 대한 프레임워크의 자동 콘텐츠 유형 지원을 활용합니다. 다양한 데이터 변환 유형으로 확장이 가능합니다.
    • 그리고 더 많은 것들...

    빠른 시작

    자세한 내용을 살펴보기 전에 이 3단계 가이드를 따라 5분도 안 되어 Spring Cloud Stream을 시도해볼 수 있습니다. 우리는 여러분에게 선택한 메시징 미들웨어에서 오는 메시지를 수신하고, 수신된 메시지를 콘솔에 기록하는 Spring Cloud Stream 애플리케이션을 만드는 방법을 안내합니다. 우리는 이를 LoggingConsumer라고 명명합니다. 실용적이지는 않지만, 주요 개념과 추상화에 대한 좋은 소개를 제공하여 이 사용자 가이드의 나머지를 이해하는 데 도움이 될 것입니다.

    세 단계는 다음과 같습니다.

    1. Spring Initializr를 사용하여 샘플 애플리케이션 만들기
    2. 프로젝트를 IDE에 가져오기
    3. 메시지 핸들러 추가, 빌드 및 실행

    Creating a Sample Application Using Spring Initializr

    시작하려면 다음 단계를 따르세요: Spring Initializr로 이동합니다. 거기에서 Logging Consumer 애플리케이션을 생성할 수 있습니다. 그렇게 하려면:

    • Dependencies 섹션에서 'stream'을 입력하기 시작합니다. “Spring Cloud Stream” 옵션이 나타나면 선택합니다.
    • 'kafka' 또는 'rabbitmq'를 입력하기 시작합니다.
    • “Kafka” 또는 “RabbitMQ”를 선택합니다.

    기본적으로, 애플리케이션이 바인딩할 메시징 미들웨어를 선택하는 것입니다. 이미 설치했거나 설치 및 실행하는 데 더 편리한 미들웨어를 사용하는 것을 권장합니다. 또한, Initializer 화면에서 선택할 수 있는 몇 가지 다른 옵션이 존재합니다. 예를 들어, 기본값인 Maven 대신 Gradle을 빌드 도구로 선택할 수 있습니다.

    Artifact 필드에 'logging-consumer'를 입력하세요.

    Artifact 필드의 값은 애플리케이션의 이름이 됩니다. 미들웨어로 RabbitMQ를 선택했다면, Spring Initializr는 이제 다음과 같아야 합니다:

    Generate Project 버튼을 클릭하세요.
    이렇게 하면 생성된 프로젝트의 압축 파일이 하드 드라이브에 다운로드됩니다.

    원하는 프로젝트 디렉토리로 사용할 폴더에 파일의 압축을 푸세요.

    Spring Initializr에서 제공하는 다양한 가능성을 탐색해 보세요. 이를 통해 다양한 종류의 Spring 애플리케이션을 생성할 수 있습니다.

    프로젝트를 IDE에 임포트하기

    이제 프로젝트를 IDE에 임포트할 수 있습니다. IDE에 따라 특정 임포트 절차를 따라야 할 수 있음을 유의하십시오. 예를 들어, 프로젝트가 어떻게 생성되었는지(예: Maven 또는 Gradle)에 따라 특정 임포트 절차를 따라야 할 수 있습니다(예: Eclipse 또는 Spring Tool Suite(STS)에서는 File → Import → Maven → Existing Maven Project를 사용해야 합니다).

    임포트한 후에는 프로젝트에 어떤 종류의 오류도 없어야 합니다. 또한, src/main/java에는 com.example.loggingconsumer.LoggingConsumerApplication이 포함되어야 합니다.

    기술적으로, 이 시점에서 애플리케이션의 메인 클래스를 실행할 수 있습니다. 이미 유효한 스프링 부트 애플리케이션입니다. 그러나 아무 작업도 수행하지 않으므로 코드를 추가해야 합니다.

    메시지 핸들러 추가, Build and Run

    com.example.loggingconsumer.LoggingConsumerApplication 클래스를 다음과 같이 수정합니다:

    @SpringBootApplication 
    public class LoggingConsumerApplication { 
        public static void main(String[] args) { 
            SpringApplication.run(LoggingConsumerApplication.class, args); 
        } 
        @Bean 
        public Consumer<Person> log() { 
            return person -> { 
                System.out.println("Received: " + person); 
            }; 
        } 
        public static class Person { 
            private String name; 
            public String getName() { 
                return name; 
            } 
            public void setName(String name) { 
                this.name = name; 
            } 
            public String toString() { 
                return this.name; 
            } 
        } 
    }
    

    앞서 나열된 내용을 보면: We define a single message handler as a Consumer using a functional programming model.
    우리는 relying on framework rules에 의존하여 해당 핸들러를 바인더에 의해 노출된 입력 목적지 바인딩에 바인딩합니다.

    이렇게 하면 프레임워크의 핵심 기능 중 하나를 볼 수 있습니다: 들어오는 메시지 페이로드를 자동으로 Person 타입으로 변환하려고 시도합니다.

    이제 메시지를 수신하는 완전한 기능의 Spring Cloud Stream application이 준비되었습니다. 여기서 간단함을 위해 1단계에서 RabbitMQ를 선택했다고 가정합니다. Assuming RabbitMQ is installed and running, IDE에서 메인 메서드를 실행하여 애플리케이션을 시작할 수 있습니다.

    다음과 같은 출력을 볼 수 있어야 합니다:

    --
    - [ main] c.s.b.r.p.RabbitExchangeQueueProvisioner : declaring queue for inbound: input.anonymous.CbMIwdkJSBO1ZoPDOtHtCg, bound to: input 
    --
    - [ main] o.s.a.r.c.CachingConnectionFactory : Attempting to connect to: [localhost:5672] 
    --
    - [ main] o.s.a.r.c.CachingConnectionFactory : Created new connection: rabbitConnectionFactory#2a3a299:0/SimpleConnection@66c83fc8. . . . . . 
    --
    - [ main] o.s.i.a.i.AmqpInboundChannelAdapter : started inbound.input.anonymous.CbMIwdkJSBO1ZoPDOtHtCg . . . 
    --
    - [ main] c.e.l.LoggingConsumerApplication : Started LoggingConsumerApplication in 2.531 seconds (JVM running for 2.897)
    

    RabbitMQ 관리 콘솔이나 다른 RabbitMQ 클라이언트로 이동하여 input.anonymous.CbMIwdkJSBO1ZoPDOtHtCg에 메시지를 전송하세요. anonymous.CbMIwdkJSBO1ZoPDOtHtCg 부분은 그룹 이름을 나타내며 생성되므로 귀하의 환경에서 다를 수 있습니다. 더 예측 가능한 것을 원하신다면 spring.cloud.stream.bindings.input.group=hello (또는 원하는 이름)으로 설정하여 명시적인 그룹 이름을 사용할 수 있습니다.

    메시지의 내용은 다음과 같이 Person 클래스의 JSON 표현이어야 합니다: 그럼, 콘솔에서 다음과 같은 내용을 볼 수 있어야 합니다:

    Received: Sam Spade
    

    애플리케이션을 boot jar로 빌드하고 패키징할 수도 있습니다 ( ./mvnw clean install 사용) 그리고 빌드된 JAR를 java -jar 명령어로 실행할 수 있습니다.

    이제 작동하는 (비록 매우 기본적인) Spring Cloud Stream application이 있습니다.

    Streaming 데이터의 맥락에서의 Spring Expression Language (SpEL)

    Throughout this reference manual, Spring Expression Language (SpEL)를 활용할 수 있는 많은 기능과 예제를 접하게 될 것입니다. 이를 사용할 때 It is important to understand certain limitations을 이해하는 것이 중요합니다. SpEL은 현재 Message와 실행 중인 Application Context에 접근할 수 있게 해줍니다. 그러나 SpEL이 어떤 종류의 데이터를 볼 수 있는지, 특히 수신되는 Message의 맥락에서 이해하는 것이 중요합니다.

    브로커에서 메시지는 byte[] 형태로 도착합니다. 그런 다음 바인더에 의해 Message<byte[]>로 변환되며, 이때 메시지의 페이로드는 원래 형태를 유지합니다. 메시지의 헤더는 <String, Object> 형태이며, 값은 일반적으로 다른 원시 타입이나 원시 타입의 컬렉션/배열이기 때문에 Object입니다. This is because the binder does not have access to user code (functions) and therefore does not know the required input type.

    따라서 바인더는 페이로드와 메시지 헤더 형태의 읽을 수 있는 메타데이터가 포함된 봉투를 전달한 것입니다. 이는 우편으로 배달된 편지와 같습니다. 즉, 메시지의 페이로드에 접근하는 것은 가능하지만, 원시 데이터(즉, byte[])로만 접근할 수 있습니다.

    개발자들이 페이로드 객체의 필드에 SpEL을 통해 구체적인 타입(예: Foo, Bar 등)으로 접근할 수 있는 기능을 요청하는 것이 매우 일반적일 수 있지만, 이를 달성하는 것이 얼마나 어려운지 또는 불가능한지를 알 수 있습니다.

    문제를 설명하기 위한 한 가지 예를 들어보겠습니다: 페이로드 타입에 따라 다른 함수로 라우팅하기 위한 라우팅 표현식이 있다고 가정해 보십시오. 이 요구 사항은 byte[]에서 특정 타입으로의 페이로드 변환을 의미하며, 그 후 SpEL을 적용해야 합니다. 그러나 이러한 변환을 수행하기 위해서는 변환기에 전달할 실제 타입을 알아야 하며, 이는 함수의 시그니처에서 나오는 정보인데, 우리는 어떤 것인지 알 수 없습니다.

    이 요구 사항을 해결하기 위한 더 나은 접근 방식은 타입 정보를 메시지 헤더로 전달하는 것입니다(예: application/json;type=foo.bar.Baz). 이렇게 하면 읽을 수 있는 명확한 문자열 값을 얻을 수 있으며, 이를 SpEL 표현식에서 접근하고 평가하기가 쉽습니다. 추가적으로, Using the payload for routing decisions is considered a very bad practice. payload는 특권 데이터로 간주되며, 최종 수신자만 읽을 수 있는 데이터이기 때문입니다. 다시 말해, 우편 배달 비유를 사용하자면, 우편 배달원이 당신의 봉투를 열고 편지 내용을 읽어 배달 결정을 내리는 것을 원하지 않을 것입니다. 이와 같은 개념이 여기에도 적용되며, 특히 Message를 생성할 때 이러한 정보를 포함하는 것이 상대적으로 쉽기 때문에 더욱 그렇습니다. 이는 네트워크를 통해 전송될 데이터의 설계와 어떤 데이터 조각이 공개될 수 있는지, 어떤 데이터가 특권으로 간주될 수 있는지에 대한 특정 수준의 규율을 강제합니다.

    spring-cloud-stream

    소개

    Comments
    새로운 댓글