76일차 회고|Retry·DLQ·장애 복구와 n8n 운영 자동화|AI 오케스트레이션 개발자 국비지원

AI 오케스트레이션 캠프/일차별 회고 2026. 10. 31. 20:03
728x90

오늘 배운 내용

오늘은 AI 워크플로우에서 발생하는 오류를 어떻게 처리하고, 실패한 작업을 안전하게 복구할 것인가를 중심으로 학습했다.

지금까지는 n8n으로 워크플로우를 연결하고 LLM과 API를 호출하는 방법에 집중했다면, 오늘은 그 과정에서 문제가 발생했을 때 어떻게 대응해야 하는지를 살펴봤다.

수업은 HTTP 오류와 재시도(Retry)에서 시작해 멱등성(Idempotency), DLQ(Dead Letter Queue), Error Workflow, 장애 알림, 재처리(Redrive), 운영 상태 모니터링으로 이어졌다.

후반부에는 n8n 밖에서도 재시도를 활용할 수 있는 CLI 도구 개발 과제가 소개되었고, 팀 프로젝트를 위한 서버 환경과 AI 바이브 코딩 활용 사례도 살펴봤다.

오늘 수업에서 가장 중요한 주제는 프로그램이 정상적으로 실행되는 것뿐 아니라, 실패했을 때 어떻게 복구할 것인지까지 설계해야 한다는 것이었다.


1. HTTP 오류와 재시도(Retry)

HTTP 상태 코드에 따라 대응 방법이 달라진다

API를 호출하면 서버는 요청 처리 결과를 HTTP 상태 코드로 알려준다.

대표적인 오류 코드는 다음과 같다.

상태 코드의미일반적인 대응
400 잘못된 요청 입력값 수정
401 인증 실패 인증 정보 확인
403 접근 권한 없음 권한 확인
404 요청한 리소스 없음 URL 또는 리소스 확인
429 요청 횟수 제한 일정 시간 대기 후 재시도
500 서버 내부 오류 원인 확인 후 필요시 재시도

중요한 점은 모든 오류를 재시도한다고 해결할 수 있는 것은 아니라는 것이다.

예를 들어 필수 입력값이 누락되어 발생한 400 오류는 같은 요청을 여러 번 보내도 해결되지 않는다. 반면 일시적인 서버 장애나 요청 횟수 제한은 잠시 기다린 후 다시 요청하면 성공할 수 있다.

이를 기준으로 오류를 크게 두 종류로 구분했다.

  • 일시적 오류(Transient Error): 시간이 지나면 해결될 가능성이 있는 오류
  • 영구적 오류(Permanent Error): 요청이나 설정을 수정하지 않으면 반복되는 오류

Exponential Backoff와 Jitter

재시도할 때도 주의해야 한다.

오류가 발생하자마자 계속 요청을 보내면 장애가 발생한 서버에 더 큰 부담을 줄 수 있다.

이를 방지하기 위해 Exponential Backoff와 Jitter를 사용한다.

Exponential Backoff는 재시도할 때마다 대기 시간을 점점 늘리는 방법이다.

예를 들어 다음과 같이 기다릴 수 있다.

첫 번째 실패 → 1초 대기
두 번째 실패 → 2초 대기
세 번째 실패 → 4초 대기
네 번째 실패 → 8초 대기

Jitter는 대기 시간에 무작위 값을 추가하는 방법이다.

여러 사용자가 동시에 오류를 경험했을 때 모두 같은 순간에 재시도하는 현상을 줄일 수 있다.

n8n에서는 Retry On Fail, Max Tries, Wait Between Tries 같은 설정을 통해 재시도를 구성할 수 있다는 점도 학습했다.


2. Timeout과 멱등성(Idempotency)

Timeout이 발생했다고 요청이 실패한 것은 아니다

오늘 배운 내용 중 특히 중요한 개념은 Timeout이었다.

Timeout은 정해진 시간 안에 응답을 받지 못한 상황이다.

그런데 응답을 받지 못했다고 해서 서버가 요청을 처리하지 않았다고 단정할 수는 없다.

예를 들어 쇼핑몰에서 결제 요청을 보냈다고 가정해 보자.

  1. 사용자가 결제를 요청한다.
  2. 서버에서 실제 결제가 완료된다.
  3. 네트워크 문제로 성공 응답이 전달되지 않는다.
  4. 사용자는 결제가 실패했다고 생각하고 다시 요청한다.

