SQS Visibility Timeout 완벽 이해: 메시지 중복 처리 원인과 해결법

SQS 큐에서 메시지가 두 개의 컨슈머에 의해 동시에 처리되는 현상을 프로덕션에서 처음 마주치면, 대부분 애플리케이션 코드나 멱등성 로직을 먼저 의심한다. 하지만 실제 원인은 대부분 더 단순한 곳에 있다 — Visibility Timeout 이 처리 시간보다 짧게 설정되어 있는 것이다. 이 설정 하나가 SQS 중복 처리 문제의 가장 흔한 원인이다. TL;DR — SQS Visibility Timeout 핵심 요약 항목 내용 Visibility Timeout 역할 메시지를 수신한 후 다른 컨슈머에게 보이지 않도록 숨기는 시간 기본값 30초 설정 범위 0초 ~ 12시간 중복 처리 발생 조건 처리 시간 > Visibility Timeout 권장 설정 최대 처리 시간의 6배 이상 (AWS 권장) 런타임 연장 방법 ChangeMessageVisibility API 호출 삭제 타이밍 처리 완료 후 반드시 DeleteMessage 호출 SQS Visibility Timeout 동작 원리 SQS는 메시지 브로커가 아니라 분산 큐다. 컨슈머가 메시지를 ReceiveMessage 로 가져가도 메시지는 큐에서 즉시 삭제되지 않는다. 대신 Visibility Timeout 동안 다른 컨슈머에게 보이지 않는 상태(invisible)로 전환된다. 컨슈머가 처리를 완료하고 DeleteMessage 를 호출해야 비로소 큐에서 제거된다. Visibility Timeout이 만료되기 전에 DeleteMessage 가 호출되지 않으면, SQS는 해당 메시지를 다시 visible 상태로 되돌린다. 이 순간 다른 컨슈머(또는 동일 컨슈머의 다른 인스턴스)가 동일 메시지를 다시 수신할 수 있게 된다. 이것이 중복 처리의 정확한 메커니즘이다. sequenceDiagram participant Q a...

DynamoDB 용량 모드 선택 가이드: On-Demand vs Provisioned — 트래픽 패턴을 모를 때 어떻게 결정할까

DynamoDB 테이블을 처음 생성할 때 가장 먼저 마주치는 질문이 바로 용량 모드 선택이다. 트래픽 패턴이 불분명한 초기 단계에서 Provisioned를 잘못 설정하면 스로틀링으로 요청이 거부되고, On-Demand를 무심코 유지하다 보면 예상치 못한 청구서를 받게 된다. 이 글은 DynamoDB 용량 모드 의 내부 동작 원리부터 실전 전환 판단 기준까지, 운영 경험을 바탕으로 정리한다. TL;DR — 한눈에 보는 선택 기준 상황 권장 모드 핵심 이유 트래픽 패턴 미확인, 초기 서비스 On-Demand 스로틀링 없이 자동 스케일, 용량 예측 불필요 트래픽이 예측 가능하고 일정함 Provisioned + Auto Scaling 단위 비용이 낮고 비용 상한 제어 가능 급격한 스파이크 + 평시 트래픽 낮음 On-Demand 피크 대비 Provisioned 과잉 프로비저닝 방지 높은 베이스라인 + 예측 가능한 피크 Provisioned + Auto Scaling Reserved Capacity와 조합 시 비용 최적화 DynamoDB 용량 모드의 내부 동작 원리 두 모드를 단순히 '자동 vs 수동'으로 이해하면 운영 중 반드시 실수가 생긴다. 각 모드가 내부적으로 어떻게 처리량을 관리하는지 먼저 파악해야 한다. Provisioned 모드 Provisioned 모드에서는 RCU(Read Capacity Unit)와 WCU(Write Capacity Unit)를 명시적으로 설정한다. DynamoDB는 설정된 용량을 파티션 단위로 분배하며, 특정 파티션에 요청이 집중되면 해당 파티션의 할당량이 소진되어 ProvisionedThroughputExceededException 이 발생한다. Auto Scaling을 활성화하면 CloudWatch 지표를 기반으로 목표 사용률에 맞게 RCU/WCU를 자동 ...

Route 53 Alias vs CNAME 레코드: ALB 연결 시 무엇을 선택해야 하는가

