반응형
이번 포스트에서는 SNS, SQS를 SpringBoot와 연동해 보자
1. SpringBoot 설정하기
1-1. SpringBoot 의존성 추가 (Build.gradle 파일)
- AWS의 메시지 서비스인 SQS(Simple Queue Service)와 SNS(Simple Notification Service)를 Spring Boot 애플리케이션과 통합하기 위한 의존성을 추가한다.
- 아래와 같이 코드를 작성한다.
// AWS
implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.1")
implementation 'io.awspring.cloud:spring-cloud-aws-starter-sqs'
implementation 'io.awspring.cloud:spring-cloud-aws-starter-sns'
1-2. 추가한 AWS 의존성 설명
- io.awspring.cloud:spring-cloud-aws-dependencies:3.0.1
- 이건 Spring Cloud AWS 프로젝트의 BOM(Bill of Materials) 의존성이다.
- BOM을 사용하면 프로젝트에서 사용하는 Spring Cloud AWS 관련 의존성들의 버전을 관리하기 쉬워진다. 이걸 사용하면 개별적으로 각 의존성의 버전을 명시할 필요가 없어져서 편리하다.
- io.awspring.cloud:spring-cloud-aws-starter-sqs
- 이건 AWS SQS를 사용하기 위한 스타터 패키지다.
- 스타터 패키지는 필요한 모든 의존성을 포함하고 있어서 SQS와 통합하는데 필요한 모든 것을 제공한다.
- io.awspring.cloud:spring-cloud-aws-starter-sns
- 이것도 마찬가지로 AWS SNS를 사용하기 위한 스타터 패키지다.
- SNS와 통합하는데 필요한 모든 의존성과 구성을 포함하고 있어서 개발자가 쉽게 SNS 기능을 애플리케이션에 추가할 수 있게 해 준다.
이 의존성들을 추가함으로써, Spring Boot 애플리케이션에서 AWS의 메시징 서비스인 SQS와 SNS를 손쉽게 사용할 수 있게 된다. 예를 들어, SQS로부터 메시지를 받거나 SNS 토픽에 메시지를 발행하는 기능을 구현할 수 있다.
1-3. Gradle Refresh 하기
- Build.gradle에 의존성을 추가하고 나서 intelliJ 우측 상단을 보면 "코끼리 모양" 버튼이 나오는데 이것을 누르거나 맨 우측의 코끼리를 눌러서 직접 refresh를 해주면 된다.
2. Application.yml 작성하기
2-1. Application.yml 작성
- AWS, SNS, SQS설정을 해준다.
2-2. SNS의 arn 찾기
- SNS에 적은 arn은 AWS의 SNS의 주제(Topic) 세부정보로 들어가서 ARN을 복사해서 넣는다.
2-3. SQS의 이름과 URL
- SQS의 세부 정보로 들어가면 필요한 SQS의 대기열 이름과 URL을 복사할 수 있다. (체크박스는 2개지만 여기서 "이름"만 가져다 사용하면 된다.)
2-4. application.yml에서 SQS의 name 설정만으로 충분한 이유
- 스프링 부트와 AWS SQS를 연동할 때 application.yml에 큐의 name만 설정하는 것이 표준 접근법이다. 왜냐하면, 스프링 클라우드 AWS가 @SqsListener를 통해 큐 이름을 자동으로 URL로 매핑해 주기 때문이다. 이렇게 하면 어플리케이션은 큐 이름만으로도 AWS의 해당 큐와 통신할 수 있게 된다.
- url 설정은 필요할 때만 추가한다. 대부분의 경우, name만으로 큐 식별이 가능하지만, 여러 리전이나 계정에서 같은 이름의 큐를 사용한다면 url로 명확히 지정하는 게 좋다. 이렇게 하면 메시지 전송 시 혼동을 방지할 수 있다.
결론적으로, name만으로도 스프링 클라우드 AWS가 큐를 찾아주니까, url은 필요에 따라 추가하는 선택적인 설정이라고 보면 된다.
2-5. 작성 코드 예시
- AWS와 스프링 부트를 통합할 때, application.yml 설정을 활용하면 자격 증명, 리전, SNS 토픽 ARN, SQS 큐 이름 및 URL 등을 손쉽게 관리할 수 있다. 이 방식을 쓰면 코드 내에서 AWS 자격 증명을 직접 다루지 않아도 되고, Spring Cloud AWS가 알아서 연동을 처리해 준다.
SNS나 SQS와 연동하는 경우에 이 설정을 사용하면 코드를 깔끔하게 유지할 수 있고, 설정 변경이 필요할 때는 코드를 건드리지 않고 설정 파일만 업데이트하면 되니까 관리가 훨씬 편해진다.
spring:
cloud:
aws:
credentials:
access-key: ${AWS_ACCESSKEY}
secret-key: ${AWS_SECRETKEY}
region:
static: ap-northeast-2 -> {지역 적기}
stack:
auto: false
sns:
topic:
arn: arn:aws:sns:ap-northeast-2:{13자리 계정번호}:{SNS의 Topic 이름}
sqs:
queue:
name: MemberQueue -> {SQS의 큐이름 적기}
#url: https://sqs.ap-northeast-2.amazonaws.com/{13자리 계정번호}/{SQS의 큐 이름}
3. SNS 클라이언트 Bean 등록하기
3-1. SnsConfig 설정클래스 작성하기
- 아래는 실제 작성한 코드예시다.
@Getter
@Configuration
public class AwsSnsConfig {
@Value("${spring.cloud.aws.credentials.access-key}")
private String awsAccessKey;
@Value("${spring.cloud.aws.credentials.secret-key}")
private String awsSecretKey;
@Value("${spring.cloud.aws.region.static}")
private String awsRegion;
@Value("${spring.cloud.aws.sns.topic.arn}")
private String snsTopicARN;
// SNS Client 세팅
@Bean
public SnsClient getSnsClient() {
return SnsClient.builder()
.region(Region.of(awsRegion)) // 리전 설정 추가
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(awsAccessKey, awsSecretKey)))
.build();
}
}
3-2. 코드 설명
- 이 코드는 Spring Boot 애플리케이션에서 AWS SNS(Simple Notification Service) 클라이언트를 설정하기 위한 구성 클래스다.
- @Configuration 어노테이션은 이 클래스가 스프링의 구성(설정) 클래스임을 나타낸다. @Value 어노테이션은 application.properties 또는 application.yml 파일에서 설정한 값을 필드에 주입한다.
- AwsSnsConfig
- AWS SNS 클라이언트를 설정하는 스프링 구성 클래스이다.
- AWS SNS 클라이언트를 설정하는 스프링 구성 클래스이다.
- awsAccessKey, awsSecretKey, awsRegion, snsTopicARN
- AWS 자격 증명과 리전, SNS 토픽 ARN을 저장하는 필드다. 이 값들은 외부 설정 파일에서 주입된다.
- AWS 자격 증명과 리전, SNS 토픽 ARN을 저장하는 필드다. 이 값들은 외부 설정 파일에서 주입된다.
- getSnsClient()
- SnsClient 인스턴스를 생성하고 스프링 빈으로 등록하는 메서드이다.
- 이 메서드는 StaticCredentialsProvider를 사용하여 자격 증명을 설정하고, Region.of() 메서드를 사용하여 AWS 리전을 설정한다.
이 클래스를 사용하면, AWS SNS와 통신하기 위한 클라이언트를 쉽게 생성하고, 스프링 애플리케이션 전반에서 사용할 수 있다.
4. SQS 클라이언트 Bean 등록하기
4-1. SQS 전용 Config 클래스를 작성
- 참고로 SQS는 리스너 전용 설정만 작성했다. (보내는 쪽은 설정하지 않음)
@Getter
@Configuration
public class AwsSqsConfig {
@Value("${spring.cloud.aws.credentials.access-key}")
private String awsAccessKey;
@Value("${spring.cloud.aws.credentials.secret-key}")
private String awsSecretKey;
@Value("${spring.cloud.aws.region.static}")
private String awsRegion;
// Sqs Async Client 세팅하기
@Bean
public SqsAsyncClient sqsAsyncClient() {
return SqsAsyncClient.builder()
.credentialsProvider(() -> new AwsCredentials() {
@Override
public String accessKeyId() {
return awsAccessKey;
}
@Override
public String secretAccessKey() {
return awsSecretKey;
}
})
.region(Region.of(awsRegion))
.build();
}
// Listener Factory 설정하기
@Bean
public SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory() {
return SqsMessageListenerContainerFactory
.builder()
.sqsAsyncClient(sqsAsyncClient())
.build();
}
}
4-2. 코드 설명
- SqsAsyncClient
- AWS SQS 서비스와 비동기적으로 통신할 수 있는 클라이언트를 생성한다.
- credentialsProvider() 메서드를 통해 AWS 자격 증명을 설정한다. 여기서는 익명 클래스를 사용해서 AwsCredentials 인터페이스를 구현하고 있다.
- region() 메서드를 사용하여 AWS 리전을 설정한다.
- SqsMessageListenerContainerFactory
- SQS 메시지 리스너를 위한 컨테이너 팩토리를 생성한다.
- 이 팩토리는 메시지 리스너가 메시지를 수신할 때 사용되는 컨테이너를 설정하는 데 사용된다.
- sqsAsyncClient() 메서드를 호출하여 생성된 SqsAsyncClient 인스턴스를 사용한다.
5. SNS로 메시지를 발행할 서비스 클래스 작성하기
5-1. Sns 서비스 클래스 작성하기
- 이 클래스에 작성한 메서드를 통해서 AWS Simple Notification Service(SNS)에 메시지를 발행하게 될 것이다.
- 작성한 코드예시
@Service
@RequiredArgsConstructor
public class SnsService {
private final AwsSnsConfig awsConfig;
private final ObjectMapper objectMapper;
public PublishResponse publishToSns(Map<String, Object> messageData) {
String messageJson;
try {
messageJson = objectMapper.writeValueAsString(messageData);
} catch (JsonProcessingException e) {
throw new RuntimeException("Failed to convert message data to JSON", e);
}
PublishRequest publishRequest = PublishRequest.builder()
.topicArn(awsConfig.getSnsTopicARN())
.subject("sns 전송 테스트")
.message(messageJson)
.build();
SnsClient snsClient = awsConfig.getSnsClient();
return snsClient.publish(publishRequest);
}
}
5-2. 코드 설명
- 이 서비스는 외부에서 받은 메시지 데이터를 JSON으로 변환해서 SNS에 발행하는 역할을 한다.
- 여기서 JSON을 사용하는 이유는 다음과 같다.
- 타입 보존 : JSON은 데이터 타입을 그대로 유지해 줘서, 수신자가 데이터를 정확하게 이해하고 처리할 수 있게 해 준다.
- 오류 관리 : ObjectMapper를 사용하면 변환 과정에서 발생할 수 있는 오류를 잡아내고, 적절한 예외 처리를 할 수 있어서 안정성이 높아진다.
- 확장성과 유지보수 : JSON은 표준화되고 널리 쓰이는 포맷이라, 시스템이 커지거나 다른 시스템과 연동할 때 문제가 적다.
- 통신 표준 : JSON은 웹 API 통신의 표준 포맷으로, 대부분의 언어와 플랫폼에서 쉽게 다룰 수 있다.
toString() 메서드를 쓰는 것보다 JSON 형식을 쓰는 게 이런 이유로 더 나은 선택이 되는 것이다.
6. SNS로 메시지를 발행할 컨트롤러 작성하기
6-1. SNS 관련 코드 사용방법
- 메시지 데이터 준비
- 발행하고자 하는 메시지의 내용을 Map<String, Object> 형태로 준비해야 한다. 이 Map에는 메시지의 각 부분을 key-value 쌍으로 넣으면 된다.
- 서비스 호출
- SnsService의 publishToSns() 메서드를 호출하면서, 준비한 메시지 데이터를 인자로 넘겨준다.
- 이 컨트롤러에서 방금 만든 서비스를 호출해서 메시지를 발행하게 된다. 그래서 서비스를 먼저 작성한 것이다. MVC패턴
- 결과 처리
- publishToSns() 메서드는 PublishResponse 객체를 반환한다. 이 객체를 사용해서 발행 요청의 결과를 처리할 수 있다.
6-2. 코드 작성하기
- 어떤 컨트롤러나 다른 서비스에서 이 SnsService를 사용하고 싶다면, 다음과 같이 할 수 있다.
- 아래는 작성한 코드이다.
@RequiredArgsConstructor
@RestController
public class NotificationController {
private final SnsService snsService;
@PostMapping("/notify")
public ResponseEntity<?> sendNotification(@RequestBody Map<String, Object> notificationData) {
// 1. SnsService를 사용해서 메시지 발행
PublishResponse response = snsService.publishToSns(notificationData);
// 2. 발행 결과를 HTTP 응답으로 반환
return ResponseEntity.ok().body(response.messageId());
}
}
7. PostMan으로 검증하기
7-1. PostMan에 컨트롤러로 설정한 매핑을 요청한다.
- Post매핑으로 설정해 주고 Header로 가서 Content-Type을 application/json으로 변경해 준다.
7-2. Body에 메시지 적어서 보내기
- Body에 아래와 같이 raw를 택한 다음 우측에서 JSON을 선택하고 하단에 JSON데이터를 적어서 보낸다.
- 전송이 성공하면 맨 하단의 Body부분에 발행에 성공한 Message의 ID값이 나올 것이다. (컨트롤러에서 ID를 반환하도록 작성함)
8. @SqsListener 메서드로 SNS 메시지 받아서 메서드 동작시키기
8-1. @SqsListener를 사용한 코드를 작성
- 여기서 클래스 상단에 @Service를 붙이는 이유는 해당 클래스가 Spring의 빈으로 등록되어야 하고, 그 안에 있는 @SqsListener 메서드가 메시지 리스너로 활성화되어야 하기 때문이다.
- 사용한 코드
@Service
public class AwsSqsListener {
@SqsListener(value = "${spring.cloud.aws.sqs.queue.name}")
public void receiveMessage(String message) {
// 메시지 처리 로직
System.out.println("Received message: " + message);
}
}
8-2. 로그 확인하기
- 아래와 같이 SNS로 발행한 메시지를 SQS가 잘 받아서 시스템으로 출력한 것을 확인할 수 있다. (독자분들은 로그 사용하시는 것을 추천)
드디어 SNS와 SQS를 SpringBoot와 연결하는 데 성공했다!
이렇게 SNS, SQS를 SpringBoot와 연결시켰다. 이 과정도 쉬운 것 같았지만 생각보다 오래 걸렸다.
왜냐하면 SpringBoot3.x.x를 사용하다 보니 생각보다 이에 대한 정보가 적었기 때문이다.
다른 블로그의 도움도 많이 받았는데 많은 정보를 제공해 주시는 지식 공유자 분들께 항상 감사함을 느끼며 이번 포스팅을 마친다.
2023.11.06 - [AWS] - AWS Message-Driven 완성 3편: SNS와 SQS 연동 및 테스트 전략
반응형
'AWS > SNS, SQS' 카테고리의 다른 글
AWS SQS에서 오류 메시지 처리하기: 수동 삭제로 해결하는 방법 (2) | 2023.11.24 |
---|---|
AWS Message-Driven 완성 3편: SNS와 SQS 연동 및 테스트 전략 (2) | 2023.11.06 |
AWS Message-Driven 실전 2편: SQS 구축과 테스트 검증 (0) | 2023.11.06 |
AWS Message-Driven 입문 1편: SNS 설정으로 시작하는 MSA (0) | 2023.11.06 |