이 경우 동일한 결제가 두 번 처리될 위험이 있다.

따라서 Timeout이 발생했을 때는 단순히 다시 실행하기보다 이미 처리된 요청인지 확인하는 구조가 필요하다.

멱등성이란?

멱등성(Idempotency)은 같은 작업을 여러 번 실행하더라도 최종 결과가 한 번 실행했을 때와 같도록 하는 성질이다.

API에서 자주 사용하는 방법 중 하나는 멱등성 키(Idempotency Key)를 전달하는 것이다.

POST /tickets
Idempotency-Key: request-001

서버는 동일한 키를 가진 요청이 이미 처리되었는지 확인하고 중복 실행을 방지할 수 있다.

재시도할 때는 새로운 키를 만들지 않고 원래 요청과 동일한 키를 유지해야 한다.

이 개념은 티켓 생성뿐 아니라 쇼핑몰 주문, 결제, 대량 이체처럼 중복 실행이 위험한 업무에서도 중요하다.


3. n8n에서 오류 처리와 부분 성공 구현하기

일부 요청만 실패하는 상황

수업에서는 고객 문의를 티켓으로 등록하는 Intake 워크플로우를 예제로 사용했다.

여러 요청을 한 번에 처리할 때는 일부만 성공하고 나머지는 실패할 수 있다.

강사 시연에서는 첫 번째 배치의 티켓 3건이 성공했고, 두 번째 배치에서는 text 값이 비어 있는 요청이 포함되어 2건만 성공했다.

이 과정에서 일부 요청이 성공했음에도 전체 HTTP 응답이 500으로 나타나는 상황을 확인했다.

즉, 전체 요청이 실패했다는 응답과 실제 데이터 저장 결과가 일치하지 않을 수 있다는 것이다.

이후 멱등성 처리가 없는 상태에서 첫 번째 배치를 다시 실행하자 티켓이 중복 생성되어 총 8건이 저장되는 상황도 확인했다.

이 실습은 부분 성공과 멱등성의 필요성을 보여주는 사례였다.

My Intake 워크플로우 개선

강사는 기존 Intake를 복사한 My Intake 워크플로우를 수정하면서 입력값 검증과 오류 대응을 추가했다.

주요 검증 대상은 다음과 같았다.

  • id: 요청 식별자
  • user: 요청한 사용자
  • text: 고객 문의 내용

필수값이 없는 요청은 LLM이나 외부 API를 호출하기 전에 rejected 상태로 분리했다.

또한 티켓 API 호출에 Timeout과 최대 재시도 횟수를 설정하고, 동일한 요청 ID를 멱등성 키로 활용하도록 구성했다.

LLM 호출이 실패했을 때는 전체 처리를 중단하는 대신 다음과 같은 기본값을 사용하는 Graceful Degradation도 다뤘다.

{
  "category": "미분류",
  "priority": "보통"
}

Graceful Degradation은 일부 기능에 문제가 발생하더라도 가능한 범위에서 서비스를 계속 제공하는 방식이다.

다만 모든 오류를 기본값으로 감추면 안 되므로, 실패 사실은 별도로 기록하고 확인할 수 있어야 한다.


4. DLQ(Dead Letter Queue)로 실패한 요청 보관하기

DLQ란?

DLQ는 정상적으로 처리하지 못한 메시지나 요청을 나중에 확인하고 재처리할 수 있도록 보관하는 공간이다.

택배 배송에 실패한 물건을 바로 버리지 않고 별도 보관소에 두는 것과 비슷하다.

고객 문의 접수
      ↓
입력값 검증
      ↓
티켓 생성 API 호출
      ↓
   성공 / 실패
      ↓
실패한 요청 → DLQ 보관

DLQ가 필요한 이유는 간단하다.

실패한 요청을 잃어버리지 않고 나중에 복구하기 위해서다.

Send to DLQ 구성

강사는 My Intake에서 티켓 생성이 실패한 요청을 DLQ에 저장하는 과정을 시연했다.

기존에는 실패한 요청이 결과에만 표시되고 실제 DLQ에는 남지 않는 문제가 있었다.

이를 개선하기 위해 실패한 요청의 ID, 사용자, 문의 내용, 워크플로우 출처 등을 DLQ로 전달하도록 구성했다.

