스프링부트 sns, sqs 적용기

hbjs97·2023년 7월 24일
0

사내프로젝트 진행중 업로드한 이미지의 썸네일을 추출해 갱신해야하는 상황이 생겼다.
서비스 특성상 대량이 이미지가 업로드되는데, 무거운 썸네일 추출작업을 대량으로 처리하자니 api 서버에서 감당이 안될것같았다.

해당 작업을 담당하는 별도의 모듈(프로세스)을 개발해 비동기처리하기로 정했다.
인프라쪽 여력이 부족해 당장 kafka 환경을 구성해 사용하기는 어려웠다. 그래서 대안으로 sns, sqs를 사용하기로했다.

redis, kafka를 mq로 사용해본 경험이 있는데 sns, sqs는 설정이 더 간편해보여 금방 적용시킬 수 있을것같았다.
하지만 여러문제들이 있었고 어떻게 해결했는지 기록해보려고 한다.

SNS, SQS 연동하는 순서는 다음과 같다.
1. SNS 주제 생성
2. SQS 큐 생성
3. SQS가 SNS를 구독

서버에서 이를 사용하는 api, worker 서비스가 있다.
api 서비스에서 SNS에 이벤트를 발행하고, worker 서비스에서 이를 구독해 비동기 처리를한다.


구독을 생성할 때

위와같은 설정을 할 수 있는데, '원시 메시지 전송 활성화' 라는 옵션이 있다.
처음 설정할 때 해당옵션을 체크하지 않았다.

그렇게 구독을 생성하고 SNS에 이벤트를 발행했는데 SQS Listener에서 수신받은 데이터에 문제가 있었다.

예를들어 이벤트 발행 시 List 형식의 데이터를 payload로 사용했는데, listener에서 수신한 데이터는 많은 메타데이터가 추가된 형식의 객체였다.

class ReceivedData(
        val Type: String,
        val MessageId: String,
        val TopicArn: String,
        val Message: String,
        val Timestamp: String,
        val SignatureVersion: String,
        val Signature: String,
        val SigningCertURL: String,
        val UnsubscribeURL: String,
        val MessageAttributes: String,
        val id: String,
        val contentType: String,
        val timestamp: String,
)

위와같은 형태의 데이터가 수신되었는데, 발행한 데이터는 Message에 string으로 들어가있었다.
내가 필요한건 발행할때 넣었던 데이터인데, 메타데이터가 너무 많이 붙어오고 역직렬화 컨버터도 만들어서 사용해야 한다는점이 너무 불편했다. Long 타입 몇개넣어서 발행했을 뿐인데 수신된 데이터의 양이 1KB 정도 되는 비효율적인 문제도 발생했다.

첫번째로 시도했던건 SNS을 통하지 않고 바로 SQS에 적재하는 것이다.
spring boot 애플리케이션에서 SNS에 발행하던 Payload를 그대로 SQS에 담아 적재했는데, 위 문제들이 해결되었다.
데이터양이 줄어들었고 메타데이터도 제거되었고 역직렬화 할 필요없이 타입에 맞는 인스턴스로 listen을 할 수 있었다.

다 좋았는데 SNS를 이용하지 못한다는점이 너무 아쉬웠다.
이를 적용하려는 서비스에는 A 이벤트를 SNS에 발행했을때, 해당 이벤트를 구독하는 SQS 큐가 3개있다. 즉, 위와같은 방식으로 SQS에 직접 적재하려면 여러개의 큐에 직접 적재해야 하는 불편한 문제도 있었고, 각 큐에 데이터를 적재하는 중 문제가 발생하면 이전에 적재된 데이터를 되돌릴 방법이 없다는 점도 문제였다.

따라서 SNS 사용을 포기할 수 없었고 방법을 찾아봤는데 정말 단순하게 해결이 가능한 문제였다.
구독을 생성할 때 '원시 메시지 전송 활성화' 를 체크하면 메타데이터 없이 Payload만 주고받을 수 있었다.

1개의 댓글

comment-user-thumbnail
2023년 7월 24일

좋은 글이네요. 공유해주셔서 감사합니다.

답글 달기