0Pricing
PHP Academy · 강의

PHP에서 RabbitMQ 다루기

RabbitMQ로 메시지를 발행하고 소비합니다.

PHP에서 RabbitMQ 다루기은(는) CoddyKit의 무료 PHP Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 PHP Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

PHP에서 RabbitMQ 사용하기

RabbitMQ는 AMQP 0-9-1을 사용하는 브로커입니다. PHP에서 대표적인 클라이언트는 php-amqplib/php-amqplib(순수 PHP) 또는 C 기반의 ext-amqp입니다. 이 단원에서는 Composer가 실행되는 어디서나 사용할 수 있는 php-amqplib를 사용합니다.

핵심 AMQP 모델에는 세 가지 구성 요소가 있습니다. 교환기는 메시지를 받고, 바인딩은 키에 따라 메시지를 라우팅하며, 큐는 소비자가 처리할 메시지를 보관합니다. 이 구조를 익히면 나머지는 세부 사항에 불과합니다.

클라이언트 설치

Composer로 라이브러리를 추가하십시오. 일반적인 CLI PHP 빌드에 포함되는 sockets와 bcmath 확장이 필요합니다.

composer require php-amqplib/php-amqplib
# Connection target, e.g. amqp://guest:guest@localhost:5672/

교환기·큐·바인딩 모델

생산자는 큐에 직접 발행하지 않고 반드시 교환기에 발행합니다. 교환기 유형이 라우팅 방식을 결정합니다:

  • direct — 라우팅 키가 정확히 일치해야 합니다.
  • topic — order.*.eu와 같은 와일드카드 패턴을 사용합니다.
  • fanout — 연결된 모든 큐에 브로드캐스트합니다.
  • headers — 헤더 속성을 기준으로 일치시킵니다.

바인딩은 라우팅 패턴을 사용해 큐를 교환기에 연결합니다. 생산자와 큐 구조를 분리하는 것이 교환기 계층의 핵심 목적입니다.

연결 및 선언

연결을 열고 채널을 가져온 다음 토폴로지를 선언합니다. durable: true를 설정하면 브로커가 다시 시작되어도 교환기와 큐가 유지됩니다. 선언은 멱등적이므로, 일치하는 인수로 이미 존재하는 엔터티를 선언하면 아무 작업도 수행되지 않습니다.

<?php
require 'vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;

$conn = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$ch = $conn->channel();

$ch->exchange_declare('orders', 'topic', false, true, false);
$ch->queue_declare('orders.email', false, true, false, false);
$ch->queue_bind('orders.email', 'orders', 'order.created');

echo "Topology ready\n";
$ch->close();
$conn->close();

메시지 발행

본문을 AMQPMessage로 감쌉니다. delivery_mode = 2로 설정하면 메시지가 영속적이 됩니다. 재시작 후에도 메시지가 유지되려면 내구성 있는 큐와 영속 메시지가 모두 필요하며, 둘 중 하나만으로는 충분하지 않습니다.

<?php
require 'vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

$conn = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$ch = $conn->channel();

$payload = json_encode(['orderId' => 42, 'total' => 19.90]);
$msg = new AMQPMessage($payload, [
    'content_type'  => 'application/json',
    'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT,
    'message_id'    => bin2hex(random_bytes(8)),
]);

$ch->basic_publish($msg, 'orders', 'order.created');
echo "Published\n";
$ch->close();
$conn->close();

수동 확인 응답으로 메시지 소비

basic_consume으로 콜백을 등록합니다. no_ack = false를 전달하면 확인 응답을 직접 제어할 수 있습니다. 작업이 성공한 후에만 확인 응답을 보내십시오. 실패하면 재큐잉을 사용하여 basic_nack을 보내 RabbitMQ가 메시지를 다시 전달하도록 합니다.

<?php
require 'vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;

$conn = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$ch = $conn->channel();
$ch->basic_qos(null, 10, null); // prefetch 10

$callback = function ($msg) {
    $data = json_decode($msg->getBody(), true);
    try {
        // ... do work ...
        $msg->ack();
    } catch (\Throwable $e) {
        $msg->nack(true); // requeue
    }
};

$ch->basic_consume('orders.email', '', false, false, false, false, $callback);
while ($ch->is_consuming()) {
    $ch->wait();
}

미리 가져오기 및 공정한 분배

기본적으로 RabbitMQ는 각 소비자가 얼마나 바쁜지 고려하지 않고 메시지를 소비자에게 순서대로 번갈아 보냅니다. 따라서 느린 소비자에게 작업이 쌓입니다. basic_qos(null, prefetch, null)은 소비자가 보유할 수 있는 확인 응답되지 않은 메시지 수를 제한합니다.

무겁고 편차가 큰 작업에서는 미리 가져오기 값을 작은 수로 설정하십시오(예: 1–10). 그러면 브로커는 처리 여유가 있는 소비자에게만 새 작업을 보냅니다. 이를 공정한 분배라고 합니다.

발행자 확인 응답