이후 테스트에서는 실패한 요청 2건이 DLQ에 저장되는 결과를 확인했다.

여기서 중요한 점은 입력값이 잘못된 rejected 요청과 시스템 장애로 실패한 요청을 구분하는 것이다.

입력값을 수정해야 하는 요청까지 무조건 DLQ에 넣고 재시도하는 것은 적절하지 않다.


5. Error Workflow와 장애 알림 설계

예상한 오류와 예상하지 못한 오류

오류는 크게 두 가지로 구분할 수 있다.

  • Handled Error: 미리 예상하고 처리 방법을 준비한 오류
  • Unhandled Error: 준비한 처리 경로 밖에서 발생한 예상하지 못한 오류

예를 들어 필수 입력값이 비어 있으면 거절하도록 만든 것은 Handled Error에 해당한다.

반면 워크플로우 설정이 잘못되거나 예상하지 못한 데이터 구조 때문에 실행 자체가 중단된다면 Unhandled Error가 될 수 있다.

n8n에서는 Error Trigger를 사용하는 Error Workflow를 통해 이러한 실행 실패를 감지할 수 있다.

강사는 오류 발생 시 다음과 같은 정보를 남기는 구조를 설명했다.

  • 오류가 발생한 워크플로우
  • 실행 ID
  • 오류가 발생한 노드
  • 오류 메시지

다만 Error Workflow는 장애를 자동으로 해결하는 기능이 아니라 장애 발생 사실을 감지하고 알리는 마지막 안전장치에 가깝다.

DLQ 자체가 실패하면 어떻게 될까?

DLQ에 저장하는 API도 실패할 수 있다.

이 경우 원래 실패한 요청을 보관하지 못하기 때문에 요청이 유실될 위험이 있다.

수업에서는 DLQ 저장 결과를 확인하고, 저장에 실패하면 관련 요청 ID를 남기며 Critical 알림을 발생시키는 방법을 다뤘다.

알림 등급과 중복 알림 방지

모든 오류를 같은 긴급도로 알리면 담당자가 반복되는 알림에 익숙해져 중요한 장애를 놓칠 수 있다.

따라서 알림을 심각도에 따라 구분했다.

등급상황대응
Critical DLQ 저장 실패, 심각한 예상 밖 장애 즉시 확인
High 재시도 소진, DLQ 누적 담당자 확인
일반 기록 잘못된 입력값, 일부 기능의 대체 처리 기록 및 추후 분석

또한 같은 원인으로 발생한 High 알림은 일정 시간 동안 묶어서 전달하는 방법도 실습했다.

강사 시연에서는 최근 10분간의 알림을 조회해 중복 High 알림을 줄이는 기능을 구성했다.

중요한 것은 알림 개수만 줄이고 실제 오류 기록과 DLQ 데이터는 유지해야 한다는 점이다.


6. DLQ 재처리(Redrive)와 Parked 상태

실패한 요청을 다시 처리하기

DLQ에 요청을 저장했다고 해서 원래 업무가 완료된 것은 아니다.

장애 원인을 해결한 뒤 저장된 요청을 다시 처리해야 한다.

이를 Redrive 또는 Replay라고 한다.

강사는 재처리 전용으로 티켓 생성 로직을 새로 만드는 대신 기존 My Intake 워크플로우를 재사용하도록 설명했다.

이렇게 하면 입력 검증, 멱등성, API 호출 규칙을 동일하게 적용할 수 있다.

세 번 실패하면 Parked 상태로 전환

7교시에서는 Lab 3 Challenge 1을 통해 최대 시도 횟수 제한을 구현하는 과정을 살펴봤다.

재처리를 무한히 반복하면 시스템 자원과 비용이 낭비될 수 있기 때문이다.

강사는 최대 3회 시도 후에도 실패한 요청을 parked 상태로 전환하도록 수정했다.

DLQ 요청
   ↓
재처리 횟수 확인
   ↓
3회 미만 → 다시 처리
   ↓
최대 횟수 도달
   ↓
Parked 상태로 전환
   ↓
담당자 알림

parked는 요청을 삭제한다는 의미가 아니다.

자동 재처리를 중단하고 사람이 원인을 확인하도록 별도로 보관하는 상태다.

강사 시연에서는 수정 전 7개 중 3개만 통과했던 Challenge 1 테스트가 수정 후 7개 모두 통과했다.


