사내에서 메시징 서비스로 AWS SQS를 자주 사용하고 있습니다. SQS에서는 메시지를 최대 14일까지 보존하고 있는데요. 팀 내에서 혹시라도 장애 발생이나 실수 등으로 인해 설정한 보존 기간을 지났을 때 메시지 처리를 어떻게 해야할지 고민이 있었고, 이에 대해 확인한 내용을 공유해보겠습니다.
DLQ를 사용해볼까?
처음으로 생각해본 부분은 DLQ(Dead Letter Queue)를 적용하는 것이었습니다. AWS에서 DLQ에 대한 설명은 다음과 같습니다.
DLQ(Dead Letter Queue)는 소프트웨어 시스템에서 오류로 인해 처리할 수 없는 메시지를 임시로 저장하는 특수한 유형의 메시지 대기열입니다. DLQ(Dead Letter Queue)는 대상이 없거나 의도한 수신자가 처리할 수 없는 잘못된 메시지를 저장합니다.
‘시스템 오류로 인해 처리할 수 없는 메시지를 임시로 저장’한다는 내용이 딱 저희가 원하는 부분과 맞아보입니다.
한 번 생성해서 테스트 해보겠습니다.
DLQ 테스트

기본적으로 DLQ는 다른 큐와 동일합니다. 때문에 다른 큐를 만드는 것처럼 동일하게 큐를 생성해주면 됩니다. 저는 테스트 할 큐 이름 뒤에 ‘DLQ’만 추가하여 만들었습니다.
여기서 주의할 점은 표준 유형 큐의 DLQ는 표준 유형으로, FIFO 유형 큐의 DLQ는 FIFO 유형으로 만들어야 한다는 것입니다.

다음은 DLQ로 생성한 큐를 등록해줘야 합니다. 기존에 생성했던 큐라면 편집 메뉴로 들어가서 수정해주도록 합니다. 여기서 최대 수신 수는 DLQ로 메시지가 넘어가는 기준입니다. 큐에서 메시지가 설정된 최대 수신 수를 초과하여 수신되면 DLQ로 메시지가 넘어갑니다. (여기서 이상함을 느꼈어야 했습니다.)
그럼 테스트를 시작해보겠습니다.

‘메시지 전송 및 수신’ 메뉴로 들어가서 임의의 메시지를 전송합니다. 그리고 메시지 풀링으로 메시지를 수신합니다.

메시지 수신 수가 설정했던 최대 수신 수(2)를 넘어가면 사용 가능한 메시지가 0으로 바뀌고 DLQ로 설정했던 큐에서 메시지를 확인할 수 있습니다.
메시지를 수신하면 수신한 측에서 메시지 처리 후 메시지 삭제 처리를 해야하는데, 메시지가 삭제되지 않고 여러 번 수신되면 제대로 처리되지 못하는 메시지로 판단하여 DLQ로 전달하는 것입니다.
보존 기간을 지난 메시지는?
하지만 목적은 보존 기간이 지난 메시지를 DLQ로 보내는 것입니다. DLQ가 제대로 연결된 것은 확인했으니 보존 기간이 지난 후에도 DLQ로 보내지는지 확인해보았습니다.
결론부터 말하자면 보존 기간이 지난 메시지는 DLQ에서 확인할 수 없었습니다.
[Amazon SQS 메시지 대기열에 얼마나 오래 메시지를 보관할 수 있습니까?]메시지 보존 기간이 더 길면 메시지의 생산과 소비 간의 간격도 좀 더 길게 정할 수 있는 유연성이 제공됩니다. Amazon SQS 메시지 보존 기간은 1분에서 14일 사이의 값으로 구성할 수 있습니다. 기본 설정은 4일입니다. 메시지 보존 할당량에 도달하면 메시지가 자동으로 삭제됩니다.
[DLQ(Dead Letter Queue)는 어떻게 작동합니까?]소스 대기열을 생성할 때 Amazon SQS를 사용하면 배달 못한 편지 대기열(DLQ)과 SQS가 메시지를 DLQ로 이동해야 하는 조건을 지정할 수 있습니다. 조건은 소비자가 대기열에서 메시지를 수신할 수 있는 횟수로 maxReceiveCount로 정의됩니다. 메시지의 ReceiveCount가 대기열의 maxReceiveCount를 초과하면 Amazon SQS는 메시지를 배달 못한 편지 대기열(원래 메시지 ID 포함)로 이동하도록 설계되었습니다. Amazon SQS FAQ
AWS FAQ에도 설명되어 있지만, 보존 기간이 지난 메시지는 삭제됩니다. DLQ는 보존 기간과는 전혀 관련없이 동작합니다.
그리고 더 큰 문제가?!
여기까지는 AWS 문서만 제대로 확인한다면 알 수 있는 내용입니다. 다만, 실습을 통해 확인해보았을 뿐입니다. 그런데 테스트 중 예상치 못한 이슈를 발견하였습니다.

