๐Ÿฐ RabbitMQ์™€ C#์œผ๋กœ ๋ฉ”์‹œ์ง€ ํ ๊ตฌํ˜„ํ•˜๊ธฐ ๐Ÿš€

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿฐ RabbitMQ์™€ C#์œผ๋กœ ๋ฉ”์‹œ์ง€ ํ ๊ตฌํ˜„ํ•˜๊ธฐ ๐Ÿš€

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ ์ •๋ง ํฅ๋ฏธ์ง„์ง„ํ•œ ์ฃผ์ œ๋กœ ์ฐพ์•„์™”์–ด์š”. ๋ฐ”๋กœ RabbitMQ์™€ C#์„ ์ด์šฉํ•ด์„œ ๋ฉ”์‹œ์ง€ ํ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ์ด๊ฑฐ ์™„์ „ ๊ฟ€์žผ ์•„๋‹ˆ๊ฒ ์–ด์š”? ๐Ÿ˜†

ํ”„๋กœ๊ทธ๋žจ ๊ฐœ๋ฐœ์˜ ์„ธ๊ณ„์—์„œ ๋ฉ”์‹œ์ง€ ํ๋Š” ์ •๋ง ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•˜๋Š”๋ฐ์š”, ํŠนํžˆ C# ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ๋Š” ๋”์šฑ ๊ทธ๋ ‡์ฃ . ์—ฌ๋Ÿฌ๋ถ„, ํ˜น์‹œ ์žฌ๋Šฅ๋„ท(https://www.jaenung.net)์ด๋ผ๋Š” ์‚ฌ์ดํŠธ ์•„์„ธ์š”? ๊ฑฐ๊ธฐ์„œ๋„ ์ด๋Ÿฐ ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•ด์„œ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ ๊ฑฐ๋ž˜๋ฅผ ๋” ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์š”. ์–ด๋–ป๊ฒŒ ๋ณด๋ฉด ์žฌ๋Šฅ๋„ท์˜ ์ˆจ์€ ์˜์›…์ด ๋  ์ˆ˜๋„ ์žˆ๊ฒ ๋„ค์š”! ใ…‹ใ…‹ใ…‹

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์‹œ์ž‘ํ•ด๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? ๊ทธ๋Ÿผ ๊ณ ๊ณ ์”ฝ~! ๐Ÿš€

๐Ÿ‡ RabbitMQ๋ž€ ๋ญ์•ผ? ๊ท€์—ฌ์šด ํ† ๋ผ ์ด๋ฆ„์ธ๊ฐ€์š”?

ใ…‹ใ…‹ใ…‹ ์•„๋‹ˆ์—์š”, ์—ฌ๋Ÿฌ๋ถ„! RabbitMQ๋Š” ๊ท€์—ฌ์šด ํ† ๋ผ ์ด๋ฆ„์ด ์•„๋‹ˆ๋ผ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค ์†Œํ”„ํŠธ์›จ์–ด์˜ˆ์š”. ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๊ฐ€ ๋ญ๋ƒ๊ณ ์š”? ์‰ฝ๊ฒŒ ๋งํ•ด์„œ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋“ค ์‚ฌ์ด์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์ค‘๊ฐ„๋‹ค๋ฆฌ ์—ญํ• ์„ ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ด์—์š”.

RabbitMQ๋Š” AMQP(Advanced Message Queuing Protocol)๋ผ๋Š” ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•ด์š”. ์ด ํ”„๋กœํ† ์ฝœ์€ ๋ฉ”์‹œ์ง€๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ, ๊ทธ๋ฆฌ๊ณ  ํšจ์œจ์ ์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฑฐ์ฃ . ๋งˆ์น˜ ์šฐ์ฒด๊ตญ์—์„œ ํŽธ์ง€๋ฅผ ๋ฐฐ๋‹ฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”! ๐Ÿ“ฎ

RabbitMQ์˜ ํŠน์ง•์„ ์ข€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ์š”?

  • ๐Ÿ”ฅ ์‹ ๋ขฐ์„ฑ: ๋ฉ”์‹œ์ง€๊ฐ€ ์ ˆ๋Œ€ ์œ ์‹ค๋˜์ง€ ์•Š์•„์š”. ๋งˆ์น˜ ํŽธ์ง€๊ฐ€ ์ ˆ๋Œ€ ์‚ฌ๋ผ์ง€์ง€ ์•Š๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”!
  • ๐Ÿš€ ๋น ๋ฅธ ์†๋„: ์ดˆ๋‹น ์ˆ˜๋งŒ ๊ฐœ์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ด‘์† ๋ฐฐ๋‹ฌ์ด์ฃ !
  • ๐ŸŒ ๋‹ค์–‘ํ•œ ํ”„๋กœํ† ์ฝœ ์ง€์›: AMQP, MQTT, STOMP ๋“ฑ ์—ฌ๋Ÿฌ ํ”„๋กœํ† ์ฝœ์„ ์ง€์›ํ•ด์š”. ๋‹ค๊ตญ์–ด ๋Šฅ๋ ฅ์ž ๊ฐ™์€ ๊ฑฐ์ฃ !
  • ๐Ÿ”ง ์œ ์—ฐํ•œ ๋ผ์šฐํŒ…: ๋ฉ”์‹œ์ง€๋ฅผ ์›ํ•˜๋Š” ๊ณณ์œผ๋กœ ์ •ํ™•ํ•˜๊ฒŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์š”. GPS ๋‚ด๋น„๊ฒŒ์ด์…˜ ๊ฐ™์€ ๊ฑฐ์˜ˆ์š”!
  • ๐Ÿ”’ ๋ณด์•ˆ: SSL ์ง€์›์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ „์†กํ•ด์š”. ๋น„๋ฐ€ ์š”์› ๊ธ‰ ๋ณด์•ˆ์ด์ฃ !