basic_publish은 즉시 반환되므로 브로커가 메시지를 수락했는지는 알려 주지 않습니다. 발행을 보장하려면 발행자 확인 응답을 활성화하십시오. 그러면 브로커는 메시지가 안전하게 저장되거나 라우팅된 후 확인 응답을 보냅니다.

<?php
require 'vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

$conn = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$ch = $conn->channel();
$ch->confirm_select(); // enable confirms on this channel

$ch->set_ack_handler(fn($m) => print("confirmed\n"));
$ch->set_nack_handler(fn($m) => print("REJECTED\n"));

$ch->basic_publish(new AMQPMessage('hi'), 'orders', 'order.created');
$ch->wait_for_pending_acks(5.0); // block until confirmed or timeout

배달 불가 메시지 처리

거부된 메시지(nack을 재큐잉하지 않은 경우)나 만료된 메시지가 DLX로 라우팅되도록 큐의 x-dead-letter-exchange 인수를 설정합니다. 쿼럼 큐에서 x-delivery-limit과 함께 사용하면 재시도 횟수를 자동으로 제한할 수 있습니다.

<?php
use PhpAmqpLib\Wire\AMQPTable;

$args = new AMQPTable([
    'x-dead-letter-exchange'    => 'orders.dlx',
    'x-dead-letter-routing-key' => 'order.failed',
    'x-message-ttl'             => 60000, // ms before expiry
]);
// false=passive, true=durable, false=exclusive, false=autodelete, args
$ch->queue_declare('orders.email', false, true, false, false, false, $args);
$ch->queue_declare('orders.dead', false, true, false, false);
$ch->queue_bind('orders.dead', 'orders.dlx', 'order.failed');

운영 환경에서 작업자 실행

PHP RabbitMQ 작업자를 운영할 때 얻은 몇 가지 실전 규칙입니다:

  • 소비자를 종료될 때 다시 시작하는 프로세스 감독자(시스템 서비스 관리자 / 프로세스 감독자) 아래에서 장시간 실행되는 CLI 프로세스로 실행합니다.
  • PHP는 시간이 지나면서 메모리를 누수하므로, N개의 메시지를 처리했거나 메모리 임계값에 도달하면 작업자를 다시 시작합니다.
  • AMQP 하트비트를 보내고 SIGTERM을 처리하여 정상적으로 종료합니다. 즉, 처리 중인 메시지를 완료한 다음 중지합니다.
  • 기존 미러링 큐 대신 HA를 위해 쿼럼 큐를 사용합니다.

정상 종료

배포 과정에서 SIGTERM을 보냅니다. 단순한 작업자는 메시지를 처리하는 중에 종료되어 재전달을 유발합니다. 신호 처리기를 설치하여 플래그를 변경하고, 현재 메시지를 완료한 뒤 확인 응답을 보내고, 소비 루프를 정상적으로 빠져나오게 하십시오. pcntl_async_signals(true)를 사용하면 AMQP 대기 사이에 PHP가 신호를 전달할 수 있습니다.

<?php
pcntl_async_signals(true);
$running = true;
pcntl_signal(SIGTERM, function () use (&$running) {
    $running = false; // stop after the current message
    echo "SIGTERM: draining...\n";
});

while ($running && $ch->is_consuming()) {
    try {
        $ch->wait(null, false, 5); // wakes for signals
    } catch (\PhpAmqpLib\Exception\AMQPTimeoutException $e) {
        // idle tick - loop and re-check $running
    }
}
$ch->close();
echo "Stopped cleanly\n";

빠른 확인

브로커 재시작을 견디기.

복습

이제 PHP로 실제 RabbitMQ 처리 흐름을 구축할 수 있습니다.

  • 교환기에 발행하고, 바인딩을 통해 큐로 라우팅합니다.
  • 내구성 있는 큐와 영속 메시지는 재시작 후에도 유지됩니다.
  • 수동 확인 응답으로 소비하고, 공정한 분배를 위해 basic_qos 미리 가져오기를 조정합니다.
  • 전송을 보장하려면 발행자 확인 응답을 사용하고, 처리할 수 없는 메시지에는 DLX를 사용합니다.
  • 하트비트와 정상 종료를 지원하는 감독자 아래에서 작업자를 실행합니다.

다음은 작업 큐잉 대신 높은 처리량의 스트리밍이 필요할 때 사용하는 카프카입니다.

자주 묻는 질문

“PHP에서 RabbitMQ 다루기” 강의는 무료인가요?

네 — “PHP에서 RabbitMQ 다루기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 PHP Academy 강의 전체를 잠금 해제할 수 있습니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“PHP에서 RabbitMQ 다루기”에서 뭘 배우나요?

RabbitMQ로 메시지를 발행하고 소비합니다. 브라우저에서 직접 실행하는 실습 코드로 PHP Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

PHP Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 PHP Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“PHP에서 RabbitMQ 다루기” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 PHP Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 PHP Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 비동기 메시징이 필요한 이유
  2. PHP에서 RabbitMQ 다루기
  3. PHP용 Apache Kafka
  4. 이벤트 기반 워크플로 구축
← PHP Academy(으)로 돌아가기