Spring 통합 및 Google Cloud Pub/Sub를 사용한 메시징

Spring 통합은 MessageChannels를 통해 Messages를 교환하는 메시지 메커니즘을 제공합니다. 채널 어댑터를 사용하여 외부 시스템과 통신합니다.

이 연습에서는 Spring Cloud GCP에서 제공하는 Spring 통합 채널 어댑터를 사용하여 통신하는 두 가지 앱을 만들어 보겠습니다. 이러한 어댑터를 사용하면 Spring 통합에서 Google Cloud Pub/Sub를 메시지 교환 백엔드로 사용합니다.

Cloud Shell과 Cloud SDK gcloud 명령어를 사용하는 방법을 알아봅니다.

이 가이드에서는 Spring Boot 시작 가이드의 샘플 코드를 사용합니다.

학습할 내용

  • Spring Integration 및 Spring Cloud GCP를 사용하여 Google Cloud Pub/Sub로 앱 간에 메시지를 교환하는 방법

필요한 항목

  • Google Cloud Platform 프로젝트
  • 브라우저(예: Chrome 또는 Firefox)
  • Vim, EMAC, Nano와 같은 표준 Linux 텍스트 편집기에 대한 지식

본 튜토리얼을 어떻게 사용하실 계획인가요?

읽기만 할 계획입니다 읽은 다음 연습 활동을 완료할 계획입니다

HTML/CSS 웹 앱 빌드 관련 사전지식 수준을 평가해 주세요.

초급 중급 고급

귀하의 Google Cloud Platform 서비스 사용 경험을 평가해 주세요.

초급 중급 고급

자습형 환경 설정

Google 계정 (Gmail 또는 Google 앱)이 아직 없다면 계정을 만들어야 합니다. Google Cloud Platform Console (console.cloud.google.com)에 로그인하여 새 프로젝트를 만듭니다.

2016-02-10 12:45:26.png 스크린샷

모든 Google Cloud 프로젝트에서 고유한 이름인 프로젝트 ID를 기억하세요(위의 이름은 이미 사용되었으므로 사용할 수 없습니다). 이 ID는 나중에 이 Codelab에서 PROJECT_ID라고 부릅니다.

다음으로 Google Cloud 리소스를 사용하려면 Cloud Console에서 결제를 사용 설정해야 합니다.

이 codelab을 실행하는 과정에는 많은 비용이 들지 않지만 더 많은 리소스를 사용하려고 하거나 실행 중일 경우 비용이 더 들 수 있습니다(이 문서 마지막의 '삭제' 섹션 참조).

Google Cloud Platform의 신규 사용자는 $300 무료 체험판을 사용할 수 있습니다.

Google Cloud Shell

노트북에서 원격으로 작동할 수 있는 상태지만, 이 Codelab에서는 Cloud에서 실행되는 명령줄 환경인 Google Cloud Shell을 사용할 것입니다.

Google Cloud Shell 활성화

GCP 콘솔에서 오른쪽 상단 툴바의 Cloud Shell 아이콘을 클릭합니다.

그런 다음 'Cloud Shell 시작'을 클릭합니다.

환경을 프로비저닝하고 연결하는 데 몇 분 정도 소요됩니다.

가상 머신은 필요한 모든 개발 도구와 함께 로드됩니다. 영구적인 5GB 홈 디렉토리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 실습에서 대부분의 작업은 브라우저나 Google Chromebook만을 이용하여 수행할 수 있습니다.

Cloud Shell에 연결되면 인증이 이미 완료되어 있고 프로젝트가 이미 PROJECT_ID로 설정되어 있음을 확인할 수 있습니다.

Cloud Shell에서 다음 명령어를 실행하여 인증되었는지 확인합니다.

gcloud auth list

명령어 결과

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

명령어 결과

[core]
project = <PROJECT_ID>

또는 다음 명령어로 설정할 수 있습니다.

gcloud config set project <PROJECT_ID>

명령어 결과

Updated property [core/project].

Google Cloud Pub/Sub 주제 페이지로 이동하여 API를 사용 설정합니다.

주제 만들기를 클릭합니다.

주제 이름으로 exampleTopic를 입력하고 만들기를 클릭합니다.

주제가 생성되면 주제 페이지에 남아 있습니다. 방금 만든 주제를 찾은 다음 줄 끝의 점 3개를 누르고 새 구독을 클릭합니다.

구독 이름 텍스트 상자에 exampleSubscription을 입력하고 만들기를 클릭합니다.

Cloud Shell이 출시된 후에는 명령줄을 사용하여 Spring Initializr로 두 개의 새 Spring Boot 애플리케이션을 생성할 수 있습니다.