์ด๋ ‡๊ฒŒ ๋ณด๋‹ˆ๊นŒ RabbitMQ๊ฐ€ ์ •๋ง ๋Œ€๋‹จํ•˜์ฃ ? ๋งˆ์น˜ ์Šˆํผ ํžˆ์–ด๋กœ ๊ฐ™์•„์š”! ๐Ÿฆธโ€โ™‚๏ธ

๐Ÿค” ์žฌ๋Šฅ๋„ท์—์„œ์˜ ํ™œ์šฉ ์˜ˆ์‹œ

์žฌ๋Šฅ๋„ท์—์„œ RabbitMQ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์–ด๋–ค ์ ์ด ์ข‹์„๊นŒ์š”? ์˜ˆ๋ฅผ ๋“ค์–ด, ์ƒˆ๋กœ์šด ์žฌ๋Šฅ ๊ฑฐ๋ž˜๊ฐ€ ๋“ฑ๋ก๋  ๋•Œ๋งˆ๋‹ค ๊ด€๋ จ ์„œ๋น„์Šค๋“ค์— ์ฆ‰์‹œ ์•Œ๋ฆผ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž๋“ค์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ƒˆ๋กœ์šด ์žฌ๋Šฅ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ? ์™„์ „ ๊ฟ€๊ธฐ๋Šฅ ์•„๋‹Œ๊ฐ€์š”? ๐Ÿ˜Ž

์ž, ์ด์ œ RabbitMQ์— ๋Œ€ํ•ด ์–ด๋Š ์ •๋„ ๊ฐ์ด ์˜ค์‹œ๋‚˜์š”? ๊ทธ๋Ÿผ ์ด์ œ C#๊ณผ ํ•จ๊ป˜ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•Œ์•„๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? ๋‹ค์Œ ์„น์…˜์œผ๋กœ ๊ณ ๊ณ ์”ฝ~! ๐Ÿš€

๐Ÿ–ฅ๏ธ C#๊ณผ RabbitMQ์˜ ํ™˜์ƒ์˜ ์ฝœ๋ผ๋ณด

์—ฌ๋Ÿฌ๋ถ„, C#์ด๋ž‘ RabbitMQ๊ฐ€ ๋งŒ๋‚˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ๋ฐ”๋กœ ๊ฐœ๋ฐœ์ž๋“ค์˜ ๋“œ๋ฆผํŒ€์ด ํƒ„์ƒํ•˜๋Š” ๊ฑฐ์˜ˆ์š”! ใ…‹ใ…‹ใ…‹

C#์€ ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ์—์„œ ๊ฐœ๋ฐœํ•œ ๊ฐ•๋ ฅํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ฃ . ๊ฐ์ฒด ์ง€ํ–ฅ์ ์ด๊ณ , ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ๋›ฐ์–ด๋‚˜๋ฉฐ, ๋‹ค์–‘ํ•œ ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ทธ๋ฆฌ๊ณ  RabbitMQ๋Š” ๋ฉ”์‹œ์ง€ ํ์˜ ๊ฐ•์ž๊ณ ์š”. ์ด ๋‘˜์ด ๋งŒ๋‚˜๋ฉด ์ •๋ง ๋Œ€๋‹จํ•œ ์ผ์„ ํ•  ์ˆ˜ ์žˆ์–ด์š”!

C#์œผ๋กœ RabbitMQ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด RabbitMQ.Client๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ด์š”. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” NuGet ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €๋ฅผ ํ†ตํ•ด ์‰ฝ๊ฒŒ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

์ž, ์ด์ œ ์‹ค์ œ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณผ๊นŒ์š”? ๋จผ์ € ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” Producer(์ƒ์‚ฐ์ž)๋ถ€ํ„ฐ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”!


using RabbitMQ.Client;
using System;
using System.Text;

class Program
{
    static void Main()
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.QueueDeclare(queue: "hello",
                                 durable: false,
                                 exclusive: false,
                                 autoDelete: false,
                                 arguments: null);

            string message = "์•ˆ๋…•ํ•˜์„ธ์š”, RabbitMQ!";
            var body = Encoding.UTF8.GetBytes(message);

            channel.BasicPublish(exchange: "",
                                 routingKey: "hello",
                                 basicProperties: null,
                                 body: body);

            Console.WriteLine($" [x] Sent {message}");
        }

        Console.WriteLine(" Press [enter] to exit.");
        Console.ReadLine();
    }
}

์šฐ์™€~ ์ด๊ฒŒ ๋ฐ”๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” Producer ์ฝ”๋“œ์˜ˆ์š”! ๐Ÿ˜ฒ

์ด ์ฝ”๋“œ๊ฐ€ ํ•˜๋Š” ์ผ์„ ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•ด๋“œ๋ฆด๊ฒŒ์š”:

  1. ๋จผ์ € RabbitMQ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•ด์š”. ์—ฌ๊ธฐ์„œ๋Š” ๋กœ์ปฌํ˜ธ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ, ์‹ค์ œ ์„œ๋ฒ„ ์ฃผ์†Œ๋ฅผ ๋„ฃ์œผ๋ฉด ๋ผ์š”.
  2. ๊ทธ ๋‹ค์Œ, 'hello'๋ผ๋Š” ์ด๋ฆ„์˜ ํ๋ฅผ ๋งŒ๋“ค์–ด์š”. ์ด ํ๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜๋Š” ๊ณณ์ด์—์š”.
  3. ๋ฉ”์‹œ์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฐ”์ดํŠธ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•ด์š”.
  4. ๋งˆ์ง€๋ง‰์œผ๋กœ, ๋ฉ”์‹œ์ง€๋ฅผ ํ์— ๋ฐœํ–‰ํ•ด์š”.

์ด์ œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๋Š” Consumer(์†Œ๋น„์ž)๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊นŒ์š”?


using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;

class Program
{
    static void Main()
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.QueueDeclare(queue: "hello",
                                 durable: false,
                                 exclusive: false,
                                 autoDelete: false,
                                 arguments: null);

            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (model, ea) =>
            {
                var body = ea.Body.ToArray();
                var message = Encoding.UTF8.GetString(body);
                Console.WriteLine($" [x] Received {message}");
            };
            channel.BasicConsume(queue: "hello",
                                 autoAck: true,
                                 consumer: consumer);

            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }
    }
}