ALB를 새로 프로비저닝하고 도메인을 연결하려는 순간, 대부분의 엔지니어는 CNAME 레코드를 먼저 떠올린다. 그런데 example.com 자체(zone apex)를 ALB에 연결하려는 순간 CNAME은 동작하지 않는다 — DNS 표준이 이를 금지하기 때문이다. Route 53 Alias 레코드는 이 문제를 해결하기 위해 설계된 AWS 전용 확장이며, 단순한 편의 기능이 아니라 운영 비용과 장애 내성에 직접 영향을 미친다. TL;DR — Route 53 Alias vs CNAME 핵심 비교 항목 CNAME Route 53 Alias Zone Apex 사용 가능 여부 ❌ 불가 (RFC 1912) ✅ 가능 쿼리 과금 쿼리당 과금 AWS 리소스 대상 시 무료 DNS 응답 내용 CNAME 체인 반환 A/AAAA 레코드로 직접 응답 대상 리소스 상태 연동 없음 ALB 등 AWS 리소스와 연동 TTL 설정 직접 설정 Route 53이 자동 관리 사용 가능 대상 임의 호스트명 AWS 리소스 한정 DNS 동작 원리: CNAME 체인과 Alias 플래팅 CNAME 레코드는 한 호스트명을 다른 호스트명으로 위임한다. 클라이언트가 www.example.com 을 조회하면 리졸버는 CNAME 대상인 ALB의 DNS 이름을 다시 조회해야 한다. 이 추가 조회가 CNAME 체인이다. Zone apex( example.com )에 CNAME을 설정할 수 없는 이유는 RFC 1912에 명시되어 있다 — zone apex에는 SOA, NS 레코드가 반드시 공존해야 하는데, CNAME은 같은 이름에 다른 레코드가 존재하는 것을 허용하지 않는다. Route 53 Alias 레코드는 DNS 표준 레코드 타입이 아니다. Route 53 네임서버 내부에서 처리되는 확장으로, 쿼리 시점에 대상 리소스의 현재 IP 주소를 조...

Lambda 환경 변수 완전 가이드: DB 엔드포인트 주입부터 KMS 암호화까지

Lambda 함수에 데이터베이스 엔드포인트를 하드코딩했다가 코드 리포지토리에 그대로 노출된 경험이 한 번쯤은 있을 것이다. Lambda 환경 변수는 이 문제를 해결하는 가장 직접적인 방법이지만, KMS 암호화 옵션을 잘못 이해하면 오히려 보안 감사에서 지적을 받는다. TL;DR — Lambda 환경 변수 핵심 요약 항목 내용 환경 변수 설정 방법 콘솔, CLI, IaC 모두 지원. 런타임에 OS 환경 변수로 주입됨 기본 암호화 저장 시 AWS 관리형 키(aws/lambda)로 자동 암호화 KMS 고객 관리형 키(CMK) 별도 KMS 키 지정 시 추가 제어 가능. 함수 실행 역할에 kms:Decrypt 필요 전송 중 암호화 콘솔 헬퍼 암호화 사용 시 배포 전 클라이언트 측 암호화 적용 민감 정보 대안 Secrets Manager 또는 SSM Parameter Store(SecureString) 권장 Lambda 환경 변수가 동작하는 방식 Lambda는 함수 배포 패키지와 환경 변수를 분리해서 관리한다. 환경 변수는 함수 설정의 일부로 저장되고, 실행 환경(Execution Environment)이 초기화될 때 프로세스의 OS 환경 변수로 주입된다. 코드에서는 process.env.DB_ENDPOINT (Node.js), os.environ['DB_ENDPOINT'] (Python) 처럼 일반 환경 변수와 동일하게 읽는다. 저장 계층에서 Lambda는 기본적으로 AWS 관리형 KMS 키( aws/lambda )를 사용해 환경 변수를 암호화한다. 이 키는 AWS가 소유하고 관리하므로 별도 비용이 발생하지 않지만, 키 정책 제어나 감사 로그 분리는 불가능하다. 고객 관리형 키(CMK)를 지정하면 키 정책으로 접근을 제어하고 CloudTrail에서 복호화 이벤트를 추적할 수 있다. ...

AWS 프리 티어 요금 초과 방지: CloudWatch 결제 알람 설정 완전 가이드

AWS 계정을 처음 만들고 프리 티어로 실습하다가 월말에 예상치 못한 청구서를 받는 경우가 생각보다 많다. EC2 인스턴스를 종료하지 않고 잠들었거나, 실수로 프리 티어 한도를 초과하는 서비스를 켜둔 경우다. CloudWatch 결제 알람(Billing Alarm) 을 미리 설정해두면 요금이 임계값을 넘는 순간 이메일로 알림을 받을 수 있어, 프리 티어 초과를 조기에 차단할 수 있다. TL;DR — CloudWatch 결제 알람 설정 요약 단계 작업 핵심 포인트 1 결제 알람 활성화 루트 계정 또는 결제 권한 보유 IAM 사용자로 Billing 콘솔에서 활성화 필요 2 SNS 주제 생성 us-east-1 리전에서만 생성 — 결제 지표는 이 리전에만 존재 3 이메일 구독 추가 및 확인 구독 확인 이메일의 링크를 클릭해야 알림이 실제로 전송됨 4 CloudWatch 알람 생성 EstimatedCharges 지표, USD 5 임계값 설정 5 동작 확인 알람 상태 및 SNS 구독 상태 검증 결제 알람이 작동하는 방식 — 설정 전에 반드시 알아야 할 구조 CloudWatch 결제 알람은 일반 CloudWatch 알람과 동일한 메커니즘으로 동작하지만, 몇 가지 중요한 제약이 있다. AWS/Billing 네임스페이스의 EstimatedCharges 지표는 us-east-1 리전에서만 게시 된다. 다른 리전에서 알람을 만들려고 해도 이 지표를 찾을 수 없다. 또한 이 지표는 약 6시간마다 업데이트되므로, 실시간 요금 감시 도구가 아니라 누적 요금 경보 도구로 이해해야 한다. 알람이 트리거되면 CloudWatch는 SNS(Simple Notification Service) 주제로 메시지를 발행하고, SNS는 구독된 이메일 주소로 알림을 전달한다. 이 흐름에서 SNS 구독 확인이 완료되지 않으면 알람이 울려...

