메시지 전달
메시지 전달이란?
메시지 전달Message Passing은 객체지향 프로그래밍OOP에서 객체들이 서로 상호작용하는 방법 중 하나로, 객체가 다른 객체에게 작업을 요청하거나 정보를 주고받는 방식을 의미합니다. OOP에서는 모든 객체가 독립적이며 자신의 데이터를 관리하고, 객체들 간의 협력은 메시지를 주고받는 형태로 이루어집니다. 이 메시지 전달 방식은 객체지향 프로그래밍의 핵심 개념 중 하나로, 객체 간의 결합도를 낮추고 시스템을 유연하게 설계할 수 있게 도와줍니다.
메시지 전달의 개념
메시지 전달은 객체가 다른 객체의 메서드를 호출하는 방식으로 이루어집니다. 객체는 자신이 직접적으로 알고 있는 객체에게만 메시지를 보낼 수 있으며, 보낸 메시지에 따라 수신 객체가 해당하는 메서드를 실행하게 됩니다. 이 방식은 현실 세계에서 사람들이 서로 소통하는 것과 유사합니다. 메시지를 주고받는 행위를 통해, 각 객체는 서로의 역할을 수행하며 프로그램을 구성하게 됩니다. 예를 들어, 도서관 관리 시스템에서 ‘대출’이라는 행위는 메시지를 통해 객체들 간에 전달될 수 있습니다. 사용자는 도서관에 “책을 빌리고 싶다"는 메시지를 전달하고, 도서관 객체는 책 객체에게 “대출 가능한지 확인하라"는 메시지를 전달할 수 있습니다.
public class User
{
public string Name { get; set; }
public void BorrowBook(Library library, int bookId)
{
library.RequestBorrow(this, bookId); // 도서관에 메시지 전달
}
}
public class Library
{
private List<Book> books = new List<Book>();
public void RequestBorrow(User user, int bookId)
{
var book = books.FirstOrDefault(b => b.Id == bookId);
if (book != null && book.IsAvailable())
{
book.Borrow(user); // 책 객체에 메시지 전달
Console.WriteLine($"{user.Name}님이 책을 대출했습니다.");
}
else
{
Console.WriteLine("책이 대출 불가능한 상태입니다.");
}
}
}
public class Book
{
public int Id { get; set; }
public bool IsBorrowed { get; private set; }
public bool IsAvailable() => !IsBorrowed;
public void Borrow(User user) => IsBorrowed = true;
}
위 예시에서 User 객체는 Library 객체에게 책을 대출해 달라는 요청 메시지를 전달합니다. Library 객체는 책이 대출 가능한지 확인한 후, Book 객체에게 대출 상태를 변경하도록 메시지를 전달합니다. 각 객체는 자신의 역할을 수행하면서 다른 객체와 협력하여 프로그램의 기능을 구현하게 됩니다.
메시지 전달의 중요성
결합도 감소
메시지 전달 방식은 객체들이 서로를 직접 참조하지 않고, 메시지라는 추상화된 방법을 통해 상호작용하게 합니다. 이는 객체 간의 결합도를 줄여, 코드 변경 시 다른 객체에 미치는 영향을 최소화할 수 있습니다.
캡슐화 유지
객체는 자신의 내부 상태를 메시지로 노출하지 않고, 외부에서 특정 요청을 처리할 수 있게 합니다. 이로 인해 객체는 자신의 데이터를 보호할 수 있으며, 외부에서 임의로 데이터를 변경할 수 없도록 합니다.
유연한 확장성
메시지 전달은 객체가 변경되더라도 다른 객체들과의 인터페이스만 유지되면 쉽게 확장할 수 있습니다. 새로운 기능을 추가할 때도 기존 객체 간의 관계를 유지하면서 메시지 전달 방식을 확장하면 됩니다.
메시지 전달 방식
객체 간 메시지 전달은 주로 메서드 호출 형태로 나타나지만, 이를 보다 고도화 하면 다음과 같은 방식으로도 확장할 수 있습니다. 다음은 이벤트 기반, 콜백, 메시지 큐에 대한 간단한 예제들을 추가하여 객체 간의 메시지 전달 방식을 설명하는 방식입니다.
이벤트 기반 메시지 전달
이벤트 기반 메시지 전달에서는 한 객체가 이벤트를 발생 시키고, 다른 객체가 이를 구독하여 특정 작업을 수행합니다.
public class Book
{
public string Title { get; set; }
// 이벤트 선언
public event Action BookBorrowed;
public Book(string title)
{
Title = title;
}
public void Borrow()
{
Console.WriteLine($"{Title} has been borrowed.");
// 이벤트 발생
BookBorrowed?.Invoke();
}
}
public class Library
{
public void LendBook(Book book)
{
// 이벤트 구독
book.BookBorrowed += OnBookBorrowed;
book.Borrow();
}
private void OnBookBorrowed()
=> Console.WriteLine("Library has been notified of the book being borrowed.");
}
public class Program
{
static void Main(string[] args)
{
Book book = new Book("C# Programming Basics");
Library library = new Library();
library.LendBook(book);
}
}
Book
객체는BookBorrowed
라는 이벤트를 발생시킵니다.Library
객체는 이 이벤트를 구독하여 책이 대출되면 추가 작업을 수행합니다.
콜백 방식 메시지 전달
콜백 방식은 한 객체가 다른 객체의 작업이 끝났을 때 실행할 코드를 미리 넘겨주는 방식입니다.
public class Book
{
public string Title { get; set; }
public Book(string title)
{
Title = title;
}
// 책 대출 메서드, 콜백을 받아 작업 완료 후 호출
public void Borrow(Action onBorrowed)
{
Console.WriteLine($"{Title} has been borrowed.");
// 콜백 실행
onBorrowed();
}
}
public class Library
{
public void LendBook(Book book)
{
// 콜백을 전달하여 대출 후에 작업 수행
book.Borrow(OnBookBorrowed);
}
private void OnBookBorrowed()
=> Console.WriteLine("Library has been notified of the book being borrowed.");
}
public class Program
{
static void Main(string[] args)
{
Book book = new Book("C# Programming Basics");
Library library = new Library();
library.LendBook(book);
}
}
Library
객체는LendBook
메서드에서Book
객체에 콜백을 넘깁니다.Book
객체는Borrow
메서드 작업이 완료된 후 콜백을 실행하여 작업을 마칩니다.
메시지 큐 방식 메시지 전달
비동기 시스템에서 메시지 큐를 사용하여 여러 객체 간의 메시지를 관리할 수 있습니다. 메시지를 전달하는 객체와 메시지를 수신하는 객체가 반드시 동시에 존재하지 않아도 되며, 메시지는 큐에 저장되어 나중에 처리될 수 있습니다.
using System;
using System.Collections.Generic;
using System.Threading;
public class MessageQueue
{
private Queue<Action> messages = new Queue<Action>();
// 메시지 큐에 메시지 추가
public void Enqueue(Action message) => messages.Enqueue(message);
// 메시지 처리
public void ProcessMessages()
{
while (messages.Count > 0)
{
Action message = messages.Dequeue();
message();
}
}
}
public class Book
{
public string Title { get; set; }
public Book(string title)
{
Title = title;
}
public void Borrow()
=> Console.WriteLine($"{Title} has been borrowed.");
}
public class Library
{
private MessageQueue messageQueue = new MessageQueue();
public void LendBook(Book book)
{
// 책을 대출하는 메시지를 큐에 추가
messageQueue.Enqueue(() => book.Borrow());
}
public void ProcessLibraryQueue()
{
// 메시지 큐 처리
messageQueue.ProcessMessages();
}
}
public class Program
{
static void Main(string[] args)
{
Book book = new Book("C# Programming Basics");
Library library = new Library();
// 메시지 큐에 대출 요청 추가
library.LendBook(book);
// 메시지 큐 처리
library.ProcessLibraryQueue();
}
}
Library
객체는LendBook
메서드를 통해 책 대출 작업을 메시지 큐에 추가합니다.ProcessLibraryQueue
메서드를 호출하여 큐에 있는 메시지를 처리합니다.- 이 방식은 비동기적으로 처리할 수 있어, 서로 다른 객체가 독립적으로 작업을 수행할 수 있습니다.
맺음말
메시지 전달은 객체지향 프로그래밍에서 객체들 간의 상호작용을 추상화하고, 객체 간의 결합도를 낮추는 중요한 방법입니다. 객체는 다른 객체와 직접적으로 연결되지 않고 메시지로 상호작용하므로, 유지보수성과 확장성이 뛰어난 프로그램을 구현할 수 있습니다. 메시지 전달을 효과적으로 활용하면 시스템의 유연성을 극대화할 수 있으며, 다양한 패턴과 함께 사용하여 강력한 소프트웨어 설계를 지원할 수 있습니다.