์งœ์ž”~ ์ด๊ฒŒ ๋ฐ”๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๋Š” Consumer ์ฝ”๋“œ์˜ˆ์š”! ๐Ÿ˜Ž

์ด ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ผ์„ ํ•ด์š”:

  1. Producer์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ RabbitMQ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•ด์š”.
  2. 'hello' ํ๋ฅผ ์„ ์–ธํ•ด์š”. (Producer์—์„œ ์ด๋ฏธ ๋งŒ๋“ค์—ˆ์ง€๋งŒ, ์–ด๋Š ์ชฝ์ด ๋จผ์ € ์‹คํ–‰๋ ์ง€ ๋ชจ๋ฅด๋‹ˆ๊นŒ ์•ˆ์ „ํ•˜๊ฒŒ ๋‹ค์‹œ ์„ ์–ธํ•ด์š”)
  3. EventingBasicConsumer๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์„ ์ค€๋น„๋ฅผ ํ•ด์š”.
  4. ๋ฉ”์‹œ์ง€๊ฐ€ ๋„์ฐฉํ•˜๋ฉด ํ™”๋ฉด์— ์ถœ๋ ฅํ•ด์š”.
  5. BasicConsume ๋ฉ”์„œ๋“œ๋กœ ํ์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์†Œ๋น„ํ•˜๊ธฐ ์‹œ์ž‘ํ•ด์š”.

๐Ÿ’ก ๊ฟ€ํŒ

์—ฌ๋Ÿฌ๋ถ„, ์ด ์ฝ”๋“œ๋“ค์„ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋ผ์š”! ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์—๋Ÿฌ ์ฒ˜๋ฆฌ, ๋กœ๊น…, ์„ค์ • ๊ด€๋ฆฌ ๋“ฑ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ด์š”. ์•ˆ์ „ํ•œ ์ฝ”๋”ฉ ์Šต๊ด€์„ ๋“ค์ด๋Š” ๊ฒŒ ์ค‘์š”ํ•ด์š”! ๐Ÿ˜‰

์ž, ์ด๋ ‡๊ฒŒ ํ•ด์„œ C#๊ณผ RabbitMQ๋ฅผ ์ด์šฉํ•œ ๊ธฐ๋ณธ์ ์ธ ๋ฉ”์‹œ์ง€ ํ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ดค์–ด์š”. ์–ด๋•Œ์š”? ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ต์ง€ ์•Š์ฃ ? ๐Ÿ˜„

๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์ด ์‹œ์Šคํ…œ์„ ์ข€ ๋” ๋ฐœ์ „์‹œ์ผœ๋ณผ ๊ฑฐ์˜ˆ์š”. ๋” ๋ณต์žกํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋‹ค๋ค„๋ณผ ์ค€๋น„ ๋˜์…จ๋‚˜์š”? ๊ทธ๋Ÿผ ๊ณ ๊ณ ์”ฝ~! ๐Ÿš€

๐ŸŽญ ๋‹ค์–‘ํ•œ ๋ฉ”์‹œ์ง• ํŒจํ„ด ๊ตฌํ˜„ํ•˜๊ธฐ

์—ฌ๋Ÿฌ๋ถ„, ์ง€๊ธˆ๊นŒ์ง€ ๊ธฐ๋ณธ์ ์ธ ๋ฉ”์‹œ์ง€ ํ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ดค๋Š”๋ฐ์š”. ์ด์ œ ์ข€ ๋” ๋ณต์žกํ•˜๊ณ  ์žฌ๋ฏธ์žˆ๋Š” ๊ฑธ ํ•ด๋ณผ๊นŒ์š”? RabbitMQ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ๋ฉ”์‹œ์ง• ํŒจํ„ด์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์˜ค๋Š˜์€ ๊ทธ ์ค‘์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ์„ธ ๊ฐ€์ง€ ํŒจํ„ด์„ ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? ๐Ÿ˜Ž

1. ์ž‘์—… ํ (Work Queues)

์ž‘์—… ํ๋Š” ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์„ ์—ฌ๋Ÿฌ ์›Œ์ปค์—๊ฒŒ ๋ถ„์‚ฐ์‹œํ‚ค๋Š” ํŒจํ„ด์ด์—์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ๋„ท์—์„œ ์ƒˆ๋กœ์šด ์žฌ๋Šฅ์ด ๋“ฑ๋ก๋  ๋•Œ๋งˆ๋‹ค ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ, ๊ฒ€์ƒ‰ ์ธ๋ฑ์‹ฑ, ์•Œ๋ฆผ ๋ฐœ์†ก ๋“ฑ์˜ ์ž‘์—…์„ ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณผ๊นŒ์š”?

Producer ์ฝ”๋“œ:


using RabbitMQ.Client;
using System;
using System.Text;

class NewTalentProducer
{
    public static void Main()
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.QueueDeclare(queue: "talent_tasks",
                                 durable: true,
                                 exclusive: false,
                                 autoDelete: false,
                                 arguments: null);

            var message = "์ƒˆ๋กœ์šด ์žฌ๋Šฅ: ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ณผ์™ธ";
            var body = Encoding.UTF8.GetBytes(message);

            var properties = channel.CreateBasicProperties();
            properties.Persistent = true;

            channel.BasicPublish(exchange: "",
                                 routingKey: "talent_tasks",
                                 basicProperties: properties,
                                 body: body);
            Console.WriteLine($" [x] Sent {message}");
        }

        Console.WriteLine(" Press [enter] to exit.");
        Console.ReadLine();
    }
}

Consumer ์ฝ”๋“œ:


using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;
using System.Threading;

class Worker
{
    public static void Main()
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.QueueDeclare(queue: "talent_tasks",
                                 durable: true,
                                 exclusive: false,
                                 autoDelete: false,
                                 arguments: null);

            channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);

            Console.WriteLine(" [*] Waiting for messages.");

            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (sender, ea) =>
            {
                var body = ea.Body.ToArray();
                var message = Encoding.UTF8.GetString(body);
                Console.WriteLine($" [x] Received {message}");

                int dots = message.Split('.').Length - 1;
                Thread.Sleep(dots * 1000);

                Console.WriteLine(" [x] Done");

                channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
            };
            channel.BasicConsume(queue: "talent_tasks",
                                 autoAck: false,
                                 consumer: consumer);

            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }
    }
}

์ด ์ฝ”๋“œ์—์„œ ์ฃผ๋ชฉํ•  ์ ์€:

  • ํ๋ฅผ durable๋กœ ์„ค์ •ํ–ˆ์–ด์š”. ์„œ๋ฒ„๊ฐ€ ์žฌ์‹œ์ž‘ํ•ด๋„ ํ๊ฐ€ ์‚ฌ๋ผ์ง€์ง€ ์•Š์•„์š”.
  • ๋ฉ”์‹œ์ง€๋ฅผ persistent๋กœ ๋งŒ๋“ค์—ˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฉ”์‹œ์ง€๋„ ์„œ๋ฒ„ ์žฌ์‹œ์ž‘ ํ›„์—๋„ ์‚ด์•„๋‚จ์•„์š”.
  • BasicQos๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ๋ฉ”์‹œ์ง€๋งŒ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ–ˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ž‘์—…์„ ๊ณตํ‰ํ•˜๊ฒŒ ๋ถ„๋ฐฐํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ์ž‘์—…์ด ๋๋‚˜๋ฉด BasicAck๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ–ˆ๋‹ค๊ณ  ์•Œ๋ ค์ค˜์š”.

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ

์žฌ๋Šฅ๋„ท์—์„œ ์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด, ์ƒˆ๋กœ์šด ์žฌ๋Šฅ์ด ๋“ฑ๋ก๋  ๋•Œ๋งˆ๋‹ค ํ•„์š”ํ•œ ์—ฌ๋Ÿฌ ์ž‘์—…(์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ, ๊ฒ€์ƒ‰ ์ธ๋ฑ์‹ฑ, ์•Œ๋ฆผ ๋ฐœ์†ก ๋“ฑ)์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ฐ ์ž‘์—…์„ ๋ณ„๋„์˜ ์›Œ์ปค๊ฐ€ ๋‹ด๋‹นํ•˜๋ฉด ์‹œ์Šคํ…œ์˜ ํ™•์žฅ์„ฑ์ด ๋†’์•„์ง€์ฃ !

2. ๋ฐœํ–‰/๊ตฌ๋… (Publish/Subscribe)

์ด ํŒจํ„ด์€ ํ•˜๋‚˜์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์—ฌ๋Ÿฌ ์†Œ๋น„์ž์—๊ฒŒ ์ „๋‹ฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ๋„ท์—์„œ ์ƒˆ๋กœ์šด ๊ณต์ง€์‚ฌํ•ญ์ด ๋“ฑ๋ก๋˜๋ฉด ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆผ์„ ๋ณด๋‚ด๊ณ  ์‹ถ๋‹ค๋ฉด ์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

Producer ์ฝ”๋“œ:


using System;
using RabbitMQ.Client;
using System.Text;

class EmitLog
{
    public static void Main(string[] args)
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout);

            var message = "์ƒˆ๋กœ์šด ๊ณต์ง€์‚ฌํ•ญ: ์žฌ๋Šฅ๋„ท ์„œ๋น„์Šค ๊ฐœ์„  ์•ˆ๋‚ด";
            var body = Encoding.UTF8.GetBytes(message);
            channel.BasicPublish(exchange: "logs",
                                 routingKey: "",
                                 basicProperties: null,
                                 body: body);
            Console.WriteLine($" [x] Sent {message}");
        }

        Console.WriteLine(" Press [enter] to exit.");
        Console.ReadLine();
    }
}

Consumer ์ฝ”๋“œ:


using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;

class ReceiveLogs
{
    public static void Main()
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout);

            var queueName = channel.QueueDeclare().QueueName;
            channel.QueueBind(queue: queueName,
                              exchange: "logs",
                              routingKey: "");

            Console.WriteLine(" [*] Waiting for logs.");

            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (model, ea) =>
            {
                var body = ea.Body.ToArray();
                var message = Encoding.UTF8.GetString(body);
                Console.WriteLine($" [x] {message}");
            };
            channel.BasicConsume(queue: queueName,
                                 autoAck: true,
                                 consumer: consumer);

            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }
    }
}

์ด ์ฝ”๋“œ์—์„œ ์ฃผ๋ชฉํ•  ์ ์€:

  • exchange๋ฅผ ์‚ฌ์šฉํ–ˆ์–ด์š”. 'fanout' ํƒ€์ž…์˜ exchange๋Š” ๋ชจ๋“  ํ์— ๋ฉ”์‹œ์ง€๋ฅผ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธํ•ด์š”.
  • Consumer๋Š” ์ž„์‹œ ํ๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ exchange์— ๋ฐ”์ธ๋”ฉํ•ด์š”.
  • ์—ฌ๋Ÿฌ Consumer๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, ๋ชจ๋“  Consumer๊ฐ€ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ฒŒ ๋ผ์š”.

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ

์žฌ๋Šฅ๋„ท์—์„œ ์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด, ์ค‘์š”ํ•œ ๊ณต์ง€์‚ฌํ•ญ์ด๋‚˜ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ์•ˆ๋‚ด ๋“ฑ์„ ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์š”. ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ํ•œ์ธต ๊ฐœ์„ ๋˜๊ฒ ์ฃ ? ๐Ÿ˜Š

3. ๋ผ์šฐํŒ… (Routing)

