백그라운드 작업
규칙
- 느린 작업은 백그라운드 작업으로 오프로드: 이메일, 이미지 처리, 웹훅, 보고서, AI 호출
- BullMQ는 자체 호스팅 Redis 큐에 사용 — Inngest 또는 Trigger.dev는 서버리스/관리형 환경
- 모든 작업은 멱등성을 가져야 함 — 재시도 시 부작용 없이 안전하게 처리 (멱등성 키 사용)
- 지수 백오프를 사용하여 재시도: 3-5회 시도, 지연 시간 1초, 10초, 60초, 5분
- 데드 레터 큐(DLQ): 최대 재시도 후 DLQ로 이동하여 조사 — 절대 자동으로 삭제하지 않음
- 큐별 동시성 제한 설정 — 워커 과부하 방지 (예:
concurrency: 5)
- 작업 페이로드는 작게 유지: 전체 객체 대신 ID와 참조 전달
- 큐를 우선순위별로 분리:
critical (결제), default (이메일), low (분석)
- 큐 깊이 및 처리 시간 모니터링 — 큐가 쌓이면 알림 전송
패턴
import { Queue, Worker } from "bullmq";
const queue = new Queue("이메일", { connection: redis });
await queue.add("환영", { userId }, {
attempts: 3,
backoff: { type: "exponential", delay: 1000 },
});
const worker = new Worker("이메일", async (job) => {
await sendWelcomeEmail(job.data.userId);
}, { connection: redis, concurrency: 5 });
import { inngest } from "./client";
export const sendEmail = inngest.createFunction(
{ id: "send-welcome-email", retries: 3 },
{ event: "user/created" },
async ({ event }) => { await sendWelcomeEmail(event.data.userId); }
);
피해야 할 사항
- API 요청 핸들러에서 느린 작업 처리 — 빠르게 응답하고 백그라운드에서 처리
- 멱등성이 없는 작업 — 중복 실행 시 이중 청구, 이중 이메일 발생
- 무제한 동시성 — 데이터베이스 연결과 메모리를 고갈시킴
- 작업 큐에 큰 페이로드 저장 — 대신 참조 전달