Step Functions vs SQS 조합: 워크플로 오케스트레이션 선택 기준
주문 처리처럼 여러 단계가 이어지는 백엔드 처리를 만들 때, 구조 선택지는 크게 둘입니다. Step Functions가 전체 흐름을 지휘하거나, 각 단계가 SQS 큐로 다음 단계에 넘기며 이어지거나. 결론을 먼저 적으면, 분기·재시도·보상 처리가 있는 업무 플로우, 그리고 흐름 전체를 한눈에 봐야 하는 처리는 Step Functions, 단계가 한둘뿐인 단순 비동기 처리와 대량 이벤트 소비는 SQS + Lambda입니다. 요금 차이가 수십 배라 돈 문제로 보이기 쉽지만, 실제 결정 요소는 실패 처리를 누가 책임지는가입니다. 메시징 서비스 자체의 선택은 SQS vs SNS vs EventBridge에서 다뤘습니다. 요금은 us-east-1 기준입니다.
한눈에 보는 비교 #
| 구분 | Step Functions Standard | Step Functions Express | SQS + Lambda 체인 |
|---|---|---|---|
| 과금 단위 | 상태 전이 100만 건당 약 $25 | 100만 실행당 약 $1 + 실행 시간 | 100만 요청당 약 $0.40 |
| 최장 실행 | 1년 | 5분 | 제한 없음 (큐 단위 연결) |
| 실행 보장 | 정확히 1회 | 최소 1회 | 최소 1회 |
| 실행 이력·시각화 | 단계별 이력 90일 | CloudWatch Logs 경유 | 없음 (직접 구축) |
| 재시도·분기·병렬 | 선언적 정의 | 선언적 정의 | 각 소비자 코드에 분산 |
| 서비스 직접 통합 | 200개 이상 (Lambda 없이 호출) | 동일 | Lambda 필수 |
| 적합한 형태 | 업무 플로우, 사가, 사람 승인 대기 | 고빈도 단기 파이프라인 | 단순 비동기, 부하 평준화 |
구조 차이: 지휘자가 있는가 #
Step Functions는 오케스트레이션입니다. 흐름 정의가 한 곳(상태 머신)에 있고, 각 단계의 성공·실패·재시도·분기를 그 정의가 결정합니다. 실행마다 어느 단계까지 갔고 어디서 실패했는지가 이력으로 남고 콘솔에서 시각적으로 보입니다. 재시도 정책과 catch 절을 선언만 하면 되므로, 실패 처리 코드가 업무 코드에서 분리됩니다.
SQS + Lambda 체인은 코레오그래피입니다. 전체 흐름을 아는 주체가 없고, 각 단계가 자기 일을 끝내면 다음 큐에 메시지를 넣는 방식으로 이어집니다. 구성 요소는 큐와 함수뿐이라 단순하고 요금도 낮지만, 흐름이라는 개념 자체가 코드 바깥에 존재하지 않습니다. “이 주문이 지금 어느 단계에 있는가?“에 답하려면 상관 ID 로깅과 추적을 직접 만들어야 하고, 3단계에서 실패한 처리를 되돌리는 보상 로직도 각 소비자에 흩어집니다.
단계가 2개 이하이고 실패 처리가 “DLQ에 넣고 재처리"로 충분하다면 코레오그래피의 단순함이 이깁니다. 단계가 늘고, 분기가 생기고, 부분 실패 시 되돌림(사가 패턴)이 필요해지는 순간부터는 흩어진 흐름이 유지보수 비용으로 돌아옵니다. 경험적으로 큐를 사이에 둔 단계가 3개를 넘으면 상태 머신으로 옮길 신호입니다.
요금: 수십 배 차이의 실체 #
Standard 워크플로는 상태 전이당 과금입니다. 100만 전이당 약 $25이므로, 5단계 워크플로를 월 100만 번 실행하면 전이 500만 건에 약 $125입니다. 같은 처리를 SQS 체인으로 만들면 큐 요청 수백만 건에 몇 달러 수준입니다. 이 격차 때문에 고빈도 처리에 Standard를 쓰면 청구서가 눈에 띄게 자랍니다.
그 사이를 메우는 것이 Express 워크플로입니다. 100만 실행당 약 $1에 실행 시간·메모리 요금이 더해지는 구조라, 짧은 고빈도 파이프라인이면 Standard의 수십 분의 1로 내려갑니다. 위 예시라면 실행 요금을 합쳐도 몇 달러 선입니다. 대가는 제약입니다. 최장 5분, 최소 1회 실행 보장(멱등성 필요), 이력은 CloudWatch Logs 경유라 Standard의 단계별 콘솔 이력만큼 편하지 않습니다.
정리하면 요금 축의 선택은 세 칸입니다. 사람 승인 대기나 장시간 처리가 끼는 저빈도 업무 플로우는 Standard, 5분 안에 끝나는 고빈도 자동 파이프라인은 Express, 오케스트레이션 자체가 필요 없는 처리는 SQS입니다. Standard 요금이 부담될 때 첫 검토 대상은 SQS 전환이 아니라 Express 전환입니다.
병용: 대립이 아니라 조합 #
실무 구성은 둘 중 하나가 아니라 조합인 경우가 많습니다.
- 입구는 SQS, 처리는 Step Functions: 큐로 유입 스파이크를 평준화하고, 소비자가 큐에서 꺼내 상태 머신 실행을 시작합니다. 큐의 버퍼링과 상태 머신의 가시성을 함께 얻습니다.
- 상태 머신 안에서 SQS 호출: Step Functions는 SQS 전송을 직접 통합으로 호출할 수 있어, 다른 시스템에 일을 넘기는 단계를 Lambda 없이 만들 수 있습니다. 콜백 토큰(waitForTaskToken)을 쓰면 “메시지를 보내고 외부 처리가 끝날 때까지 대기"하는 단계도 됩니다.
- 본류는 상태 머신, 부수 작업은 큐: 주문 확정이라는 본류는 Step Functions로 지휘하고, 알림 발송 같은 실패해도 본류에 영향 없는 부수 작업은 큐로 흘려보내는 분리가 요금과 복잡도를 함께 낮춥니다.
선택 순서 #
- 흐름의 단계 수와 분기부터 셉니다: 2단계 이하 직선 처리는 SQS + Lambda로 충분합니다. 3단계 이상, 분기·병렬·보상이 보이면 Step Functions 후보입니다.
- 실패 시나리오를 적어 봅니다: “어디까지 갔는지 추적해야 하는가, 부분 실패를 되돌려야 하는가"에 하나라도 예면 오케스트레이션이 맞습니다. DLQ 재처리로 충분하면 큐 체인입니다.
- Standard와 Express를 실행 시간·빈도로 가릅니다: 5분 초과 또는 사람 대기가 있으면 Standard, 단기 고빈도면 Express입니다. 멱등성이 확보되는지도 이때 확인합니다.
- 요금은 전이 수로 검산합니다: 단계 수 × 월 실행 수 × $0.000025가 Standard 요금입니다. 고빈도인데 Standard를 쓰고 있다면 Express 전환이 첫 절감입니다.
- 유입 평준화가 필요하면 앞에 큐를 둡니다: 스파이크 흡수는 큐의 일이고 흐름 지휘는 상태 머신의 일입니다. 역할을 나누면 둘 다 작아집니다.
정리 #
- 결정 요소는 요금보다 실패 처리의 책임 소재입니다. 재시도·분기·보상·추적이 필요하면 Step Functions, DLQ로 충분한 단순 비동기는 SQS + Lambda입니다.
- Standard는 상태 전이 100만 건당 약 $25로 비싸지만 1년 실행, 정확히 1회, 단계별 이력을 줍니다. 저빈도 업무 플로우의 요금입니다.
- Express는 100만 실행당 약 $1로 Standard의 수십 분의 1입니다. 5분 이내 고빈도 파이프라인이면 Standard가 아니라 Express가 정답입니다.
- 큐 사이 단계가 3개를 넘으면 코레오그래피의 단순함이 유지보수 비용으로 역전되는 신호입니다.
- 실무 정답은 병용입니다. 큐로 평준화하고 상태 머신으로 지휘하며, 본류와 부수 작업을 분리합니다.