๋ผ์šฐํŒ… ํŒจํ„ด์€ ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ๋ฉ”์‹œ์ง€๋ฅผ ์„ ๋ณ„์ ์œผ๋กœ ์ „๋‹ฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ๋„ท์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๊ด€์‹ฌ ์žˆ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ์˜ ์ƒˆ ์žฌ๋Šฅ๋งŒ ์•Œ๋ฆผ์„ ๋ฐ›๊ณ  ์‹ถ๋‹ค๋ฉด ์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

Producer ์ฝ”๋“œ:


using System;
using RabbitMQ.Client;
using System.Text;

class EmitLogDirect
{
    public static void Main(string[] args)
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.ExchangeDeclare(exchange: "direct_logs", type: ExchangeType.Direct);

            var category = "programming"; // ๋˜๋Š” "design", "marketing" ๋“ฑ
            var message = $"์ƒˆ๋กœ์šด {category} ์žฌ๋Šฅ์ด ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค!";
            var body = Encoding.UTF8.GetBytes(message);
            
            channel.BasicPublish(exchange: "direct_logs",
                                 routingKey: category,
                                 basicProperties: null,
                                 body: body);
            Console.WriteLine($" [x] Sent '{category}':'{message}'");
        }

        Console.WriteLine(" Press [enter] to exit.");
        Console.ReadLine();
    }
}

Consumer ์ฝ”๋“œ:


using System;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text;

class ReceiveLogsDirect
{
    public static void Main(string[] args)
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.ExchangeDeclare(exchange: "direct_logs", type: ExchangeType.Direct);
            var queueName = channel.QueueDeclare().QueueName;

            if (args.Length < 1)
            {
                Console.Error.WriteLine("Usage: {0} [info] [warning] [error]",
                                        Environment.GetCommandLineArgs()[0]);
                Console.WriteLine(" Press [enter] to exit.");
                Console.ReadLine();
                Environment.ExitCode = 1;
                return;
            }

            foreach (var category in args)
            {
                channel.QueueBind(queue: queueName,
                                  exchange: "direct_logs",
                                  routingKey: category);
            }

            Console.WriteLine(" [*] Waiting for messages.");

            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (model, ea) =>
            {
                var body = ea.Body.ToArray();
                var message = Encoding.UTF8.GetString(body);
                var routingKey = ea.RoutingKey;
                Console.WriteLine($" [x] Received '{routingKey}':'{message}'");
            };
            channel.BasicConsume(queue: queueName,
                                 autoAck: true,
                                 consumer: consumer);

            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }
    }
}

์ด ์ฝ”๋“œ์—์„œ ์ฃผ๋ชฉํ•  ์ ์€:

  • 'direct' ํƒ€์ž…์˜ exchange๋ฅผ ์‚ฌ์šฉํ–ˆ์–ด์š”. ์ด ํƒ€์ž…์€ ๋ผ์šฐํŒ… ํ‚ค์— ๋”ฐ๋ผ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•ด์š”.
  • Producer๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ๋•Œ ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ๋ผ์šฐํŒ… ํ‚ค๋กœ ์‚ฌ์šฉํ•ด์š”.
  • Consumer๋Š” ๊ด€์‹ฌ ์žˆ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ๋งŒ ๋ฐ”์ธ๋”ฉํ•ด์š”. ๊ทธ๋ž˜์„œ ์›ํ•˜๋Š” ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋ฉ”์‹œ์ง€๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ

์žฌ๋Šฅ๋„ท์—์„œ ์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด, ์‚ฌ์šฉ์ž๋“ค์ด ๊ด€์‹ฌ ์žˆ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ์˜ ์ƒˆ ์žฌ๋Šฅ๋งŒ ์„ ๋ณ„์ ์œผ๋กœ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ๋”์šฑ ๊ฐœ์ธํ™”๋˜๊ณ , ๋ถˆํ•„์š”ํ•œ ์•Œ๋ฆผ์œผ๋กœ ์ธํ•œ ํ”ผ๋กœ๋„๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์ฃ ! ๐Ÿ‘

์–ด๋•Œ์š”, ์—ฌ๋Ÿฌ๋ถ„? ์ด๋ ‡๊ฒŒ ๋‹ค์–‘ํ•œ ๋ฉ”์‹œ์ง• ํŒจํ„ด์„ ๊ตฌํ˜„ํ•ด๋ดค๋Š”๋ฐ, ์žฌ๋ฏธ์žˆ์ง€ ์•Š๋‚˜์š”? ใ…‹ใ…‹ใ…‹ ์ด๋Ÿฐ ํŒจํ„ด๋“ค์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ์ •๋ง ๊ฐ•๋ ฅํ•œ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ํŠนํžˆ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋Š” ์ด๋Ÿฐ ๊ธฐ์ˆ ๋“ค์ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์ฃ . ๐Ÿ˜Š

๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์ด๋Ÿฐ ํŒจํ„ด๋“ค์„ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•  ๋•Œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์ ๋“ค์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? ๊ทธ๋Ÿผ ๊ณ ๊ณ ์”ฝ~! ๐Ÿš€

๐Ÿ› ๏ธ ์‹ค์ „ ์ ์šฉ ์‹œ ๊ณ ๋ ค์‚ฌํ•ญ

์—ฌ๋Ÿฌ๋ถ„, ์ง€๊ธˆ๊นŒ์ง€ RabbitMQ์™€ C#์„ ์ด์šฉํ•ด ๋‹ค์–‘ํ•œ ๋ฉ”์‹œ์ง• ํŒจํ„ด์„ ๊ตฌํ˜„ํ•ด๋ดค๋Š”๋ฐ์š”. ์ด์ œ ์ด๊ฑธ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•  ๋•Œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์ ๋“ค์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? ์ž, ์‹œ์ž‘ํ•ด๋ณผ๊ฒŒ์š”! ๐Ÿ˜Š

1. ๋ฉ”์‹œ์ง€ ์ง€์†์„ฑ๊ณผ ์‹ ๋ขฐ์„ฑ

