메시지 큐

Message Queue

도구

보낸 작업을 순서대로 쌓아 두었다가 처리할 수 있는 만큼씩 꺼내 가게 하는 서버 쪽 장치입니다.

등장 배경

사용자가 버튼을 누르면 서버가 그 자리에서 일을 끝내고 결과를 돌려주는 것이 기본 모양입니다. 요청을 받아 처리하고 응답을 내보내는 프로그램이 서버이고, 목록을 불러오거나 글을 저장하는 일처럼 0.1초 안에 끝나는 작업에서는 이 방식에 아무 문제가 없습니다.

무거운 작업이 끼어들면 그림이 달라집니다. 문서 300쪽을 파일로 내보내는 데 40초가 걸린다면 그 40초 동안 사용자는 빈 화면을 보고 있어야 하고, 브라우저는 보통 30초쯤 기다리다 스스로 연결을 끊습니다. 더 큰 문제는 몰릴 때입니다. 월요일 아침 9시에 내보내기 요청이 500건 들어오면 서버는 500개를 동시에 붙들고 메모리를 쓰다 쓰러집니다. 쓰러진 뒤에는 어느 요청이 끝났고 어느 요청이 안 끝났는지도 알 수 없어서, 사용자에게는 실패했다는 말조차 해 줄 수 없습니다.

서버를 열 대로 늘리는 답이 먼저 떠오르지만, 아침 9시만 넘기면 놀고 있을 아홉 대의 값을 매달 내야 합니다. 요청을 거절하는 답은 사용자가 곧바로 알아차립니다.

메시지 큐는 셋째 답입니다. 요청이 들어오면 처리하지 않고 목록에 적어 둔 뒤 곧바로 "접수했습니다" 를 돌려주고, 뒤에서 도는 프로그램이 그 목록에서 자기가 감당할 만큼만 꺼내 처리합니다. 들어오는 속도와 처리하는 속도를 끊어 놓는 것이 전부입니다. 아침 9시에 500건이 들어와도 줄이 길어질 뿐 서버는 평소와 같은 속도로 돕니다.

해결하는 문제

네 가지를 한 장치로 해결합니다.

  1. 응답이 오래 걸리는 문제입니다. 받아 적는 데는 0.01초면 충분하니 화면은 곧바로 다음으로 넘어가고, 다 되면 알림으로 알려 줍니다. 사용자가 기다리는 시간은 그대로여도 화면 앞에 붙잡혀 있지 않아도 됩니다.
  2. 몰릴 때 넘어지는 문제입니다. 초당 300건이 들어오고 서버가 초당 50건을 처리할 수 있다면 대기 줄이 초당 250건씩 길어집니다. 대신 서버는 쓰러지지 않고, 요청이 잦아드는 오전 11시쯤 줄이 저절로 줄어듭니다.
  3. 중간에 사라지는 문제입니다. 큐에 들어간 작업은 처리하는 쪽이 끝냈다고 알려 줄 때까지 지워지지 않습니다. 처리하던 프로그램이 도중에 죽으면 그 작업은 잠시 뒤 다시 꺼내집니다. 이 재시도 때문에 같은 작업이 두 번 실행될 수 있어서, 처리하는 쪽에는 같은 요청을 여러 번 받아도 결과가 같아지는 성질인 멱등성이 필요합니다. 메일 발송이라면 발송 기록을 먼저 남기고 이미 있으면 건너뛰는 식입니다.
  4. 두 시스템이 서로를 기다리는 문제입니다. 주문을 받는 쪽과 청구서를 만드는 쪽이 직접 연결돼 있으면 청구 쪽이 5분간 내려갈 때 주문도 함께 멈춥니다. 사이에 큐를 두면 주문은 계속 받아 두고, 청구 쪽이 돌아온 뒤 밀린 것을 차례로 처리합니다.

대안

큐를 쓰지 않고 같은 일을 하는 방법이 넷 있고, 작업의 무게와 건수에 따라 고릅니다.

  1. 그 자리에서 처리합니다. 1초 안에 끝나고 몰릴 일도 없는 작업이면 이쪽이 낫습니다. 큐를 하나 들이면 장치 자체를 운영해야 하고, 문제가 생겼을 때 들여다볼 곳이 한 군데 늘어납니다.
  2. 백그라운드 작업으로 돌립니다. 응답과 분리해 뒤에서 처리하는 작업을 말하는데, 큐 없이 서버 자기 안에서 굴릴 수도 있습니다. 코드가 단순한 대신 그 서버가 재시작되면 하던 일이 사라지고, 몰릴 때 조절해 줄 사람도 없습니다.
  3. 크론 잡에 맡깁니다. 정해진 시각마다 자동 실행되는 작업이라, 지금 당장 처리할 필요가 없고 모아서 한 번에 해도 되는 일에 맞습니다. 밤 12시에 하루치 사용량을 집계하는 일에 큐는 과합니다.
  4. 데이터베이스 표를 큐처럼 씁니다. 할 일을 행으로 넣어 두고 1분마다 꺼내 처리하는 방식입니다. 이미 있는 것으로 해결되고 내용을 눈으로 확인하기 쉬워서, 하루 수천 건까지는 이쪽으로 충분합니다.