7. Runbook과 장애 대응 훈련

Runbook이란?

Runbook은 장애가 발생했을 때 담당자가 따라야 할 절차를 정리한 운영 매뉴얼이다.

예를 들어 DLQ에 요청이 쌓였을 때 다음 내용을 확인하도록 작성할 수 있다.

  1. 어떤 장애가 발생했는가?
  2. 어떤 명령어와 화면에서 상태를 확인하는가?
  3. 정상 상태를 판단하는 기준은 무엇인가?
  4. 장애 원인을 어떻게 복구하는가?
  5. 언제 DLQ 재처리를 시작하는가?
  6. 재처리 후 어떤 결과를 검증하는가?

단순히 "서버를 확인한다"라고 적는 것이 아니라 구체적인 명령어와 판단 기준을 남겨야 한다.

강사는 Game Day와 Fire Drill처럼 의도적으로 장애 상황을 만들어 런북을 검증하는 훈련도 소개했다.

또한 장애 발생부터 감지까지의 평균 시간인 MTTD와 복구까지의 평균 시간인 MTTR을 통해 운영 품질을 확인할 수 있다고 설명했다.


8. My Ops Status로 운영 상태 확인하기

7교시의 두 번째 Challenge에서는 시스템 상태를 하나의 Webhook으로 확인하는 My Ops Status 워크플로우를 만들었다.

운영 담당자가 DLQ와 알림 기록을 각각 확인하지 않아도 현재 상태를 파악할 수 있도록 하는 기능이다.

상태는 세 가지로 구분했다.

상태조건
CRITICAL Parked 요청 또는 Critical 알림이 있음
WARNING DLQ 대기 요청 또는 최근 High 알림이 있음
OK 위 조건에 해당하지 않음

강사는 빨간불, 노란불, 초록불에 비유하여 설명했다.

여기서 중요한 점은 CRITICAL 조건을 먼저 확인해야 한다는 것이다.

예를 들어 DLQ에 요청이 남아 있으면서 Parked 요청도 있다면 WARNING이 아니라 CRITICAL로 판단해야 한다.

강사 시연에서는 My Ops Status 워크플로우를 추가한 뒤 Challenge 2 테스트도 7개 모두 통과했다.

이러한 상태 조회 기능은 나중에 운영 대시보드와 연결하여 시각적으로 표현할 수 있다.


9. n8n 밖에서도 사용할 수 있는 qretry CLI 과제

마지막 8교시에는 오늘 배운 재시도 개념을 n8n 외부로 확장하는 바이브 코딩 과제가 소개되었다.

n8n에서는 노드 설정으로 재시도를 구현할 수 있지만, 실제 운영 환경에는 셸 스크립트, curl 명령어, 백업 작업처럼 n8n 밖에서 실행되는 작업도 많다.

이러한 명령어가 한 번 실패했다고 바로 종료되지 않도록 범용 재시도 도구를 만드는 것이 과제의 목표였다.

강사가 소개한 요구사항은 다음과 같다.

  • 어느 폴더에서나 실행할 수 있는 CLI 도구
  • 실행할 명령어를 인자로 전달
  • 명령어 실행 결과 확인
  • 실패하면 지정한 횟수만큼 재시도

전사문상 도구 이름은 qretry로 들리지만 정확한 표기는 과제 원문 확인이 필요하다.

이번 수업에서는 요구사항이 소개되었으며, 실제 완성 코드나 테스트 결과는 확인되지 않았다.


10. 팀 프로젝트 서버 환경과 바이브 코딩 활용

n8n 서버 환경과 HTTPS

8교시에는 팀 프로젝트를 위한 서버 환경도 안내되었다.

팀원별로 개발한 기능을 팀 리더가 통합하고, 서버에서 실행한 뒤 외부 웹브라우저로 접근할 수 있도록 구성하는 방식이었다.

강사는 웹 애플리케이션용 포트와 n8n 접속용 포트를 구분하여 설명했다.

서버 접속 과정에서는 HTTP와 HTTPS 관련 문제도 확인했다.

HTTP는 기본적으로 통신 내용이 암호화되지 않지만, HTTPS는 TLS를 사용하여 통신을 암호화한다.

외부에서 서버에 접속할 때는 HTTPS뿐 아니라 인증 정보와 접근 권한도 함께 관리해야 한다.

