AWS

Lambda 재귀 루프 감지 EventBridge 지원, 도쿄와 서울 리전에서 직접 확인해 보기

Lambda와 EventBridge로 이벤트 기반 구조를 만들다 보면, 함수가 처리 결과를 이벤트로 다시 발행하는 경우를 경험해 보신 적이 있으신가요?
이때 규칙 패턴을 넓게 잡거나 이벤트 버스 이름을 잘못 넣으면, 함수가 자신을 호출한 버스에 다시 이벤트를 보내 무한 루프가 생기는 상황이 생길 수 있습니다.
호출이 계속 이어지면서 동시성과 비용이 순식간에 올라가고, 대부분 청구서나 경보를 보고 나서야 알게 됩니다.

안녕하세요. GS Neotek 송상민 입니다.
이런 상황에 활용하기 좋은 기능이 나와서 직접 실험해 보았습니다.

AWS 발표 소개

2026년 10월 14일, AWS Lambda의 재귀 루프 감지 기능이 Amazon EventBridge 커스텀 이벤트 버스까지 지원하도록 확장되었습니다.
Lambda 함수가 자신을 호출한 이벤트 버스로 다시 이벤트를 보내는 실수를 하면, Lambda가 이 루프를 감지해서 끊어 준다는 내용입니다.
도쿄와 서울 리전에서 실제로 무한 루프를 만들어 확인해 보았고, 서울 리전 사용자라면 알아 두어야 할 결과가 나와서 정리했습니다.

재귀 루프 감지는 어떻게 동작하나요

공식 문서에 따르면 동작 방식은 다음과 같습니다.

  • 지원 서비스가 Lambda로 보내는 이벤트에는 X-Ray 추적 헤더 기반의 메타데이터가 붙고, 함수가 지원 SDK로 다시 이벤트를 쓰면 이 메타데이터의 호출 횟수가 올라갑니다.
  • 같은 이벤트에서 시작된 호출 체인이 약 16회에 이르면 Lambda가 다음 호출을 중단합니다.
  • 중단되면 RecursiveInvocationsDropped CloudWatch 지표가 기록되고, AWS Health Dashboard와 운영 담당자 이메일로 알림이 갑니다(최대 3.5시간 지연).
  • 별도 설정이 필요 없는 기본 기능이며, 의도적으로 재귀를 쓰는 함수만 PutFunctionRecursionConfig로 끌 수 있습니다.

먼저 알아야 할 것: 커스텀 이벤트 버스가 두 종류가 되었습니다

이번 발표를 이해하려면 한 달 전 소식을 먼저 알아야 합니다.
2026년 9월 24일 EventBridge가 커스텀 이벤트 버스를 새로 출시하면서, 기존 버스는 “Custom event bus – classic”으로 이름이 바뀌었습니다.
그리고 이번 재귀 루프 감지의 대상은 이 중 새 커스텀 이벤트 버스입니다.

두 버스의 가장 큰 차이는 버스가 이벤트를 저장하느냐입니다.

  • 기존 버스(default 버스 포함)는 이벤트를 저장하지 않습니다.
    들어오는 순간 규칙(Rule)이 패턴을 보고 타깃(Target)으로 바로 밀어 주고 끝납니다.
  • 새 버스는 이벤트를 일정 기간(기본 24시간, 최대 1년) 쌓아 둡니다.
    구독자(Subscriber)가 각자 거기서 꺼내 가는 구조라서, 과거 시점부터 다시 받기, 배치로 받기, 순서대로 받기 같은 설정을 구독자마다 할 수 있습니다.

규칙 하나에 타깃을 여러 개 다는 것과 구독자를 여러 개 만드는 것은 결과가 같으므로, 대상 수가 핵심 차이는 아닙니다.

구분기존 버스(classic, default)새 커스텀 이벤트 버스
이벤트 전달규칙 + 타깃
(들어오는 즉시 전달)
구독자(Subscriber)
(보관된 이벤트를 꺼내 감)
이벤트 보관없음기본 24시간, 최대 1년
배치·순서 보장1건씩, 순서 보장 없음1. 배치 크기 설정
2. FIFO 순서 보장·중복 제거
APIeventseventsv2(SDK에서는 eventbridgev2)
출시 리전모든 상용 리전14개 리전(서울 미포함)
이번 재귀 루프 감지대상 아님대상