$ curl https://start.spring.io/starter.tgz \
  -d bootVersion=2.0.6.RELEASE \
  -d dependencies=web \
  -d baseDir=spring-integration-sender | tar -xzvf -
$ curl https://start.spring.io/starter.tgz \
  -d bootVersion=2.0.6.RELEASE \
  -d baseDir=spring-integration-receiver | tar -xzvf -

이제 메시지 전송 앱을 만들겠습니다. 발신 앱의 디렉터리로 변경합니다.

$ cd spring-integration-sender

앱에서 채널에 메시지를 써야 하는 경우 메시지가 채널에 수신되면 발신 채널 어댑터가 메시지를 수신하여 일반 Spring 메시지에서 Google Cloud Pub/Sub 주제로 변환하고 Google Cloud Pub/Sub 주제에 게시합니다.

앱이 채널에 쓰기 위해 Spring 통합 메시지 게이트웨이를 사용하면 됩니다. vim, emacs 또는 nano의 텍스트 편집기를 사용하여 DemoApplication 클래스 내에서 PubsubOutboundGateway 인터페이스를 선언합니다.

src/main/java/com/example/demo/DemoApplication.java

...
import org.springframework.integration.annotation.MessagingGateway;

@SpringBootApplication
public class DemoApplication {

        ...

        @MessagingGateway(defaultRequestChannel = "pubsubOutputChannel")
        public interface PubsubOutboundGateway {

                void sendToPubsub(String text);
        }
}

이제 채널에 메시지를 보낼 수 있는 메커니즘이 생겼지만 메시지가 전달된 후에는 어디로 이동하나요?

채널의 새 메시지를 사용하고 Google Cloud Pub/Sub 주제에 게시하려면 아웃바운드 채널 어댑터가 필요합니다.

src/main/java/com/example/demo/DemoApplication.java

...
import org.springframework.cloud.gcp.pubsub.core.PubSubTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.cloud.gcp.pubsub.integration.outbound.PubSubMessageHandler;
import org.springframework.messaging.MessageHandler;

@SpringBootApplication
public class DemoApplication {

        ...

        @Bean
        @ServiceActivator(inputChannel = "pubsubOutputChannel")
        public MessageHandler messageSender(PubSubTemplate pubsubTemplate) {
                return new PubSubMessageHandler(pubsubTemplate, "exampleTopic");
        }
}

@ServiceActivator 주석을 사용하면 MessageHandlerinputChannel의 모든 새 메시지에 적용됩니다. 이 경우에는 아웃바운드 채널 어댑터인 PubSubMessageHandler를 호출하여 Google Cloud Pub/Sub의 exampleTopic 주제에 메시지를 게시합니다.

이제 채널 어댑터를 사용하면 PubsubOutboundGateway 객체를 자동 연결하고 이를 사용해 채널에 메시지를 작성할 수 있습니다.

src/main/java/com/example/demo/DemoApplication.java

...
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.view.RedirectView;

@SpringBootApplication
public class DemoApplication {

...

        @Autowired
        private PubsubOutboundGateway messagingGateway;

        @PostMapping("/postMessage")
        public RedirectView postMessage(@RequestParam("message") String message) {
                this.messagingGateway.sendToPubsub(message);
                return new RedirectView("/");
        }
}

이제 @PostMapping 주석으로 인해 HTTP POST 요청을 리슨하는 엔드포인트가 있지만 REST 클래스에 @RestController 주석을 추가하여 REST 컨트롤러로 표시하지 않는 것도 있습니다.

src/main/java/com/example/demo/DemoApplication.java

import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication {
  ...
}

앱을 실행하려면 필요한 종속 항목을 추가하기만 하면 됩니다.

pom.xml

<project>
  ...
  <!-- Add Spring Cloud GCP Dependency BOM -->
  <dependencyManagement>
        <dependencies>
                <dependency>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-gcp-dependencies</artifactId>
                        <version>1.0.0.RELEASE</version>
                        <type>pom</type>
                        <scope>import</scope>
                </dependency>
        </dependencies>
  </dependencyManagement>

  <dependencies>
        ...
        <!-- Add Pub/Sub Starter -->
        <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
        </dependency>

        <!-- Add Spring Integration -->
        <dependency>
                <groupId>org.springframework.integration</groupId>
                <artifactId>spring-integration-core</artifactId>
        </dependency>

  </dependencies>

</project>

발신기 앱을 실행합니다.

# Set the Project ID in environmental variable
$ export GOOGLE_CLOUD_PROJECT=`gcloud config list \
  --format 'value(core.project)'`
$ ./mvnw spring-boot:run

앱이 포트 8080과 엔드포인트 /postMessage의 메시지가 포함된 POST 요청을 수신 대기 중이지만 나중에 확인하겠습니다.