옮겨 갈 때를 재는 기준은 셋입니다. 작업 하나가 몇 초 이상 걸리는가, 몰릴 때와 평소의 차이가 몇 배인가, 작업이 사라지면 사용자가 알아차리는가. 세 번째에 그렇다고 답한다면 건수가 적어도 큐 쪽이 안전합니다.

실무 용례

"이거 큐로 빼죠. 지금 응답에서 8초씩 기다리고 있어요."

화면이 멈춰 있는 시간을 없애자는 제안입니다.

"큐가 밀렸어요. 대기 12,000건이고 처리하는 쪽을 세 대로 늘리는 중입니다."

들어오는 속도가 처리 속도를 넘어섰고, 꺼내 가는 프로그램 수를 늘려 따라잡겠다는 뜻입니다.

"재시도가 돌면서 같은 메일이 두 번 갔어요. 발송 쪽에 멱등키를 붙여야 합니다."

큐가 작업을 한 번 이상 건넬 수 있으니 받는 쪽에서 중복을 걸러야 한다는 말입니다.

페이지덱에서 태오가 문서 내보내기를 큐로 옮긴 적이 있습니다. 옮기기 전에는 월요일 아침마다 서버가 한 번씩 넘어졌고, 그때마다 수아가 고객에게 사과 메일을 보냈습니다. 옮긴 뒤에는 요청 500건이 줄을 서고 꺼내 가는 프로그램 두 대가 차례로 처리해 마지막 건이 9시 18분에 끝났습니다. 서버는 한 번도 넘어지지 않았습니다.

달라진 것이 하나 더 있습니다. 넘어지지 않으니 밀린 건수를 숫자로 볼 수 있게 됐고, 대기가 5,000건을 넘으면 알림이 오도록 걸어 두었습니다. 고객이 먼저 알려 주던 문제를 팀이 먼저 알게 된 셈입니다.

흔한 오해

큐를 넣으면 빨라진다고 읽는 경우가 가장 많습니다. 화면이 곧바로 넘어가니 그렇게 느껴집니다. 실제로 짧아진 것은 응답 시간이고 작업이 끝나는 시점은 오히려 뒤로 밀립니다. 줄을 서는 시간이 새로 붙기 때문입니다. 이 차이를 모르고 도입하면 사용자에게는 곧바로 끝난 것처럼 보이는데 결과물은 20분 뒤에 나오는 상태가 되고, 진행 상황을 보여 주지 않으면 같은 요청을 세 번 더 누릅니다. 큐를 넣는 일과 진행 상황을 보여 주는 일은 늘 같이 갑니다.

큐에 넣으면 순서대로 정확히 한 번 처리된다고 믿는 것도 흔합니다. 줄이라는 말이 그렇게 들립니다. 처리하는 쪽을 세 대로 늘리는 순간 순서는 깨집니다. 세 대가 각자 꺼내 가니 나중에 들어온 작업이 먼저 끝날 수 있습니다. 횟수도 마찬가지여서, 대부분의 큐는 한 번 이상 건네는 것까지만 보장합니다. 순서와 횟수를 큐가 지켜 준다고 믿고 설계하면 중복 청구나 뒤집힌 상태 변경으로 돌아옵니다.

자주 헷갈리는 용어

용어무엇을 가리키는가메시지 큐와의 차이
스트림 처리끝없이 들어오는 데이터를 오는 즉시 계산하며 흘려보내는 방식큐는 작업 하나를 한 곳이 가져가 끝내면 지웁니다. 스트림은 같은 흐름을 여러 곳이 각자 읽으며 집계합니다
이벤트 기반 아키텍처사건을 주고받으며 시스템을 느슨하게 연결하는 설계설계 방식이고, 큐는 그 설계를 실제로 굴릴 때 쓰는 부품입니다
백그라운드 작업응답과 분리해 뒤에서 처리하는 작업큐는 그 작업을 줄 세워 건네주는 장치입니다. 앞은 일이고 뒤는 일을 나르는 통로입니다

같이 보면 좋은 페이지

  • 백엔드

    큐가 어느 층에 놓인 부품인지 먼저 봅니다

  • 서버

    큐가 덜어 주는 쪽이 무엇을 하는지 봅니다

  • 스트림 처리

    줄 세우기와 흘려보내기를 나란히 놓고 비교합니다

마지막 업데이트 2026-09-16