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

1. 개요

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

이 연습에서는 Spring Cloud GCP에서 제공하는 Spring Integration 채널 어댑터를 사용하여 통신하는 두 개의 앱을 만듭니다. 이러한 어댑터를 사용하면 Spring Integration에서 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 서비스 사용 경험을 평가해 주세요.

초급 중급 고급

2. 설정 및 요구사항

자습형 환경 설정

  1. Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.

b35bf95b8bf3d5d8.pnga99b7ace416376c4.pngbd84a6d3004737c5.png

  • 프로젝트 이름 은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
  • 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud 콘솔은 고유한 문자열을 자동으로 생성합니다. 일반적으로는 신경 쓰지 않아도 됩니다. 대부분의 Codelab에서는 프로젝트 ID (일반적으로 PROJECT_ID로 식별됨)를 참조해야 합니다. 생성된 ID가 마음에 들지 않으면 다른 임의 ID를 생성할 수 있습니다. 또는 직접 시도해 보고 사용 가능한지 확인할 수도 있습니다. 이 단계 이후에는 변경할 수 없으며 프로젝트 기간 동안 유지됩니다.
  • 참고로 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참고하세요.
  1. 다음으로 Cloud 리소스/API를 사용하려면 Cloud 콘솔에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼이 끝난 후에 요금이 청구되지 않도록 리소스를 종료하려면 만든 리소스 또는 프로젝트를 삭제하면 됩니다. Google Cloud 신규 사용자는 300달러(USD) 상당의 무료 체험판 프로그램에 참여할 수 있습니다.

Google Cloud Shell

Google Cloud의 경우 노트북에서 원격으로 조작할 수 있지만 이 Codelab에서는 Cloud에서 실행되는 명령줄 환경인 Google Cloud Shell을 사용합니다.

Cloud Shell 활성화

  1. Cloud Console에서 Cloud Shell 활성화 853e55310c205094.png 를 클릭합니다.

55efc1aaa7a4d3ad.png

Cloud Shell을 처음 시작하는 경우 Cloud Shell에 대한 설명이 포함된 중간 화면이 표시됩니다. 중간 화면이 표시되면 계속 을 클릭합니다.

9c92662c6a846a5c.png

Cloud Shell을 프로비저닝하고 연결하는 작업은 몇 분이면 끝납니다.

9f0e51b578fecce5.png

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

Cloud Shell에 연결되면 인증이 완료되었고 프로젝트가 해당 프로젝트 ID로 설정된 것을 확인할 수 있습니다.

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

명령어 출력

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Cloud Shell에서 다음 명령어를 실행하여 gcloud 명령어가 프로젝트를 알고 있는지 확인합니다.
gcloud config list project

명령어 출력

[core]
project = <PROJECT_ID>

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

gcloud config set project <PROJECT_ID>

명령어 출력

Updated property [core/project].

3. Pub/Sub 리소스 프로비저닝

Google Cloud Pub/Sub 주제 페이지로 이동합니다.

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

4c938409dc7169a6.png

주제 이름으로 exampleTopic을 입력한 후 만들기 를 클릭합니다.

e2daeec91537f672.png

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

975efa26e5054936.png

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

f7a91d9e1cb48009.png

4. Spring Boot 애플리케이션 초기화

Cloud Shell이 실행되면 명령줄을 사용하여 Spring Initializr로 두 개의 새 Spring Boot 애플리케이션을 생성할 수 있습니다.

$ curl https://start.spring.io/starter.tgz \
  -d bootVersion=3.0.5 \
  -d dependencies=web,integration,cloud-gcp-pubsub \
  -d type=maven-project \
  -d baseDir=spring-integration-sender | tar -xzvf -

$ curl https://start.spring.io/starter.tgz \
  -d bootVersion=3.0.5 \
  -d dependencies=web,integration,cloud-gcp-pubsub \
  -d type=maven-project \
  -d baseDir=spring-integration-receiver | tar -xzvf -

5. 메시지를 전송하는 애플리케이션 만들기

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

$ cd spring-integration-sender

앱이 채널에 메시지를 쓰도록 하겠습니다. 메시지가 채널에 있으면 아웃바운드 채널 어댑터에서 메시지를 선택하여 일반 Spring 메시지에서 Google Cloud Pub/Sub 메시지로 변환하고 Google Cloud Pub/Sub 주제에 게시합니다.

앱이 채널에 쓸 수 있도록 Spring Integration 메시징 게이트웨이를 사용할 수 있습니다. 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 com.google.cloud.spring.pubsub.core.PubSubTemplate;
import com.google.cloud.spring.pubsub.integration.outbound.PubSubMessageHandler;

import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.ServiceActivator;
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 요청을 수신 대기하는 엔드포인트가 있지만 DemoApplication 클래스에 @RestController 주석을 추가하여 REST 컨트롤러로 표시해야 합니다.

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

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

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

JAVA_HOME이 올바른 버전으로 설정되어 있는지 확인합니다.

export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64

발신자 앱을 실행합니다.

# 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 요청을 수신 대기하고 있지만 이 내용은 나중에 설명합니다.

6. 메시지를 수신하는 애플리케이션 만들기

Google Cloud Pub/Sub를 통해 메시지를 전송하는 앱을 만들었습니다. 이제 이러한 메시지를 수신하고 처리하는 다른 앱을 만듭니다.

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

9799bee5fea95aa6.png

그런 다음 새 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 com.google.cloud.spring.pubsub.core.PubSubTemplate;
import com.google.cloud.spring.pubsub.integration.inbound.PubSubInboundChannelAdapter;

import org.springframework.beans.factory.annotation.Qualifier;

@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 구독의 새 메시지를 수신 대기합니다.

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

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);
  }
}

JAVA_HOME이 올바른 버전으로 설정되어 있는지 확인합니다.

export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64

수신기 앱을 실행합니다.

$ ./mvnw spring-boot:run -Dspring-boot.run.jvmArguments="-Dserver.port=8081"

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

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

그런 다음 수신기 앱이 전송한 메시지를 기록했는지 확인합니다.

INFO: Message arrived! Payload: Hello world!

7. 정리

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

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

8. 요약

Google Cloud Pub/Sub용 Spring Integration 채널 어댑터를 사용하는 두 개의 Spring Boot 앱을 설정했습니다. 이러한 앱은 Google Cloud Pub/Sub API와 상호작용하지 않고 서로 메시지를 교환합니다.

9. 수고하셨습니다

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

자세히 알아보기

라이선스

이 작업물은 크리에이티브 커먼즈 저작자 표시 2.0 일반 라이선스에 따라 사용이 허가되었습니다.