[AWS] Amazon SQS 적용해보기 - 스프링 SQS 설정 및 AWS SQS로 메시지 보내기

김강욱·2024년 5월 8일
1

Project-Evertrip

목록 보기
10/19
post-thumbnail

이번 포스팅에서는 Spring Boot Application에서 SQS로 메시지를 보내는 시간을 가져보도록 하겠습니다.

사실 진행중인 Evertrip 프로젝트는 SQS에 메시지를 Listen 하는 목적으로만 사용할 계획이기 때문에 SQS로 메시지를 보낼 필요는 없지만 그래도 SQS에 메시지를 보내는 작업을 추가로 확장할 수도 있기 때문에 정리해보려고 합니다.

1. build.gradle 설정 추가

먼저 build.gradle에 의존성 설정을 추가해보도록 하겠습니다.

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.2.4'
	id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '17'
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	// 메시지 큐 의존성 추가, Spring 3.0 버전 이상이라면 아래로 설정
	implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.1")
	implementation 'io.awspring.cloud:spring-cloud-aws-starter-sqs'
}

tasks.named('test') {
	useJUnitPlatform()
}

Spring Boot 3.x에 호환되는 버전은 Spring Cloud AWS 3.x 버전이라고 하네요. 이전 버전과 설정법이 조금 달라졌다고 합니다.

현재 프로젝트의 Spring Boot 버전은 3.2.4 이며 이를 기준으로 SQS 설정 해주었습니다.


2. application.yml에 AWS 설정 추가하기

## AWS 설정
cloud:
  aws:
    credentials:
      accessKey: ENC(pm3ifHj0/X0OQeQpb/JIbViMcQOWAOXOCHaNm2E174Q=)
      secretKey: ENC(AjW16S4bKWYSZ8Gi9bopBjateeI1eA39p0MF0v69YgGU5Y7C9pd8h+Pm2xJMZTBn07ihdRkhXxE=)
    s3:
      bucket: ever-trip-bucket
    sqs:
      queue-name: evertripqueue
    region:
      static: ap-northeast-2
    stack:
      auto: false

기존의 프로젝트는 이미 AWS S3를 사용하기 위해 cloud-aws를 연동해놓은 상태이므로 sqs의 queue-name만 간단히 추가해주었습니다.

3. SQSConfig 파일 작성

@Configuration
public class AwsSQSConfig {

    @Value("${cloud.aws.credentials.accessKey}")
    private String AWS_ACCESS_KEY;

    @Value("${cloud.aws.credentials.secretKey}")
    private String AWS_SECRET_KEY;

    @Value("${cloud.aws.region.static}")
    private String AWS_REGION;

    // 클라이언트 설정: region과 자격증명
    @Bean
    public SqsAsyncClient sqsAsyncClient() {
        return SqsAsyncClient.builder()
                .credentialsProvider(() -> new AwsCredentials() {
                    @Override
                    public String accessKeyId() {
                        return AWS_ACCESS_KEY;
                    }

                    @Override
                    public String secretAccessKey() {
                        return AWS_SECRET_KEY;
                    }
                })
                .region(Region.of(AWS_REGION))
                .build();
    }

    // Listener Factory 설정 (Listener 쪽)
    @Bean
    SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory(SqsAsyncClient sqsAsyncClient) {
        return SqsMessageListenerContainerFactory
                .builder()
                .configure(options -> options
                        .acknowledgementMode(AcknowledgementMode.ALWAYS)
                        .acknowledgementInterval(Duration.ofSeconds(3))
                        .acknowledgementThreshold(5)
                        .acknowledgementOrdering(AcknowledgementOrdering.ORDERED)
                )
                .sqsAsyncClient(sqsAsyncClient)
                .build();
    }

    // 메시지 발송을 위한 SQS 템플릿 설정 (Sender 쪽)
    @Bean
    public SqsTemplate sqsTemplate() {
        return SqsTemplate.newTemplate(sqsAsyncClient());
    }
}

다음은 AwsSQSConfig 파일을 등록해주었습니다. application.yml에 등록된 환경 변수(AccessKey, SecretKey, Region)에 대한 정보를 바탕으로 SqsAsyncClient, SqsMessageListenerContainerFactory, SqsTemplate 세가지 빈을 등록해주었습니다.

해당 설정에는 Listener에 대한 설정도 포함되어있습니다. 나중에 메시지 수신에 대한 로직을 위한 설정 정보이니 참고하시면 될 것 같습니다.

먼저 SqsAsyncClient 빈 설정은 실제 비동기 SQS 클라이언트의 정보를 설정하고 있습니다. AccessKey, SecretKey, Region에 대한 정보를 이용하여 클라이언트 인스턴스를 생성하여 실제 SQS와의 요청에 해당 클라이언트 인스턴스를 사용합니다.

