서비스 운영 ·
오래 걸리는 작업을 대기열과 백그라운드로 나누는 법
먼저 답부터
오래 걸리는 작업은 사용자 요청 안에서 끝까지 기다리게 하지 말고 작업 내용과 식별자를 대기열에 저장한 뒤 별도 작업자가 처리하도록 나눕니다. 화면에는 접수 번호와 현재 상태를 보여 주고, 작업자는 재시도 횟수와 중복 방지와 실패 보관함을 갖춰 결과가 사라지거나 두 번 생기지 않게 해야 합니다.
사용자가 영상을 올렸는데 변환이 끝날 때까지 화면이 멈춰 있으면 새로고침하거나 버튼을 다시 누르기 쉽습니다. 서버도 연결을 오래 붙잡고 있어 다른 요청을 받기 어려워질 수 있습니다. 오래 걸리는 일은 먼저 접수하고 뒤에서 처리하는 구조가 필요합니다.
병원 접수대와 검사실을 떠올려 보세요. 접수대가 검사까지 직접 끝내느라 다음 사람을 세워 두지 않습니다. 이름과 검사 종류를 기록하고 번호표를 준 뒤 검사실이 차례로 부릅니다. 웹서비스의 대기열과 백그라운드 작업도 같은 역할 분담입니다.
백그라운드 작업은 화면 요청과 떨어져 실행되는 일이다
background job은 사용자의 화면 요청이 끝난 뒤에도 서버 쪽에서 이어서 처리하는 작업입니다. 영상 변환, 큰 보고서 생성, 여러 명에게 메일 보내기, 외부 자료 동기화처럼 몇 초 이상 걸리거나 실패 시 다시 시도해야 하는 일에 자주 씁니다.
모든 일을 뒤로 보낼 필요는 없습니다. 로그인 확인이나 장바구니 수량 변경처럼 사용자가 즉시 결과를 알아야 하는 짧은 작업은 요청 안에서 처리하는 편이 단순합니다. 오래 걸리는 시간, 외부 서비스 의존, 재시도 필요성, 동시 요청 수를 보고 나눕니다.
대기열은 처리할 작업을 잠시 보관하는 번호표 줄이다
queue는 먼저 들어온 작업이나 우선순위가 높은 작업을 작업자가 가져갈 때까지 보관하는 대기열입니다. 작업을 만든 쪽은 producer, 즉 생산자이고 실제로 가져가 실행하는 쪽은 consumer 또는 worker, 즉 소비자나 작업자입니다.
AWS SQS 공식 문서는 생산자와 소비자 사이에 대기열을 두면 두 구성 요소를 느슨하게 분리할 수 있다고 설명합니다. 작업자가 잠시 느려져도 접수된 메시지가 대기열에 남아 있다면 화면 서버가 같은 속도로 멈출 필요가 없습니다.
{
"jobId": "job_42",
"type": "resize_image",
"fileId": "file_7",
"requestedAt": "2026-09-11T04:40:00+09:00"
}
메시지에는 작업에 필요한 식별자만 넣고 큰 파일 자체나 비밀키를 넣지 않습니다. 작업자는 fileId로 접근 권한을 다시 확인한 뒤 저장소에서 파일을 읽습니다.
화면에는 완료 약속 대신 현재 상태를 보여 준다
접수 직후 서버는 작업 ID와 접수 상태를 돌려줄 수 있습니다. 화면은 이 ID로 현재 상태를 조회하거나 완료 알림을 기다립니다. 아직 변환되지 않았는데 성공이라고 표시하지 않고 접수됨, 처리 중, 완료, 실패를 구분합니다.
- 접수됨은 대기열에 안전하게 들어갔다는 뜻입니다.
- 처리 중은 작업자가 가져가 실행하고 있다는 뜻입니다.
- 완료는 결과 파일이나 후속 기록이 저장됐다는 뜻입니다.
- 실패는 자동 재시도 뒤에도 끝내지 못한 상태입니다.
- 취소는 아직 실행하지 않았거나 안전하게 중단됐다는 뜻입니다.
진행률을 정확히 알 수 없다면 임의의 90퍼센트를 오래 보여 주지 않습니다. “대기 중”처럼 확인된 상태와 마지막 갱신 시각을 알려 주는 편이 낫습니다.
한 메시지가 다시 전달될 수 있다고 생각한다
분산된 대기열은 처리 중 연결이 끊기면 같은 작업을 다시 전달할 수 있습니다. AWS SQS 표준 대기열도 메시지가 한 번 이상 전달되거나 순서가 달라질 수 있으므로 애플리케이션이 이를 처리해야 한다고 안내합니다.
작업자는 jobId를 기준으로 이미 완료한 작업인지 확인합니다. 이미지 변환이라면 같은 출력 경로에 안전하게 저장하고, 메일이라면 발송 기록을 보고 중복을 막습니다. 결제와 삭제 작업은 일반 작업보다 더 엄격한 거래 기록과 상태 확인이 필요합니다.
실패 작업은 무한 반복하지 않고 따로 보관한다
일시 오류는 기다렸다가 재시도할 수 있지만 손상된 파일이나 없는 권한은 반복해도 해결되지 않습니다. 최대 시도 횟수를 넘긴 메시지는 dead-letter queue, 즉 계속 실패한 작업을 따로 모으는 보관함으로 옮길 수 있습니다.
대기 → 작업자가 가져감 → 성공하면 완료 기록
↘ 실패하면 제한 횟수만 재시도
↘ 계속 실패하면 실패 보관함
실패 보관함은 버리는 곳이 아닙니다. 오류 이유, 작업 ID, 마지막 시도 시각을 보고 원인을 고친 뒤 일부만 다시 처리합니다. 한꺼번에 모두 재전송하면 같은 장애와 비용을 다시 만들 수 있습니다.
처리 속도와 비용에는 상한을 둔다
대기열이 있다고 서버 용량이 무한해지는 것은 아닙니다. 작업자 수를 급격히 늘리면 데이터베이스와 외부 API가 동시에 몰릴 수 있습니다. 반대로 작업자가 너무 적으면 기다리는 시간이 길어집니다. 대기 작업 수, 가장 오래 기다린 시간, 성공률, 실패 보관함 크기를 함께 봅니다.
사용자가 큰 파일을 무제한 올리지 못하게 크기와 형식, 계정별 동시 작업 수를 서버에서 검사합니다. 비용이 드는 AI나 영상 작업에는 월 예산과 사용자별 상한도 둡니다. 화면 제한만 두면 직접 요청으로 우회될 수 있습니다.
오늘 바로 해볼 작은 실습
코드를 실행하지 않고 오래 걸리는 기능 하나를 작업 카드로 나눕니다.
- 영상 변환이나 보고서 생성처럼 오래 걸리는 기능을 고릅니다.
- 화면에서 즉시 확인할 값과 뒤에서 처리할 값을 나눕니다.
- 작업 ID, 종류, 대상 ID, 요청 시각 네 칸을 적습니다.
- 접수됨부터 실패까지 상태 문장을 만듭니다.
- 같은 작업이 두 번 왔을 때 확인할 완료 기록을 적습니다.
- 최대 재시도 뒤 실패 보관함에서 볼 항목을 정합니다.
모르는 대기열 삭제나 purge 명령은 실행하지 마세요. purge는 대기 중인 작업을 한꺼번에 비우는 동작이라 복구가 어려울 수 있습니다. 메시지에 비밀키와 개인정보 원문을 넣지 않고, 결제·메일·삭제 작업은 중복 방지와 복구 절차를 설명할 수 있을 때만 자동 처리합니다.
확인한 자료
- What is Amazon Simple Queue Service — Amazon Web Services
- Amazon SQS standard queues — Amazon Web Services
함께 읽기
- 오류와 로그를 진료 기록처럼 읽고 원인을 좁히는 순서
디버깅은 오류 문장을 지우는 일이 아니라 같은 문제를 다시 만들 수 있는 조건을 기록하고 첫 실패 지점을 찾는 과정입니다. 화면 증상, 입력, 시간, 파일과 줄 번호, 기대 결과를 분리해 적은 뒤 한 번에 한 가지만 바꾸면 로그의 결과와 실제 원인을 혼동할 가능성이 줄어듭니다.
- 저장과 빌드와 배포를 포장 배송 공개처럼 구분하기
저장은 작업 파일을 남기는 일, 빌드는 소스 코드를 서비스용 결과물로 만드는 일, 배포는 그 결과물을 서버에 올리는 일입니다. 배포 성공 표시만으로 실제 공개 주소가 새 결과물을 제공한다고 단정할 수 없으므로 도메인, 번들, 핵심 기능과 메타데이터를 공개 환경에서 다시 확인해야 합니다.
- GitHub Actions로 커밋마다 테스트가 도는 흐름 이해하기
GitHub Actions의 CI는 push나 pull request 같은 사건이 생기면 별도 실행 컴퓨터인 러너에서 설치와 테스트 단계를 자동 수행하는 방식입니다. 워크플로 파일의 실행 조건, 권한, 비밀값 사용, 통과한 정확한 커밋을 확인해야 하며 초록 표시가 실제 배포나 모든 기능의 정상 동작까지 보장하지는 않습니다.