방금 Google Cloud Pub/Sub를 통해 메시지를 보내는 앱을 만들었습니다. 이제 이러한 메시지를 수신하고 처리하는 또 다른 앱을 만들어 보겠습니다.

+를 클릭하여 새 Cloud Shell 세션을 엽니다.

그런 다음 새 Cloud Shell 세션에서 디렉터리를 수신기 앱 디렉터리로 변경합니다.

$ cd spring-integration-receiver

이전 앱에서는 메시지 게이트웨이 선언이 사용자를 위한 발신 채널을 만들었습니다. 메시지 게이트웨이를 사용하여 메시지를 수신하지 않으므로 수신 메시지를 받을 MessageChannel를 선언해야 합니다.

src/main/java/com/example/demo/DemoApplication.java

...
import org.springframework.context.annotation.Bean;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.messaging.MessageChannel;

@SpringBootApplication
public class DemoApplication {

        ...

        @Bean
        public MessageChannel pubsubInputChannel() {
                return new DirectChannel();
        }
}

Google Cloud Pub/Sub에서 메시지를 수신하고 pubsubInputChannel로 릴레이하려면 인바운드 채널 어댑터가 필요합니다.

src/main/java/com/example/demo/DemoApplication.java

...
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.gcp.pubsub.core.PubSubTemplate;
import org.springframework.cloud.gcp.pubsub.integration.inbound.PubSubInboundChannelAdapter;

@SpringBootApplication
public class DemoApplication {
        ...

        @Bean
        public PubSubInboundChannelAdapter messageChannelAdapter(
                        @Qualifier("pubsubInputChannel") MessageChannel inputChannel,
                        PubSubTemplate pubSubTemplate) {
                PubSubInboundChannelAdapter adapter =
                                new PubSubInboundChannelAdapter(pubSubTemplate, "exampleSubscription");
                adapter.setOutputChannel(inputChannel);

                return adapter;
        }
}

이 어댑터는 pubsubInputChannel에 바인딩되며 Google Cloud Pub/Sub exampleSubscription 구독에서 새 메시지를 수신합니다.

YouTube에 수신 메시지가 게시되는 채널이 있는데 이러한 메시지를 어떻게 해야 할까요?

새로운 메시지가 pubsubInputChannel에 도착하면 트리거되는 @ServiceActivator를 사용하여 처리되도록 하세요.

src/main/java/com/example/demo/DemoApplication.java

...
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.integration.annotation.ServiceActivator;

@SpringBootApplication
public class DemoApplication {

        ...

        private static final Log LOGGER = LogFactory.getLog(DemoApplication.class);

        @ServiceActivator(inputChannel = "pubsubInputChannel")
        public void messageReceiver(String payload) {
                LOGGER.info("Message arrived! Payload: " + payload);
        }
}

여기서는 메시지 페이로드만 기록합니다.

필요한 종속 항목을 추가해야 합니다.

pom.xml

<project>
  ...
  <!-- Add Spring Cloud GCP Dependency BOM -->
  <dependencyManagement>
        <dependencies>
                <dependency>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-gcp-dependencies</artifactId>
                        <version>1.0.0.RELEASE</version>
                        <type>pom</type>
                        <scope>import</scope>
                </dependency>
        </dependencies>
  </dependencyManagement>

  <dependencies>
        ...
        <!-- Add Pub/Sub Starter -->
        <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
        </dependency>

        <!-- Add Spring Integration -->
        <dependency>
                <groupId>org.springframework.integration</groupId>
                <artifactId>spring-integration-core</artifactId>
        </dependency>

  </dependencies>

</project>

수신기 앱을 실행합니다.

$ ./mvnw spring-boot:run

이제 발신자 앱에 보내는 모든 메시지가 수신기 앱에 로깅됩니다. 이를 테스트하려면 새 Cloud Shell 세션을 열고 발신자 앱에 HTTP POST 요청을 보냅니다.

$ curl --data "message=Hello world!" localhost:8080/postMessage

그런 다음 수신기 앱이 내가 보낸 메시지를 기록했는지 확인합니다.

INFO: Message arrived! Payload: Hello world!

이 연습의 일부로 만든 구독과 주제를 삭제합니다.

$ gcloud beta pubsub subscriptions delete exampleSubscription
$ gcloud beta pubsub topics delete exampleTopic

Google Cloud Pub/Sub용 Spring 통합 채널 어댑터를 사용하는 Spring Boot 앱을 두 개 설정합니다. Google Cloud Pub/Sub API와 상호작용하지 않고 메시지를 교환합니다.

Google Cloud Pub/Sub용 Spring 통합 채널 어댑터를 사용하는 방법을 알아보았습니다.

자세히 알아보기

라이선스

이 작업물은 Creative Commons Attribution 2.0 일반 라이선스에 따라 사용이 허가되었습니다.