특히 n8n Credential에 등록하는 API 키나 서버 접속 주소를 외부에 공개하지 않도록 주의해야 한다는 설명이 있었다.

AI로 실제 서비스를 만든 사례

수업 마지막에는 기존 Excel 업무 로직을 AI 코딩 도구로 앱으로 전환한 사례를 살펴봤다.

강사가 소개한 사례에서는 쇼핑몰의 광고 수익률, 원가, 고객 생애가치, 손익 계산 등을 Excel로 관리하던 사람이 이를 Shopify 앱으로 발전시켰다.

Cursor, Claude Code, Codex 같은 AI 코딩 도구를 활용했지만, AI가 작성한 계산이 정확한지는 기존 Excel 결과와 비교하며 검증했다고 설명했다.

이 사례에서 강사가 강조한 내용은 단순했다.

AI가 코드를 작성해 줄 수는 있지만, 무엇을 만들어야 하는지와 결과가 올바른지는 해당 문제를 이해하는 사람이 판단해야 한다는 것이다.


새롭게 이해한 점과 복습할 부분

이번 수업 내용을 정리하면서 오류 처리는 단순히 try-except를 추가하거나 재시도 횟수를 설정하는 문제가 아니라는 점을 연결해서 볼 수 있었다.

요청이 실패하면 먼저 오류의 종류를 판단해야 하고, 재시도가 가능한 상황이라면 중복 실행을 방지해야 한다. 그래도 실패하면 DLQ에 보관하고, 장애 알림을 전달하며, 원인이 해결된 뒤 다시 처리해야 한다.

또한 재처리 자체가 반복 실패하면 Parked 상태로 전환하고 사람이 확인할 수 있어야 한다.

즉, 오늘 학습한 개념은 다음과 같은 하나의 운영 흐름으로 이어진다.

오류 감지 → 오류 분류 → 재시도 → DLQ 보관 → 장애 알림 → 원인 복구 → 재처리 → 결과 검증

앞으로 복습할 내용은 다음과 같다.

  • Retry와 Exponential Backoff를 실제 코드에서 구현하는 방법
  • Timeout 발생 시 중복 처리를 막는 멱등성 키 설계
  • n8n의 Error Workflow와 DLQ 연결 구조
  • Replay 과정에서 재처리 횟수를 관리하는 방법
  • My Ops Status의 상태 판정 규칙
  • qretry와 같은 CLI 재시도 도구의 실제 구현 방법

특히 이번 수업에서 소개된 여러 워크플로우는 강사 시연을 중심으로 확인했기 때문에, 직접 구성하고 테스트하면서 각 노드의 역할을 다시 확인할 필요가 있다.


오늘의 회고

오늘은 AI 오케스트레이션에서 오류 처리와 안정적인 운영이 왜 중요한지 전체적인 흐름을 살펴본 시간이었다.

처음에는 HTTP 오류에 따라 재시도 여부를 결정하는 내용으로 시작했지만, 수업이 진행되면서 DLQ, Error Workflow, 알림, 재처리, 운영 상태 모니터링까지 연결되었다.

특히 실패한 요청을 다시 실행하는 것과 안전하게 복구하는 것은 다르다는 점이 중요한 내용이었다.

요청이 이미 처리되었을 가능성을 고려해야 하고, 반복 실패하는 작업을 무한히 실행해서도 안 된다. 실패한 요청을 보관하고 사람이 확인할 수 있는 상태까지 만드는 것이 운영 시스템의 역할이라는 설명이 인상적인 학습 주제였다.

마지막에 소개된 바이브 코딩 사례도 앞으로의 프로젝트를 생각할 때 참고할 만했다. AI 도구를 얼마나 잘 사용하는지도 중요하지만, 실제로 어떤 문제가 있고 그것을 해결하기 위해 어떤 기능이 필요한지 판단하는 능력이 필요하다는 내용이었다.

앞으로 AI 에이전트나 업무 자동화 서비스를 개발할 때는 정상적인 실행 결과뿐 아니라 실패 상황, 중복 처리, 복구 방법, 운영 상태까지 함께 설계하는 것을 목표로 복습해야겠다.

랩보다 AI 더 잘해지기

랩보다 AI 더 잘해지기

JASN OK / 제이슨 옥 RAPPER / Programmer

방명록