์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ฉ”์‹œ์ง€์˜ ์†์‹ค์ด ํฐ ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ๋„ท์—์„œ ๊ฒฐ์ œ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ๋ฉ”์‹œ์ง€๊ฐ€ ์‚ฌ๋ผ์ง„๋‹ค๋ฉด? ์ƒ์ƒ๋งŒ ํ•ด๋„ ์•„์ฐ”ํ•˜์ฃ ! ๐Ÿ˜ฑ

์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”:

  • ํ์™€ ๋ฉ”์‹œ์ง€์˜ ์ง€์†์„ฑ: ํ๋ฅผ durable๋กœ, ๋ฉ”์‹œ์ง€๋ฅผ persistent๋กœ ์„ค์ •ํ•ด์š”.
  • Publisher Confirms: ๋ฉ”์‹œ์ง€๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ํ์— ์ €์žฅ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด์š”.
  • ํŠธ๋žœ์žญ์…˜: ์—ฌ๋Ÿฌ ์ž‘์—…์„ ํ•˜๋‚˜์˜ ๋‹จ์œ„๋กœ ์ฒ˜๋ฆฌํ•ด์š”.

์ฝ”๋“œ๋กœ ๋ณด๋ฉด ์ด๋ ‡๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:


var properties = channel.CreateBasicProperties();
properties.Persistent = true;

channel.ConfirmSelect();
channel.BasicPublish(exchange: "",
                     routingKey: "task_queue",
                     basicProperties: properties,
                     body: body);
channel.WaitForConfirmsOrDie();

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ

์žฌ๋Šฅ๋„ท์—์„œ ๊ฒฐ์ œ ์ฒ˜๋ฆฌ๋‚˜ ์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์ด๋Ÿฐ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์•„์š”. ์‹œ์Šคํ…œ์ด ๊ฐ‘์ž๊ธฐ ์ค‘๋‹จ๋˜๋”๋ผ๋„ ์ค‘์š”ํ•œ ์ •๋ณด๋Š” ์•ˆ์ „ํ•˜๊ฒŒ ๋ณด์กด๋  ์ˆ˜ ์žˆ์ฃ !

2. ํ™•์žฅ์„ฑ๊ณผ ์„ฑ๋Šฅ

์žฌ๋Šฅ๋„ท์ด ๋Œ€๋ฐ•๋‚˜์„œ ์‚ฌ์šฉ์ž๊ฐ€ ํญ์ฆํ–ˆ๋‹ค๊ณ  ์ƒ์ƒํ•ด๋ด์š”. ๐Ÿ‘ ๊ทธ๋Ÿผ ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ๋Ÿ‰๋„ ์—„์ฒญ๋‚˜๊ฒŒ ๋Š˜์–ด๋‚˜๊ฒ ์ฃ ? ์ด๋Ÿฐ ์ƒํ™ฉ์— ๋Œ€๋น„ํ•ด ์‹œ์Šคํ…œ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ด์š”.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•ด๋ณผ ์ˆ˜ ์žˆ์–ด์š”:

  • ํด๋Ÿฌ์Šคํ„ฐ๋ง: ์—ฌ๋Ÿฌ RabbitMQ ๋…ธ๋“œ๋ฅผ ํด๋Ÿฌ์Šคํ„ฐ๋กœ ๊ตฌ์„ฑํ•ด์š”.
  • Federation: ์—ฌ๋Ÿฌ ๋ธŒ๋กœ์ปค ๊ฐ„์— ๋ฉ”์‹œ์ง€๋ฅผ ๊ตํ™˜ํ•ด์š”.
  • Shovel: ํ ๊ฐ„์— ๋ฉ”์‹œ์ง€๋ฅผ ๋™์ ์œผ๋กœ ์ „์†กํ•ด์š”.

๋˜ํ•œ, ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„ค์ •์„ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”:


channel.BasicQos(prefetchSize: 0, prefetchCount: 10, global: false);

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•œ ๋ฒˆ์— 10๊ฐœ์˜ ๋ฉ”์‹œ์ง€๋งŒ ๊ฐ€์ ธ์™€์„œ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋ผ์š”. ์›Œ์ปค์˜ ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ์— ๋งž์ถฐ ์ด ๊ฐ’์„ ์กฐ์ •ํ•˜๋ฉด ์ข‹์•„์š”.

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ

์žฌ๋Šฅ๋„ท์˜ ์„ฑ์žฅ์— ๋”ฐ๋ผ ์‹œ์Šคํ…œ์„ ์œ ์—ฐํ•˜๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ๋‚˜ ๊ฒ€์ƒ‰ ์ธ๋ฑ์‹ฑ ๊ฐ™์€ ๋ฌด๊ฑฐ์šด ์ž‘์—…์€ ๋ณ„๋„์˜ ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์ฃ .

3. ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ๋กœ๊น…

์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์‹œ์Šคํ…œ์˜ ์ƒํƒœ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ , ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋น ๋ฅด๊ฒŒ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ด์š”. RabbitMQ๋Š” ๊ฐ•๋ ฅํ•œ ๊ด€๋ฆฌ ๋„๊ตฌ์™€ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ œ๊ณตํ•ด์š”.

  • ๊ด€๋ฆฌ UI: ์›น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ํ, ๊ตํ™˜๊ธฐ, ์—ฐ๊ฒฐ ๋“ฑ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • HTTP API: ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ RabbitMQ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ๋กœ๊น…: ์ค‘์š”ํ•œ ์ด๋ฒคํŠธ๋ฅผ ๋กœ๊ทธ๋กœ ๋‚จ๊ฒจ ๋ฌธ์ œ ํ•ด๊ฒฐ์— ํ™œ์šฉํ•ด์š”.

C# ์ฝ”๋“œ์—์„œ๋„ ๋กœ๊น…์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”:


using Microsoft.Extensions.Logging;

// ...

ILogger logger = LoggerFactory.Create(builder => builder.AddConsole())
                               .CreateLogger<program>();

logger.LogInformation("๋ฉ”์‹œ์ง€ ์ „์†ก: {Message}", message);
</program>

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ

์žฌ๋Šฅ๋„ท์˜ ๊ฐ ์ฃผ์š” ๊ธฐ๋Šฅ(์˜ˆ: ์žฌ๋Šฅ ๋“ฑ๋ก, ๊ฒฐ์ œ ์ฒ˜๋ฆฌ, ๋งค์นญ ๋“ฑ)์— ๋Œ€ํ•œ ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ ํ˜„ํ™ฉ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ฅผ ํ†ตํ•ด ์‹œ์Šคํ…œ์˜ ๋ณ‘๋ชฉ ์ง€์ ์„ ํŒŒ์•…ํ•˜๊ณ  ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์ฃ .

4. ๋ณด์•ˆ

์žฌ๋Šฅ๋„ท์€ ์‚ฌ์šฉ์ž์˜ ๊ฐœ์ธ์ •๋ณด์™€ ๊ฒฐ์ œ ์ •๋ณด๋ฅผ ๋‹ค๋ฃจ๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์•ˆ์ด ์ •๋ง ์ค‘์š”ํ•ด์š”. RabbitMQ์™€ ๊ด€๋ จํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ณด์•ˆ ์กฐ์น˜๋ฅผ ์ทจํ•  ์ˆ˜ ์žˆ์–ด์š”:

  • SSL/TLS: ํด๋ผ์ด์–ธํŠธ์™€ ๋ธŒ๋กœ์ปค ๊ฐ„์˜ ํ†ต์‹ ์„ ์•”ํ˜ธํ™”ํ•ด์š”.
  • ์ธ์ฆ: ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ ์ ‘๊ทผ์„ ์ œํ•œํ•ด์š”.
  • ๊ถŒํ•œ ๊ด€๋ฆฌ: ์‚ฌ์šฉ์ž๋‚˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋ณ„๋กœ ์ ‘๊ทผ ๊ถŒํ•œ์„ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•ด์š”.

C# ์ฝ”๋“œ์—์„œ SSL์„ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ:


var factory = new ConnectionFactory
{
    HostName = "localhost",
    UserName = "user",
    Password = "password",
    Port = 5671,
    Ssl = new SslOption
    {
        ServerName = "localhost",
        CertPath = "/path/to/client/keycert.p12",
        CertPassphrase = "MySecretPassword"
    }
};

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ

์žฌ๋Šฅ๋„ท์—์„œ ๊ฒฐ์ œ ์ •๋ณด๋‚˜ ๊ฐœ์ธ์ •๋ณด๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฉ”์‹œ์ง€๋Š” ๋ฐ˜๋“œ์‹œ ์•”ํ˜ธํ™”๋œ ์ฑ„๋„์„ ํ†ตํ•ด ์ „์†กํ•ด์•ผ ํ•ด์š”. ๋˜ํ•œ, ๊ฐ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์— ์ ์ ˆํ•œ ์ ‘๊ทผ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜์—ฌ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•  ์ˆ˜ ์žˆ์–ด์š”.

5. ์—๋Ÿฌ ์ฒ˜๋ฆฌ์™€ ์žฌ์‹œ๋„

๋„คํŠธ์›Œํฌ ๋ฌธ์ œ๋‚˜ ์„œ๋ฒ„ ์˜ค๋ฅ˜๋กœ ์ธํ•ด ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ๊ฐ€ ์‹คํŒจํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Ÿฐ ์ƒํ™ฉ์— ๋Œ€๋น„ํ•ด ์ ์ ˆํ•œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ์™€ ์žฌ์‹œ๋„ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•ด์š”.

  • Dead Letter Exchanges: ์ฒ˜๋ฆฌ์— ์‹คํŒจํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณ„๋„์˜ ํ๋กœ ๋ณด๋‚ด์š”.
  • ์žฌ์‹œ๋„ ๋กœ์ง: ์ผ์ • ์‹œ๊ฐ„ ํ›„์— ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ๋ฅผ ์žฌ์‹œ๋„ํ•ด์š”.
  • Circuit Breaker: ์—ฐ์†๋œ ์‹คํŒจ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ผ์‹œ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ์ค‘๋‹จํ•ด์š”.

Dead Letter Exchange๋ฅผ ์„ค์ •ํ•˜๋Š” C# ์ฝ”๋“œ ์˜ˆ:


var args = new Dictionary<string object>
{
    {"x-dead-letter-exchange", "dlx"},
    {"x-dead-letter-routing-key", "dlq"}
};
channel.QueueDeclare("myqueue", true, false, false, args);
</string>

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ

์žฌ๋Šฅ๋„ท์—์„œ ๊ฒฐ์ œ ์ฒ˜๋ฆฌ๋‚˜ ๋งค์นญ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์‹คํ–‰ ๊ฐ™์€ ์ค‘์š”ํ•œ ์ž‘์—…์€ ๋ฐ˜๋“œ์‹œ ์„ฑ๊ณตํ•ด์•ผ ํ•ด์š”. ์ด๋Ÿฐ ์ž‘์—…๋“ค์— ๋Œ€ํ•ด Dead Letter Exchange์™€ ์žฌ์‹œ๋„ ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋ฉด, ์ผ์‹œ์ ์ธ ์˜ค๋ฅ˜๋กœ ์ธํ•œ ์‹คํŒจ๋ฅผ ์ตœ์†Œํ™”ํ•  ์ˆ˜ ์žˆ์–ด์š”.

์ž, ์—ฌ๋Ÿฌ๋ถ„! ์ด๋ ‡๊ฒŒ RabbitMQ์™€ C#์„ ์ด์šฉํ•œ ๋ฉ”์‹œ์ง€ ํ ์‹œ์Šคํ…œ์„ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•  ๋•Œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์ฃผ์š” ์‚ฌํ•ญ๋“ค์„ ์•Œ์•„๋ดค์–ด์š”. ์ด๋Ÿฐ ์ ๋“ค์„ ์ž˜ ๊ณ ๋ คํ•˜๋ฉด ์•ˆ์ •์ ์ด๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ๐Ÿ˜Š