EBS gp2 vs gp3: IOPS 독립 확장과 비용 최적화 완전 가이드

EC2 인스턴스에 볼륨을 붙이려는데 콘솔에 gp2와 gp3가 나란히 보인다. 둘 다 '범용 SSD'라는 설명은 같은데, 실제 운영 환경에서 어떤 차이가 있는지 모르면 나중에 IOPS 부족으로 병목이 생기거나 불필요한 비용이 발생한다. EBS gp3는 스토리지 용량과 무관하게 IOPS를 독립적으로 조정할 수 있는 볼륨 타입으로, 대부분의 워크로드에서 gp2보다 비용 효율적이다. TL;DR — gp2 vs gp3 핵심 비교 항목 gp2 gp3 IOPS 결정 방식 용량에 연동 (3 IOPS/GB) 용량과 독립적으로 설정 기본 IOPS 용량 기반 자동 산정 3,000 IOPS (기본 포함) 최대 IOPS 16,000 16,000 최대 처리량 250 MiB/s 1,000 MiB/s 버스트 메커니즘 크레딧 버킷 방식 없음 (기본 성능이 일정) 비용 구조 GB당 단일 요금 GB + IOPS + 처리량 분리 과금 신규 워크로드 권장 — ✓ 가격과 한도는 변동될 수 있으므로 항상 AWS 공식 EBS 요금 페이지 에서 최신 정보를 확인하라. gp2와 gp3의 작동 방식 이해 gp2는 IOPS가 볼륨 크기에 묶여 있다. 1 GiB당 3 IOPS가 자동으로 할당되며, 최소 100 IOPS에서 최대 16,000 IOPS까지 선형으로 증가한다. 즉, 16,000 IOPS가 필요하면 최소 5,334 GiB 볼륨을 프로비저닝해야 한다. 실제로 그만큼의 스토리지가 필요 없더라도 IOPS를 위해 용량을 낭비하는 구조다. 버스트 메커니즘도 있다. 1 TiB 미만 볼륨은 크레딧 버킷을 소진하면서 최대 3,000 IOPS까지 일시적으로 올라가지만, 크레딧이 바닥나면 기본 IOPS로 떨어진다. 예측 불가능한 성능 저하의 원인이 된다. gp3는 이 연동 구조를 끊었다. 용량과 무관하게 기본 3,00...

ALB 502 Bad Gateway 완전 분석: 인스턴스가 Healthy인데 왜 502가 발생하는가

ALB 액세스 로그에 502가 쏟아지는데 타겟 그룹 콘솔에는 인스턴스가 멀쩡히 Healthy 로 표시되어 있다. 이 상황이 혼란스러운 이유는 ALB의 헬스체크와 실제 요청 처리가 완전히 별개의 레이어에서 동작하기 때문이다. 헬스체크는 통과했지만 실제 HTTP 응답이 ALB의 기대를 벗어나는 순간 502가 발생한다. TL;DR — ALB 502 원인 분류 원인 카테고리 증상 핵심 확인 지점 HTTP 프로토콜 위반 모든 요청에서 502 발생 응답 헤더 형식, Content-Length 불일치 Keep-Alive 타임아웃 불일치 간헐적 502, 로드 증가 시 악화 ALB idle timeout vs 앱 서버 keep-alive timeout 응답 헤더 크기 초과 특정 요청에서만 502 응답 헤더 총 크기 타겟 연결 거부/타임아웃 target_status_code가 비어 있음 보안 그룹, 포트 바인딩 청크 인코딩 오류 대용량 응답에서 502 Transfer-Encoding 헤더 처리 ALB 502가 발생하는 메커니즘 ALB는 클라이언트와 타겟 사이에서 HTTP 레이어 7 프록시로 동작한다. 타겟이 Healthy 상태라는 것은 ALB가 헬스체크 엔드포인트에서 정상 응답을 받았다는 의미일 뿐, 실제 애플리케이션 요청에 대한 응답이 올바르다는 보장이 아니다. ALB는 타겟으로부터 받은 HTTP 응답이 RFC를 위반하거나, 연결이 예기치 않게 끊기거나, 응답 자체를 받지 못하면 클라이언트에게 502를 반환한다. sequenceDiagram participant C as 클라이언트 participant ALB as ALB participant TG as 타겟 인스턴스 C->>ALB: HTTP 요청 ALB->>TG: 요청 전달 (Keep-Alive 연...