큐와 비동기 API · 큐가 필요한 순간 · 이론
큐는 시간을 사는 도구다
한 줄 요약
큐는 처리 속도를 높이지 않는다. 요청을 받는 속도와 처리하는 속도를 분리해서, 순간의 폭주를 시간으로 흡수한다.
왜 이게 필요했나
이미지 업로드 API 가 있다고 합시다. 원본을 저장하고, 썸네일 세 개를 만들고, 메타데이터를 추출하고, 검색 색인에 넣습니다. 전부 동기로 하면 응답이 4초 걸립니다. 평소에는 견딜 만합니다. 그런데 프로모션 날 업로드가 열 배로 늘면, 4초짜리 요청이 열 배 쌓이면서 워커 스레드가 전부 묶이고 헬스체크까지 실패합니다.
큐를 넣으면 API 는 원본만 저장하고 "접수했다"고 답합니다. 200ms 입니다. 나머지는 워커가 자기 속도로 처리합니다. 폭주가 와도 API 는 계속 200ms 로 답하고, 큐 깊이만 늘어납니다. 늘어난 깊이는 처리 지연이 됩니다 — 4초 걸리던 것이 3분 걸릴 수 있습니다. 대신 시스템은 죽지 않습니다.
이 교환이 큐의 전부입니다. 지연을 받아들이고 가용성을 삽니다.
어떻게 동작하나
큐를 쓸 만한 조건은 셋입니다. 첫째, 작업이 즉시 끝나지 않아도 되는가. 둘째, 요청 속도가 처리 속도보다 순간적으로 빠를 수 있는가. 셋째, 실패했을 때 나중에 다시 해도 되는가. 셋 다 예이면 큐가 맞습니다.
반대로 큐를 넣지 말아야 할 경우도 분명합니다. 사용자가 결과를 즉시 봐야 하는 조회, 그리고 평균 유입이 평균 처리 능력보다 큰 경우입니다. 후자를 오해하는 사람이 많습니다. 큐는 버스트를 흡수하지만 만성 과부하는 해결하지 못합니다. 유입률이 처리율보다 계속 크면 큐는 무한히 자라다가 메모리나 디스크를 다 먹고 터집니다. 큐는 λ < μ 일 때만 안정합니다. 이 부등식이 성립하지 않으면 필요한 것은 큐가 아니라 워커 증설이거나 유입 제한입니다.
현장에서 만나는 모습
큐를 넣고 나면 새로운 운영 지표가 생깁니다. 큐 깊이와 소비자 지연(consumer lag)입니다. 이 둘을 대시보드에 올리지 않으면 큐는 조용한 블랙홀이 됩니다. 사용자는 "업로드했는데 안 나와요"라고 신고하고, API 대시보드는 전부 초록색입니다. 문제는 API 뒤에 쌓여 있습니다.
그리고 큐를 넣으면 사용자 경험 설계가 함께 필요해집니다. "접수됨" 상태를 어떻게 보여 줄지, 얼마나 기다리면 되는지, 실패하면 어떻게 알릴지. 이걸 정하지 않고 큐만 넣으면 사용자는 그냥 사라진 요청을 봅니다.
다음 퀴즈에서 확인할 것
이 모듈은 개념만 다룹니다. 다음 모듈부터 Redis 리스트와 스트림으로 큐를 직접 만들고, 순서·중복·유실이 어디서 생기는지 하나씩 재현합니다.