다음 SqsMessageListenerContainerFactory 빈 설정은 SQS 메시지를 처리하기 위한 컨테이너를 설정하고 있습니다. SqsMessageListenerContainerFactory<Object>에서의 제네릭 타입 Object는 반환하려는 메시지의 타입을 나타냅니다. 이후 테스트 시에 반환 타입을 바꿔 적용해보도록 하겠습니다.

acknowledgementMode(AcknowledgementMode.ALWAYS) 옵션의 설정은 메시지가 처리된 후에 항상 해당 메시지의 수신을 확인하여 SQS 서비스에 알리도록 설정하는 것입니다. 메시지를 성공적으로 처리했다는 신호를 보내며, SQS는 이 메시지를 큐에서 제거하게 됩니다.

acknowledgementInterval(Duration.ofSeconds(3)) 옵션의 설정은 수신 확인 신호를 보내는 간격을 설정합니다. 여기서는 3초마다 처리된 메시지의 수신 확인을 SQS에 전송하게 됩니다.

acknowledgementThreshold(5) 옵션의 설정은 수신 확인을 보내기 전에 처리해야할 메시지의 최소 수를 지정합니다. 여기서는 5개의 메시지가 처리되면, 그 때 수신 확인을 보내게 됩니다. 앞에 Duration 설정과의 관계는 or 입니다. 즉, 둘 중 어느 하나라도 만족할 시 수신 확인 신호를 보내게 됩니다.

acknowledgementOrdering(AcknowledgementOrdering.ORDERED) 옵션의 설정은 메시지의 수신 확인을 보낼 때의 순서를 지정합니다. ORDERED 설정은 메시지가 수신된 순서대로 처리되고 확인됨을 의미합니다.

추가로 여러 메시지의 처리가 완료된 후 SQS에 메시지 수신 완료 확인을 보낼 때 일괄적으로 보내기 때문에 시스템 성능을 최적화하는데 도움이 됩니다.

마지막으로 SqsTemplate 빈 설정은 AWS SQS(Simple Queue Service)와의 상호작용을 위한 편리한 고수준 인터페이스를 생성하게 됩니다. 일반적으로 메시지 큐 시스템과의 작업을 단순화하며, 메시지 발송, 수신, 큐 관리 작업에 대해서 수행하도록 도와주는 역할을 합니다.


4. SQSMessageSender 등록

@Component
public class SqsMessageSender {

    private final SqsTemplate queueMessagingTemplate;

    @Value("${cloud.aws.sqs.queue-name}")
    private String QUEUE_NAME;

    public SqsMessageSender(SqsAsyncClient sqsAsyncClient) {
        this.queueMessagingTemplate = SqsTemplate.newTemplate(sqsAsyncClient);
    }

    public SendResult<String> sendMessage(String message) {
        System.out.println("Sender: " + message);
        return queueMessagingTemplate.send(to -> to
                .queue(QUEUE_NAME)
                .payload(message));
    }
}

SQS에 메시지를 전송할 빈을 등록해줍니다. 앞서 생성해주었던 SqsTemplate 빈을 의존성 주입받아 파라미터로 받은 message를 그대로 SQS Queue에 보내주는 역할을 하게 됩니다.

5. Test 진행

이제 SQS에 메시지를 보내고 Test 하는 과정을 진행해보겠습니다.

Controller
@RequiredArgsConstructor
@RestController
public class SQSController {

    private final SqsMessageSender sqsMessageSender;


    @PostMapping("/test/message")
    public void sendMessage(@RequestBody String message) {
        sqsMessageSender.sendMessage(message);
    }


}

해당 컨트롤러의 메서드에 요청을 보내고 SQS에 메시지를 확인해보겠습니다.

Postman으로 테스트 메시지를 작성한후 JSON 형태로 RequestBody에 넣어 요청을 전송하고 응답으로는 200 응답을 받았습니다.

이후 SQS 대기열에서 메시지 전송 및 수신을 클릭합니다.

메시지 전송 및 수신 페이지의 하단에서 메시지 폴딩 버튼을 클릭하시면 현재 대기열에 저장된 메시지를 확인하실 수 있습니다.

메시지가 한개 저장되어있고 해당 메시지를 클릭하시면

다음과 같이 테스트 메시지가 저장되어있음을 확인하실 수 있습니다. 성공적으로 테스트를 마쳤네요 ㅎㅎ


참고 자료
lannstark님의 블로그
beekei님의 블로그

profile
TO BE DEVELOPER

0개의 댓글

관련 채용 정보