실험

한눈에 보기

항목내용
실험 일자2026-10-29 ~ 2026-10-30
공통 조건1. Python 3.13 런타임
2. 재귀 루프 감지 설정 Terminate(기본값)
3. 함수 코드에 30회 안전장치
도쿄(ap-northeast-1)새 커스텀 이벤트 버스 + 구독자 → 16회 호출 후 Lambda가 중단(2회 반복 동일)
서울(ap-northeast-2)1. 기존 커스텀 이벤트 버스 + 규칙 → 31회 호출, Lambda가 중단하지 않음(3회 반복 동일)
2. 같은 함수의 SQS 루프 → 16회 호출 후 중단
3. 새 커스텀 이벤트 버스 → 서울 리전에 아직 없음

실험 1: 도쿄 리전, 새 커스텀 이벤트 버스

새 버스와 구독자를 만들고, 구독자의 대상으로 Lambda 함수를 연결했습니다(비동기 호출, 1건씩 전달).
함수에는 일부러 “자신을 호출한 버스에 다시 이벤트를 보내는” 버그를 넣었고, 감지가 동작하지 않을 때를 대비해 30회에서 스스로 멈추는 안전장치를 코드에 두었습니다.

새 버스는 API가 따로 있어서, 함수에서도 eventbridgev2 클라이언트를 써야 합니다.
Python 3.13 런타임에 기본으로 들어 있는 boto3에는 이 클라이언트가 없어서, 최신 boto3(1.43.122)를 Lambda 계층(Layer)으로 넣었습니다.

구독자는 아래처럼 만들었습니다.
기존 방식의 “규칙 + 타깃”이 여기서는 구독자 하나에 필터와 대상, 전달 설정이 함께 들어갑니다.

이벤트 하나를 넣어 루프를 시작하자, 호출이 정확히 16회(hop 0~15)에서 멈췄고 안전장치는 동작하지 않았습니다.
RecursiveInvocationsDropped 지표에 1건이 기록되었고, 추적 헤더의 Lineage 카운터가 호출마다 1씩 올라가는 것도 확인할 수 있습니다.

도쿄 새 버스 루프가 16회 호출 후 중단된 로그

중단된 17번째 이벤트는 함수의 실패 대상(SQS)으로 넘어갔습니다.
condition이 RecursiveInvocation이고 approximateInvokeCount가 0이라서, 함수 코드가 실행되기 전에 Lambda가 막았다는 것을 알 수 있습니다.

중단된 이벤트의 실패 기록, condition이 RecursiveInvocation

한 번 더 실행해도 같은 결과(16회, 중단 지표 누적 2건)가 나왔습니다.

도쿄 재실행 결과

실험 2: 서울 리전, 기존 커스텀 이벤트 버스

서울 리전에는 기존 커스텀 이벤트 버스만 있으므로, 기존 방식(이벤트 버스 + 규칙 + Lambda 타깃)으로 같은 루프를 만들었습니다.
함수 코드는 events 클라이언트와 버스 이름(EventBusName)을 쓰는 것만 다르고 나머지는 같습니다.

함수의 재귀 루프 감지 설정이 기본값(Terminate)인 것을 확인한 뒤, 이벤트 하나만 넣어 루프를 시작했습니다.

재귀 루프 감지 설정이 Terminate인 것을 확인한 화면

호출이 31회까지 이어졌고 결국 코드의 안전장치(30회)가 루프를 끝냈습니다.
RecursiveInvocationsDropped 지표에도 아무 값이 없었습니다.
Lineage 카운터는 도쿄와 똑같이 1씩 올라가므로, 루프 횟수 정보는 전달되지만 중단 대상이 아니라서 끊기지 않는 것으로 보입니다.

서울 기존 버스 루프에서 Lineage 카운터가 증가하지만 31회까지 호출된 로그

