EventBridge로 Lambda 스케줄링하기: Cron 표현식으로 매일 오전 8시 실행
Lambda 함수를 매일 오전 8시에 실행해야 하는데, 처음에는 단순해 보였다. 그런데 막상 EventBridge 콘솔을 열면 Cron 문법이 일반적인 Unix Cron과 미묘하게 달라서 첫 번째 규칙을 잘못 설정하는 경우가 많다. 이 글은 EventBridge Cron 표현식으로 Lambda를 스케줄링하는 전체 과정을 다루고, 실수하기 쉬운 타임존 문제와 권한 설정까지 정확하게 짚는다.
TL;DR — EventBridge Lambda 스케줄링 핵심 요약
| 항목 | 내용 |
|---|---|
| 스케줄 방식 | Rate 표현식 또는 Cron 표현식 |
| 매일 오전 8시 (UTC) Cron | cron(0 8 * * ? *) |
| EventBridge 기본 타임존 | UTC (변경 불가, Scheduler는 타임존 지정 가능) |
| 필수 IAM 권한 | EventBridge → Lambda 호출용 리소스 기반 정책 필요 |
| 한국 시간 오전 8시 UTC 환산 | 전날 오후 11시 UTC → cron(0 23 * * ? *) |
| 타임존 지정이 필요하면 | EventBridge Scheduler 사용 권장 |
EventBridge 스케줄링이 동작하는 방식
EventBridge에는 두 가지 스케줄링 메커니즘이 있다. 하나는 EventBridge Rules (규칙 기반 스케줄)이고, 다른 하나는 2022년 말에 출시된 EventBridge Scheduler다. 이 둘은 같은 서비스처럼 보이지만 동작 모델이 다르다.
(Schedule)"] -->|"직접 타겟 호출"| B["Lambda 함수"] C["EventBridge Scheduler"] -->|"실행 역할(IAM Role) 사용"| B A -.->|"리소스 기반 정책 필요"| B C -.->|"Execution Role 필요"| B style A fill:#FF9900,color:#fff style C fill:#FF9900,color:#fff style B fill:#009900,color:#fff
- EventBridge Rules (Schedule): Cron 또는 Rate 표현식을 기반으로 이벤트를 생성하고, 연결된 타겟(Lambda 등)을 호출한다. 타임존은 항상 UTC다.
- EventBridge Scheduler: 독립적인 스케줄러 서비스로, 타임존 지정, 유연한 시간 창(Flexible time window), 일회성 스케줄을 지원한다. 타겟 호출 시 실행 역할(Execution Role)이 필요하다.
- Lambda 리소스 기반 정책: EventBridge가 Lambda를 호출하려면 Lambda 함수에
lambda:InvokeFunction권한을 허용하는 리소스 기반 정책이 있어야 한다. 이 정책이 없으면 규칙은 생성되지만 Lambda는 실행되지 않는다.
EventBridge Rules의 스케줄은 버스(Event Bus)를 통하지 않는다. 스케줄 규칙은 이벤트 버스에 이벤트를 게시하는 것이 아니라 직접 타겟을 호출한다. 이 점을 모르면 이벤트 버스 정책을 아무리 수정해도 문제가 해결되지 않는다.
EventBridge Cron 표현식 문법 — Unix Cron과 다른 점
AWS EventBridge의 Cron 표현식은 6개 필드를 사용한다. 일반적인 Unix Cron의 5개 필드와 다르고, 필드 순서와 특수 문자 규칙도 다르다.
cron(분 시 일 월 요일 연도)
# 예시
cron(0 8 * * ? *) # 매일 UTC 08:00
cron(0 23 * * ? *) # 매일 UTC 23:00 (한국 시간 오전 8시)
cron(30 14 ? * MON-FRI *) # 평일 UTC 14:30
cron(0 8 1 * ? *) # 매월 1일 UTC 08:00
| 필드 | 허용 값 | 특수 문자 |
|---|---|---|
| 분 (Minutes) | 0–59 | , - * / |
| 시 (Hours) | 0–23 | , - * / |
| 일 (Day-of-month) | 1–31 | , - * ? / L W |
| 월 (Month) | 1–12 또는 JAN–DEC | , - * / |
| 요일 (Day-of-week) | 1–7 또는 SUN–SAT | , - * ? L # |
| 연도 (Year) | 1970–2199 | , - * / |
핵심 제약: 일(Day-of-month)과 요일(Day-of-week) 필드를 동시에 지정할 수 없다. 하나를 지정하면 나머지는 반드시 ?로 설정해야 한다. 매일 실행이 목적이라면 cron(0 8 * * ? *)처럼 요일 필드를 ?로 둔다.
Step 1: Lambda 함수 준비 및 리소스 기반 정책 확인
EventBridge가 Lambda를 호출하려면 Lambda 함수에 호출 권한이 부여되어 있어야 한다. 콘솔에서 규칙을 생성하면 이 정책이 자동으로 추가되지만, CLI나 IaC로 작업할 때는 직접 추가해야 한다. 권한이 없으면 규칙은 정상적으로 생성되고 트리거도 걸리지만, Lambda는 조용히 실행되지 않는다 — CloudWatch Logs에도 아무것도 남지 않는다.
# Lambda 함수의 현재 리소스 기반 정책 확인
aws lambda get-policy \
--function-name my-scheduled-function \
--region us-east-1
# EventBridge가 Lambda를 호출할 수 있도록 권한 추가
aws lambda add-permission \
--function-name my-scheduled-function \
--statement-id EventBridgeDailyTrigger \
--action lambda:InvokeFunction \
--principal events.amazonaws.com \
--source-arn arn:aws:events:us-east-1:123456789012:rule/daily-8am-rule \
--region us-east-1
--source-arn에 규칙 ARN을 지정하면 해당 규칙만 이 Lambda를 호출할 수 있다. *로 열어두면 같은 계정의 모든 EventBridge 규칙이 호출 가능해지므로, 특정 규칙 ARN을 명시하는 것이 최소 권한 원칙에 부합한다.
Step 2: EventBridge 스케줄 규칙 생성 (매일 오전 8시 UTC)
규칙을 먼저 생성하고, 이후 타겟을 연결한다. 두 단계를 분리해서 실행해야 한다.
# 스케줄 규칙 생성
aws events put-rule \
--name daily-8am-rule \
--schedule-expression "cron(0 8 * * ? *)" \
--state ENABLED \
--description "매일 UTC 08:00에 Lambda 실행" \
--region us-east-1
# Lambda 타겟 연결
aws events put-targets \
--rule daily-8am-rule \
--targets "Id=LambdaTarget1,Arn=arn:aws:lambda:us-east-1:123456789012:function:my-scheduled-function" \
--region us-east-1
타겟 연결 시 Id는 규칙 내에서 고유한 식별자로, 임의의 문자열을 사용할 수 있다. 하나의 규칙에 최대 5개의 타겟을 연결할 수 있다.
Step 3: 한국 시간 기준으로 오전 8시 실행 — 타임존 처리
EventBridge Rules는 타임존을 UTC로 고정한다. 한국 표준시(KST)는 UTC+9이므로, 한국 시간 오전 8시는 UTC로 전날 오후 11시(23:00)다.
# 한국 시간 오전 8시 = UTC 23:00 (전날)
aws events put-rule \
--name daily-8am-kst-rule \
--schedule-expression "cron(0 23 * * ? *)" \
--state ENABLED \
--description "매일 KST 08:00 (UTC 23:00)에 Lambda 실행" \
--region ap-northeast-2
서머타임(DST)이 적용되는 타임존이 필요하다면 EventBridge Rules로는 처리할 수 없다. 이 경우 EventBridge Scheduler를 사용해야 한다.
Step 4: EventBridge Scheduler로 타임존 지정 (선택적 접근)
타임존을 명시적으로 지정해야 하거나, 서머타임 대응이 필요하다면 EventBridge Scheduler가 적합하다. Scheduler는 실행 역할(Execution Role)이 필요하다 — EventBridge Rules와 달리 Lambda 리소스 기반 정책만으로는 부족하다.
🔽 EventBridge Scheduler IAM 실행 역할 정책 (클릭하여 펼치기)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:ap-northeast-2:123456789012:function:my-scheduled-function"
}
]
}
신뢰 정책(Trust Policy)에는 scheduler.amazonaws.com을 Principal로 추가해야 한다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "scheduler.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
# EventBridge Scheduler로 Asia/Seoul 타임존 기준 매일 오전 8시 스케줄 생성
aws scheduler create-schedule \
--name daily-8am-seoul \
--schedule-expression "cron(0 8 * * ? *)" \
--schedule-expression-timezone "Asia/Seoul" \
--flexible-time-window Mode=OFF \
--target '{"Arn": "arn:aws:lambda:ap-northeast-2:123456789012:function:my-scheduled-function", "RoleArn": "arn:aws:iam::123456789012:role/SchedulerExecutionRole"}' \
--region ap-northeast-2
필요?"} Q1 -->|"아니오 (UTC 고정)"| Q2{"단순 반복
주기?"} Q1 -->|"예"| SCHEDULER["EventBridge Scheduler
+ 실행 역할(IAM Role)"] Q2 -->|"예"| RATE["Rate 표현식
rate(1 day) 등"] Q2 -->|"아니오 (특정 시각/요일)"| CRON["EventBridge Rules
Cron 표현식 (UTC 기준)"] RATE --> POLICY["Lambda 리소스 기반 정책 추가"] CRON --> POLICY SCHEDULER --> DONE(["스케줄 완료"]) POLICY --> DONE style SCHEDULER fill:#FF9900,color:#fff style CRON fill:#146EB4,color:#fff style RATE fill:#146EB4,color:#fff style POLICY fill:#cc0000,color:#fff
- EventBridge Rules 경로: 타임존은 UTC 고정. Lambda 리소스 기반 정책으로 호출 권한을 부여한다.
- EventBridge Scheduler 경로: 타임존 지정 가능. 실행 역할(IAM Role)을 통해 Lambda를 호출한다.
- 선택 기준: 단순 UTC 스케줄이면 Rules, 타임존/DST/일회성 스케줄이 필요하면 Scheduler.
Step 5: 스케줄 규칙 동작 검증
규칙을 만들었다고 끝이 아니다. 실제로 Lambda가 호출되는지 확인해야 한다. 가장 빠른 방법은 Rate 표현식으로 짧은 주기 규칙을 임시로 만들어 테스트하거나, 콘솔에서 직접 타겟을 테스트하는 것이다.
# 규칙 상태 및 타겟 확인
aws events describe-rule \
--name daily-8am-rule \
--region us-east-1
aws events list-targets-by-rule \
--rule daily-8am-rule \
--region us-east-1
# Lambda 함수의 최근 호출 로그 확인 (CloudWatch Logs)
aws logs describe-log-streams \
--log-group-name /aws/lambda/my-scheduled-function \
--order-by LastEventTime \
--descending \
--max-items 5 \
--region us-east-1
# Lambda 리소스 기반 정책에 EventBridge 권한이 있는지 재확인
aws lambda get-policy \
--function-name my-scheduled-function \
--region us-east-1
실제 운영에서 만나는 문제 — 규칙은 있는데 Lambda가 실행 안 된다
EventBridge 규칙을 만들고 타겟도 연결했는데 Lambda가 실행되지 않는다는 신고가 들어왔다. CloudWatch Logs에는 아무것도 없었다. EventBridge 콘솔에서 규칙 상태는 ENABLED였고, 타겟도 정상으로 보였다.
처음엔 Cron 표현식이 잘못됐다고 생각했다. cron(0 8 * * * *)처럼 요일 필드에 ? 대신 *를 쓴 경우였다. 그런데 이 표현식은 콘솔에서 오류 없이 저장됐다 — 실제로는 잘못된 표현식이지만 저장 시점에 검증이 통과된 것이다.
실제 원인은 Lambda 리소스 기반 정책이었다. CLI로 규칙을 생성했기 때문에 콘솔처럼 자동으로 권한이 추가되지 않았다. aws lambda get-policy를 실행하니 정책 자체가 없었다. aws lambda add-permission으로 권한을 추가하자 다음 스케줄 시각에 정상 실행됐다.
Lambda가 실행되지 않을 때 확인 순서: 리소스 기반 정책 → Cron 표현식 유효성 → 규칙 상태 → 타겟 ARN 정확성.
Rate 표현식 vs Cron 표현식 선택 기준
단순 반복 주기라면 Rate 표현식이 더 간결하다. 특정 시각이나 요일 조건이 필요하면 Cron을 써야 한다.
# Rate 표현식 예시
cron 대신 rate를 사용할 수 있는 경우:
rate(5 minutes) # 5분마다
rate(1 hour) # 1시간마다
rate(1 day) # 24시간마다 (실행 시각은 규칙 생성 시각 기준)
rate(1 day)는 매일 같은 시각에 실행되는 것처럼 보이지만, 실제로는 규칙이 활성화된 시각을 기준으로 24시간 간격으로 실행된다. 정확한 시각이 중요하다면 반드시 Cron 표현식을 사용해야 한다.
Wrap-up: EventBridge Lambda 스케줄링 정리 및 다음 단계
EventBridge Cron 표현식으로 Lambda를 스케줄링하는 핵심은 세 가지다: 올바른 Cron 문법(6개 필드, 일/요일 중 하나는 ?), UTC 타임존 처리, Lambda 리소스 기반 정책 설정. 타임존 지정이 필요하다면 EventBridge Scheduler로 전환하는 것이 가장 깔끔한 해결책이다.
- 공식 문서: EventBridge 스케줄 규칙 패턴
- 공식 문서: EventBridge Scheduler 스케줄 유형
- 관련 주제: Lambda 동시 실행 제한 및 예약 동시성 설정
- 관련 주제: EventBridge Scheduler Dead-letter Queue(DLQ) 설정으로 실패 이벤트 처리
Glossary — 핵심 용어
| 용어 | 설명 |
|---|---|
| Cron 표현식 | 시간 기반 스케줄을 정의하는 문자열. AWS EventBridge는 6개 필드(분/시/일/월/요일/연도)를 사용한다. |
| 리소스 기반 정책 | Lambda 함수 자체에 부착되어 특정 서비스나 계정이 함수를 호출할 수 있도록 허용하는 IAM 정책. |
| EventBridge Scheduler | 타임존 지정, 유연한 시간 창, 일회성 스케줄을 지원하는 독립 스케줄러 서비스. EventBridge Rules와 별개다. |
| 실행 역할 (Execution Role) | EventBridge Scheduler가 타겟(Lambda 등)을 호출할 때 사용하는 IAM 역할. |
| Flexible Time Window | EventBridge Scheduler에서 지정된 시각 전후 일정 범위 내에서 실행을 분산시키는 옵션. 동시 실행 부하를 줄이는 데 사용한다. |
댓글
댓글 쓰기