์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์„ ๊ฐœ๋ฐœํ•  ๋•Œ ์ด๋Ÿฐ ๊ธฐ์ˆ ๋“ค์„ ํ™œ์šฉํ•˜๋ฉด ์ •๋ง ๋ฉ‹์ง„ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒ ์ฃ ? ์‚ฌ์šฉ์ž๋“ค์˜ ๊ฒฝํ—˜๋„ ์ข‹์•„์ง€๊ณ , ๊ฐœ๋ฐœ์ž๋“ค์˜ ์ž‘์—… ํšจ์œจ์„ฑ๋„ ๋†’์•„์งˆ ๊ฑฐ์˜ˆ์š”. ์—ฌ๋Ÿฌ๋ถ„๋„ ์ด๋Ÿฐ ๊ธฐ์ˆ ๋“ค์„ ํ™œ์šฉํ•ด์„œ ๋ฉ‹์ง„ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์„ธ์š”! ํ™”์ดํŒ…! ๐Ÿ’ช

๐ŸŽฌ ๋งˆ๋ฌด๋ฆฌ

์—ฌ๋Ÿฌ๋ถ„, ์˜ค๋Š˜ ์ •๋ง ๊ธด ์—ฌ์ •์ด์—ˆ์ฃ ? RabbitMQ์™€ C#์„ ์ด์šฉํ•œ ๋ฉ”์‹œ์ง€ ํ ์‹œ์Šคํ…œ์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ์•Œ์•„๋ดค์–ด์š”. ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋…๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ๋‹ค์–‘ํ•œ ๋ฉ”์‹œ์ง• ํŒจํ„ด, ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ ์ ์šฉ ์‹œ ๊ณ ๋ ค์‚ฌํ•ญ๊นŒ์ง€! ์ •๋ง ๋งŽ์€ ๋‚ด์šฉ์„ ๋‹ค๋ค˜๋„ค์š”. ๐Ÿ˜Š

์ด๋Ÿฐ ๊ธฐ์ˆ ๋“ค์€ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์„ ๊ฐœ๋ฐœํ•  ๋•Œ ์ •๋ง ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์–ด์š”. ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ๋” ๋‚˜์€ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๊ณ , ์‹œ์Šคํ…œ์˜ ์•ˆ์ •์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋  ๊ฑฐ์˜ˆ์š”.

์—ฌ๋Ÿฌ๋ถ„๋„ ์ด์ œ RabbitMQ์™€ C#์„ ์ด์šฉํ•ด์„œ ๋ฉ‹์ง„ ๋ฉ”์‹œ์ง€ ํ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ์ฒ˜์Œ์—๋Š” ์–ด๋ ค์›Œ ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ํ•˜๋‚˜์”ฉ ์ฐจ๊ทผ์ฐจ๊ทผ ํ•ด๋‚˜๊ฐ€๋‹ค ๋ณด๋ฉด ์–ด๋Š์ƒˆ ์ „๋ฌธ๊ฐ€๊ฐ€ ๋˜์–ด ์žˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿ’ช

๊ธฐ์–ตํ•˜์„ธ์š”, ์ฝ”๋”ฉ์€ ์‹ค์ „์ด ์ค‘์š”ํ•ด์š”. ์ด๋ก ์œผ๋กœ ๋ฐฐ์šด ๋‚ด์šฉ์„ ์ง์ ‘ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๋ฉด์„œ ๊ฒฝํ—˜์„ ์Œ“์•„๊ฐ€์„ธ์š”. ๊ทธ๋ฆฌ๊ณ  ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ๊ณผ ํŠธ๋ Œ๋“œ์— ๊ด€์‹ฌ์„ ๊ฐ€์ง€๊ณ  ๊ณต๋ถ€ํ•˜๋Š” ๊ฒƒ๋„ ์žŠ์ง€ ๋งˆ์„ธ์š”!

์—ฌ๋Ÿฌ๋ถ„์˜ ๊ฐœ๋ฐœ ์—ฌ์ •์— ํ–‰์šด์ด ํ•จ๊ป˜ํ•˜๊ธฐ๋ฅผ ๋ฐ”๋ž„๊ฒŒ์š”. ์–ธ์  ๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์ด ๋งŒ๋“  ๋ฉ‹์ง„ ์„œ๋น„์Šค ์†Œ์‹์„ ๋“ค์„ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•˜๊ณ  ์žˆ์„๊ฒŒ์š”. ํ™”์ดํŒ…! ๐Ÿš€

๐Ÿ’ก ๋งˆ์ง€๋ง‰ ํŒ

๊ฐœ๋ฐœ์€ ํ˜ผ์ž ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ์—์š”. ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์ฐธ์—ฌํ•˜๊ณ , ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค๊ณผ ๊ฒฝํ—˜์„ ๊ณต์œ ํ•˜์„ธ์š”. ํ•จ๊ป˜ ์„ฑ์žฅํ•  ๋•Œ ๋” ํฐ ๋ฐœ์ „์„ ์ด๋ฃฐ ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ๋„ ๊ฐœ๋ฐœ์ž๋“ค์„ ์œ„ํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋Š” ๊ฑด ์–ด๋–จ๊นŒ์š”? ๐Ÿ˜‰

์ž, ์ด์ œ ์ •๋ง ๋์ด์—์š”! ๊ธด ๊ธ€ ์ฝ๋Š๋ผ ๊ณ ์ƒ ๋งŽ์œผ์…จ์–ด์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ๊ฐœ๋ฐœ ์ธ์ƒ์— ์ด ๊ธ€์ด ์กฐ๊ธˆ์ด๋‚˜๋งˆ ๋„์›€์ด ๋˜์—ˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์–ธ์ œ๋‚˜ ์—ด์ •์„ ์žƒ์ง€ ๋ง๊ณ , ์ฆ๊ฒ๊ฒŒ ์ฝ”๋”ฉํ•˜์„ธ์š”! ์•ˆ๋…•ํžˆ ๊ณ„์„ธ์š”~ ๐Ÿ‘‹