위는 모니터링 지표중 ‘삭제된 메시지 수’ 지표입니다. 대기열에서 삭제된 메시지 수를 표시하는 지표인데, 위에서 확인한 AWS의 설명대로라면 보존 기간이 종료된 메시지는 자동으로 삭제가 되고, 그럼 지표에 표시되야할 것 같습니다. 하지만 위 지표에서는 실제 메시지가 수신 후 삭제 처리된 값만 확인할 수 있습니다.
AWS의 지표 설명에 따르면, 메시지 수신 측에서 직접 DeleteMessage 작업을 호출하여 성공 상태가 반환되는 경우, 위 지표가 증가한다고 합니다. 자동 삭제 처리되는 경우에는 증가하지 않는 것입니다.
결론적으로, 보존 기간이 초과되어 삭제된 메시지는 어디서도 흔적을 찾을 수 없게 됩니다.
대안을 찾아보자
사실 최대로 설정했을 때 14일이라는 기간은 결코 부족한 시간이 아닙니다. 그렇기에 AWS에서도 그 시간이 지나면 더 이상 신경 쓸 필요없는 데이터로 취급하고 흔적도 없이 지워버리는 것이 아닌가 싶습니다. 하지만 운영하다보면 다양한 상황들이 있을 수 있다보니 조금이나마 대응할 방법은 없을지 알아봅시다.

모니터링 지표에 ‘가장 오래된 메시지의 대략적인 수명’이라는 지표가 있습니다. 영어로는 ‘ApproximateAgeOfOldestMessage’로 표시됩니다. 이 지표는 대기열에 있는 삭제되지 않은 가장 오래된 메시지의 대략적인 기간을 보여줍니다. 만일 이 기간이 최대 보존 기간에 가깝다면 보존 기간이 초과되어 자동 삭제된 메시지가 있을 가능성이 큽니다.
이 지표는 Cloudwatch에서 경보하는데 쓸 수 있습니다. Lambda를 연결 하는 등의 작업을 통해 최대 보존 기간에 지표가 가까워지면 슬랙 알람이 오도록 할 수 있고, 작업자가 놓치는 일은 줄일 수 있을 것입니다.
경보 설정과 관련된 내용은 아래 링크를 참고하시면 좋습니다.
메시지를 3회 이상 수신했는데 처리하지 않았으면 메시지가 대기열의 맨 뒤로 이동되고ApproximateAgeOfOldestMessage
지표는 3회 이하로 수신한 두 번째로 오래된 메시지를 가리킵니다. 이 작업은 대기열에 리드라이브 정책이 있는 경우에도 발생합니다. SQS 지표 - ApproximateAgeOfOldestMessage
위 지표로 알림을 보낼 때도 주의할 점이 있습니다. 3회 넘게 수신된 메시지의 보존 기간은 지표로 잡히지 않습니다. 따라서 제대로 사용하려면 DLQ 최대 수신 수 설정을 3으로 설정해서 같이 쓰는 것이 좋아보이네요.
정리하자면..
테스트하며 확인 한 내용들을 정리하면 다음과 같습니다.
- DLQ 설정 없는 큐는 삭제하지 않는 한 유효기간 내 무한정 수신된다.
- DLQ 설정 시 설정된 최대 수신 수 값을 넘으면 DLQ로 메시지가 넘어간다.
- 보존 기간이 초과된 메시지는 DLQ로 넘어가지 않으며 자동 삭제된다.
- 메시지 수신하는 측에서 삭제 시에는 콘솔의 모니터링 지표에서 '삭제된 메시지 수'로 집계가 된다.
- 하지만 보존 기간 초과된 메시지는 삭제되더라도 '삭제된 메시지 수' 지표에서 모니터링 되지 않는다.
SQS에서 메시지를 관리해주기 때문에 개발자는 이에 대해 신경쓰지 않을 수 있는 장점이 있지만, 모든 것을 보장해주지는 않으므로 적절한 주의가 필요하겠습니다.
Share article