계정 설정 문제는 아닌지 확인하려고, 같은 함수에 SQS 트리거를 붙여 같은 큐로 다시 메시지를 보내는 루프를 만들어 비교했습니다.
이번에는 호출이 정확히 16회(hop 0~15)에서 멈췄습니다.

SQS 루프는 16회 호출 후 Lambda가 중단한 로그

기존 버스 루프를 한 번 더 돌려 보아도 결과는 같았고, RecursiveInvocationsDropped 지표에는 SQS 루프를 중단한 기록만 남았습니다.

서울 기존 버스 재실행 결과와 RecursiveInvocationsDropped 지표

실험 3: 서울 리전에는 새 커스텀 이벤트 버스가 아직 없습니다

그렇다면 서울에서도 새 버스로 바꾸면 되지 않을까 해서, 최신 SDK로 새 버스 API를 호출해 보았습니다.
서울 리전은 새 버스 API 엔드포인트(eventsv2.ap-northeast-2.amazonaws.com)가 존재하지 않아 연결 자체가 되지 않았고, 도쿄와 버지니아 북부에는 엔드포인트가 있었습니다.

서울 리전에는 새 커스텀 이벤트 버스 API 엔드포인트가 없는 것을 확인한 결과

결과 비교

리전 · 루프 경로호출 횟수루프를 끝낸 주체RecursiveInvocationsDropped
도쿄 · 새 커스텀 이벤트 버스 + 구독자16회Lambda 재귀 루프 감지기록됨
서울 · 기존 커스텀 이벤트 버스 + 규칙31회코드 안전장치(30회)기록 없음
서울 · SQS (같은 함수)16회Lambda 재귀 루프 감지기록됨
서울 · 새 커스텀 이벤트 버스––서울 리전 미지원

결론

이번 기능은 새 커스텀 이벤트 버스를 위한 기능이고, 도쿄의 새 버스에서는 루프가 16회에서 확실히 끊겼지만 서울 리전은 아직 새 버스를 지원하지 않습니다.

좋았던 점 / 아쉬웠던 점

  • 1. 설정 없이 기본으로 켜져 있습니다.
    지원되는 경로에서는 아무 설정 없이 16회에서 바로 끊겼고, 지표와 실패 기록도 바로 남았습니다.
  • 2. 함수 코드가 실행되기 전에 막습니다.
    중단된 호출은 approximateInvokeCount가 0으로, 17번째 호출부터는 함수가 아예 실행되지 않았습니다.
  • 3. 서울 리전에서는 아직 이 기능의 혜택을 받기 어렵습니다.
    새 커스텀 이벤트 버스가 서울에 없고, 서울에서 쓰는 기존 버스 + 규칙 구성은 이번 실험에서 중단 대상이 아니었습니다.
  • 4. 발표문만으로는 대상이 분명하지 않습니다.
    “EventBridge Custom event buses”라는 표현만 보면 기존 버스도 포함되는 것처럼 읽힐 수 있어, 새 버스 출시 소식과 함께 보는 것이 필요할 수 있습니다.

서울 리전에서는 이렇게 대비하세요

서울 리전에서 EventBridge와 Lambda를 함께 쓰고 있다면, 새 버스가 들어올 때까지 아래 장치를 직접 두는 것이 안전합니다.

  • 이벤트에 홉(hop) 카운터를 넣고 코드에서 상한을 두는 안전장치
  • 함수 예약 동시성(Reserved Concurrency) 제한
  • 호출 수(Invocations) CloudWatch 경보와 AWS Cost Anomaly Detection

이 기능을 직접 실습해 보실 분께: 서울 리전에서 기존 이벤트 버스(default 포함) + 규칙으로 실습하면 루프가 끊기지 않습니다.
도쿄처럼 새 커스텀 이벤트 버스를 지원하는 리전에서 구독자(Subscriber) 방식으로 해 보시고, 혹시 모르니 함수 코드에 호출 횟수 상한을 꼭 넣어 두세요.

게시글을 평가해주세요

궁금한 점이 있으신가요?

자세한 문의는 GS Neotek 홈페이지를 이용해 주세요.

문의하기

필자: 송 상민

전체 게시물수 : 2

전체 조회수 : 1107

게시물 공유하기