본문으로 건너뛰기

© 2026 Molayo

Qiita헤드라인2026. 06. 24. 23:44

Ralph Loop를 사용하여 AWS Step Functions를 「자율적으로 수정하여 끝까지 통과시키기」

요약

Ralph Loop를 활용하여 AWS Step Functions의 버그를 AI 에이전트가 자율적으로 수정하고 배포까지 완료하는 루프 엔지니어링 기법을 소개합니다. 로컬 검증 게이트, 실패 이력 계승, 근본 원인 수정 규율을 통해 AI의 무책임한 종료를 방지하고 성공적인 배포를 보장합니다.

핵심 포인트

  • Ralph Loop를 이용한 AI의 자율적 코드 수정 및 배포 자동화
  • 로컬 검증 통과 시에만 AWS 배포를 허용하는 '로컬 GREEN 게이트' 전략
  • 실패 이력을 기록하여 다음 이터레이션에 전달하는 메모리 계승 방식
  • 임시방편이 아닌 근본 원인을 수정하도록 강제하는 프롬프트 규율

갑작스럽지만 여러분, Step Functions의 통신 테스트는 어떻게 하고 계신가요?

저는 「수정 → 배포 → 실패 → 로그 분석 → 다시 수정」의 시행착오(Trial and Error)를 반복합니다.

그 작업은 꽤 고행이죠. 그래서 최근 부쩍 자주 들리는 루프 엔지니어링 (Loop Engineering) 에 모든 것을 맡겨 보았습니다.

**Ralph Loop (자기 수정 루프)**1에, 일부러 버그를 심어둔 Step Functions를 전달합니다 - AI가 자율적으로·단계적으로 버그를 수정하여 「
로컬 GREEN → AWS 배포 → 실행 SUCCEEDED」까지 통과시킵니다.

그리고 단순히 무턱대고 루프를 돌린다고 해서 수렴하지는 않습니다. AI는 내버려 두면 "아까와 똑같은 수정 방식"을 아무렇지 않게 다시 시도하곤 하거든요...(진심입니다)

자율적으로 제대로 수렴시키기 위한 열쇠는 이 3가지입니다.

로컬 GREEN 게이트… 로컬이 통과할 때까지 AWS로 진행시키지 않음 -
**ERROR_DETAIL.md**를 통한 실패·시도 이력의 이터레이션(Iteration) 간 계승 -
근본 원인을 수정하는 규율… 증상에 대한 임시방편적 수정을 금지함

이 「게이트·기억·규율」 3종 세트가 효과적이지만, 그 내용은 잠시 후에 설명하겠습니다.

간단히 말하면 「에이전트가 종료하려고 하면, 동일한 프롬프트를 다시 한 번 집어넣는」 방식으로 자기 수정을 끊임없이 돌리는 수법입니다 (Claude Code의 플러그인입니다).

메커니즘은 다음과 같습니다.

/ralph-loop "<프롬프트>" --max-iterations N --completion-promise DONE

으로 기동 - 에이전트가 턴을 마치려고 하면
Stop 후크2가 발화하여, 동일한 프롬프트를 재주입 - 에이전트가
<promise>DONE</promise>

를 출력하거나, max-iterations에 도달하면 종료

포인트는 **「완료 조건이 정말로 참(True)이 될 때까지, 거짓말을 하고 빠져나가면 안 된다」**는 규칙입니다. 이 부분이 은근히 중요합니다.

AI는 "이제 다 고쳤습니다! (사실 안 고침)" 같은 분위기를 풍기며 돌아가려 할 때가 있기 때문에, 제대로 멱살을 잡고 있어야 합니다. 이번 완료 조건은 "AWS 실행이 SUCCEEDED가 되면 <promise>DONE</promise>"입니다. 이 외의 상황에서는 절대로 보내주지 않습니다. 스파르타식이죠.

각 이터레이션에서 루프는 이 플로우를 뱅글뱅글 돕니다. 로컬이 통과할 때까지 AWS로는 진행시키지 않는 것이 핵심입니다.

AWS에 배포할 때마다 시간과 비용이 조금씩 소모됩니다. 저렴한 로컬에서 실패를 흡수하도록 하자는 전략입니다.

④의 "로컬 GREEN 게이트"가 이번의 주인공입니다. 로컬이 SUCCEEDED가 되지 않는 한, AWS로는 한 발짝도 나아가지 못하게 합니다. RED/FAILED는 전부 ERROR_DETAIL.md에 기록되어, Stop 후크의 재주입을 통해 다음 이터레이션으로 계승됩니다.

수정 대상인 스테이트 머신(State Machine)은 Lambda를 2개 직렬로 호출하는 초미니멀 구성입니다.

구성 방식은 AWS SAM (Lambda × 2 + StateMachine을 template.yaml로 정의)입니다. 로컬 검증은 Step Functions Local + sam local, 운영은 sam deploy를 사용합니다.

루프가 「단계적으로」 수정해 나가는 모습을 보고 싶어서, 성질이 다른 버그를 각 Lambda에 하나씩 심어두었습니다. # BUG와 같은 친절한 스포일러 주석은 없습니다.

파일버그 (수정 전)정답실패 방식
버그 Afunctions/first/app.pyresult = value + "1"value + 1
버그 Bfunctions/second/app.pyreturn {"status": "ng", ...}"status": "ok"

버그 A는 「타입을 틀려서 떨어지는」 아주 고전적인 버그이고, 버그 B는 「처리는 통과하지만 내용이 틀려서 워크플로우가 실패 판정되는」 유형입니다. 서로 다른 타입의 버그를 배치함으로써, AI가 하나씩 순서대로 해결해 나갈 수 있는지 확인하고 싶었습니다.

자, 이제 여기가 이번에 가장 전달하고 싶은 부분입니다.

AI는 단순히 루프를 돌리기만 해서는 수렴하지 않습니다.

똑같은 수정을 끝없이 반복하거나, 증상만을 임시방편으로 건드리고 근본 원인은 방치하는 식으로 말이죠…. 따라서 기억과 규율을 심어줄 필요가 있습니다.

AI에게는 기억이 없으므로, 외장 메모장을 들려줍니다. 3개 섹션으로 구성되며, 매 이터레이션 (Iteration)의 도입부에 반드시 읽게 합니다.

현재 상태 (매번 덮어쓰기): iteration / phase / status / failed_state / error_type / root_cause / attempted_fix / next_hypothesis -
금지 리스트: 「실패 스테이트 + 에러 유형 + 시도한 수정」이 재등장하면 추가하여, 두 번 다시 같은 수를 두지 않게 함 (=같은 실수를 반복하지 않기 위한 반성 노트) -
시도 이력 (추가만 가능 · 절대 삭제 금지): 각 이터레이션의 기록

"아, 그거 아까 해서 안 됐던 거다"라는 것을 제대로 파일에 새겨두는 이미지입니다.

같은 수정을 2번 반복하지 말 것 / 수정 전에 반드시 가설을 1개 작성할 것 / next_hypothesis는 이전과 다르게 작성할 것 / 로컬이 RED인 상태로 AWS로 진행하지 말 것 / 1 이터레이션에서는 관측된 실패가 나타내는 부분만 최소한으로 수정할 것 / 증상이 아니라 근본 원인을 고칠 것 / 에러를 마스킹(Masking)하지 말 것

요컨대 "서두르지 마라 · 거짓말하지 마라 · 저번과 똑같은 짓 하지 마라"를 끊임없이 프롬프트로 타이르고 있는 느낌입니다.

실제로 실행한 로그가 여기 있습니다.

ERROR_DETAIL.md (전문)

운영 규칙: 매 이터레이션 도입부에 이 파일을 읽는다. 시도 이력에 동일한 「실패 스테이트 명 + 에러 유형 + 시도한 수정」이 이미 존재한다면, 해당 수정은 금지 리스트로 취급하여 다른 가설을 세운다. next_hypothesis는 반드시 이전과 다르게 작성한다.

  • iteration: 3
  • phase: AWS
  • status: GREEN ✅
  • failed_state: - (없음)
  • error_type: - (없음)
  • root_cause: - (bug A / bug B 모두 해소됨)
  • attempted_fix: - (추가 수정 없음)
  • next_hypothesis: - (완료. AWS 실행이 SUCCEEDED에 도달)

(없음. 각 버그는 1회의 수정으로 해소되었으므로 재시도 없음)

  • failed_state: FirstTask

  • error_type: TypeError ("unsupported operand type(s) for +: 'int' and 'str'")

  • root_cause: functions/first/app.py:4
    result = value + "1"
    (int에 str을 가산) - attempted_fix:
    value + "1"
    value + 1

  • result: 수정 적용 완료. iteration-2의 run-local에서 FirstTask가 {"value": 2, "step1": "done"}를 정상 출력하는 것을 확인 → 해소

  • failed_state: CheckResult → FailState

  • error_type: UnexpectedStatus ("$.status was not 'ok'")

  • root_cause: functions/second/app.py:4
    return {"status": "ng", ...}
    (Choice가 "ok"를 요구) - attempted_fix:
    "status": "ng"
    "status": "ok"

  • result: 수정 적용 완료. iteration-3의 run-local에서 해소 확인 → 해소

  • 로컬 실행: SUCCEEDED (LOCAL GREEN)

  • AWS 배포: sam deploy로 스택 aituber-char-sfn 생성 성공 (FirstFunction / SecondFunction / StateMachine + IAM Roles)

  • AWS 실행: executionArn ...StateMachine-qPLIvdGm96Wl:032a8f6d-... → status SUCCEEDED (AWS GREEN)

  • result: 완료. <promise>DONE</promise>를 출력하고 루프 종료

【발췌판】

Iter페이즈관측된 실패근본 원인수정결과
1LOCALFirstTask에서 TypeErrorfirst/app.py value + "1"value + 1버그 A 해결
2LOCALCheckResultFailState : $.status was not 'ok'second/app.py "status": "ng""ok"버그 B 해결
3LOCAL→AWS없음로컬 GREEN → AWS 배포 → 실행 SUCCEEDED

이번 "움직임"을 도식화하면, 실패 지점이 한 단계씩 전진하며 수렴해 가는 것을 볼 수 있어 꽤 쾌감이 느껴집니다.

▶ iteration-1: 로컬 실행 이력 (전체 / 타임스탬프, inputDetails 등은 생략)

{
"events": [
{ "id": 1, "type": "ExecutionStarted",
...

▶ iteration-2: 로컬 실행 이력 (전체 / 타임스탬프, inputDetails 등은 생략)

{
"events": [
{ "id": 1, "type": "ExecutionStarted",
...

▶ iteration-3: 로컬 GREEN 확인

=== [8/8] 실행 완료 대기 중 ===
[1] status: RUNNING
[2] status: SUCCEEDED
...

▶ iteration-3: sam deploy 로그 (CloudFormation, AWS 계정 ID는 마스킹)

=== [2/4] sam deploy ===
Deploying with following values
===============================
...

▶ iteration-3: AWS 워크플로 실행 (SUCCEEDED)

=== [4/4] AWS 워크플로 실행 ===
executionArn: arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:execution:StateMachine-qPLIvdGm96Wl:032a8f6d-...
실행 완료 대기 중...
...

일부러 버그를 2개 심어둔 Step Functions를 Ralph Loop에 전달했더니, 3번의 이터레이션(iteration) 만에 단계적으로 버그를 잡아내어, AWS 실행 SUCCEEDED까지 자율적으로 도달해 주었습니다. 자신의 실수를 AI에게 통째로 맡기는 시대가 왔군요.

여기서 가장 전달하고 싶은 것은 "AI 대단하다"라는 단순한 감상이 아니라, 자기 수정 루프를 "그저 돌리는 것"이 아니라 설계에 포함시킨 3가지 규칙의 중요성입니다.

「게이트·기억·규율」의 3종 세트

  • 로컬 GREEN 게이트… 실패는 비용이 저렴한 로컬에서 흡수. AWS에는 GREEN 상태가 된 후에만 진행시킨다 (비용 및 시간 절약)
  • ERROR_DETAIL.md… 상태와 시도 이력을 계승하여 동일한 실패의 반복을 방지한다 (AI의 외장 반성 노트)
  • 근본 원인을 고치는 규율… 증상에 대한 임시방편적 수정을 금지하고, 상류(upstream)의 코드를 수정하게 한다

AI를 자율 주행시키고 싶다면, 능력에 기대기보다 환경(가드레일)을 정비하는 것이 더 효과적이라는 뜻이겠네요.

조금이라도 참고가 되셨기를 바랍니다.

'좋아요'를 눌러주시면 눈물을 흘리며 기뻐하겠습니다! 끝까지 읽어주셔서 감사합니다 🙌

AI 자동 생성 콘텐츠

본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0