상태 기반과 행동 기반 모듈화
상태 기반과 행동 기반 모듈화
모듈화는 소프트웨어 시스템을 더 작은 단위로 나누어 개발하고 관리하는 중요한 설계 원칙입니다. 이 과정에서 “상태 기반 모듈화"와 “행동 기반 모듈화"는 두 가지 주요 모듈화 방식으로, 시스템의 구조와 설계를 결정하는 데 중요한 역할을 합니다. 각각의 방식은 모듈을 정의하는 기준에 따라 차이가 있으며, 이를 통해 시스템의 유지보수성과 확장성을 높일 수 있습니다.
상태 기반 모듈화
상태 기반 모듈화는 객체나 모듈이 내부적으로 관리하는 상태를 기준으로 설계되는 방식입니다. 즉, 모듈의 상태나 데이터에 따라 해당 모듈이 정의됩니다. 상태 기반 모듈화는 객체의 상태가 중요한 역할을 하며, 상태를 유지하고 변경하는 방식에 따라 설계됩니다.
예시: 도서 관리 시스템에서의 상태 기반 모듈화
public class Book
{
public string Title { get; private set; }
public bool IsBorrowed { get; private set; }
public Book(string title)
{
Title = title;
IsBorrowed = false;
}
public void Borrow()
{
if (!IsBorrowed)
{
IsBorrowed = true;
}
else
{
throw new InvalidOperationException("Book is already borrowed.");
}
}
public void Return()
{
IsBorrowed = false;
}
}
Book
클래스는 책의 제목과 대출 상태라는 상태를 관리하는 상태 기반 모듈화의 예입니다.- 이 클래스는 내부 상태(
IsBorrowed
)에 따라 책을 대출하거나 반납하는 작업을 수행합니다.
상태 기반 모듈화의 장점
- 상태의 일관성 보장: 불변 객체를 사용하면 상태 변경이 발생하지 않으므로 시스템의 일관성을 유지할 수 있습니다.
- 동시성 처리에 유리: 상태 변경이 없기 때문에 동시성 문제를 줄일 수 있으며, 다중 스레드 환경에서 안전하게 작동할 수 있습니다.
상태 기반 모듈화의 한계
- 메모리 사용 증가: 불변 객체는 매번 새로운 객체를 생성하므로 메모리 사용량이 증가할 수 있습니다.
- 복잡한 상태 관리: 상태가 복잡한 경우 불변 객체를 사용하는 설계는 관리가 어려워질 수 있습니다.
행동 기반 모듈화
행동 기반 모듈화는 객체나 모듈이 수행하는 작업(행동)을 중심으로 설계됩니다. 즉, 모듈이 어떤 작업을 수행하는지, 어떤 기능을 제공하는지에 따라 설계가 이루어집니다. 이 방식에서는 상태보다는 객체의 행동이나 메서드가 중요하며, 특정 기능을 수행하는 책임이 강조됩니다.
예시: 도서 관리 시스템에서의 행동 기반 모듈화
public class BorrowingService
{
private readonly IBookRepository _bookRepository;
public BorrowingService(IBookRepository bookRepository)
{
_bookRepository = bookRepository;
}
public void BorrowBook(User user, int bookId)
{
var book = _bookRepository.FindById(bookId);
if (book == null)
{
throw new InvalidOperationException("Book not found.");
}
if (user.CanBorrowBook())
{
book.Borrow();
}
}
public void ReturnBook(User user, int bookId)
{
var book = _bookRepository.FindById(bookId);
if (book != null)
{
book.Return();
}
}
}
BorrowingService
클래스는 책을 빌리거나 반납하는 동작을 중심으로 설계된 행동 기반 모듈화의 예입니다.- 이 클래스는 사용자에게 책을 대출하거나 반납하는 행동을 제공하며, 내부 상태보다는 책과 관련된 비즈니스 로직을 실행합니다.
행동 기반 모듈화의 장점
- 비즈니스 규칙을 명확하게 표현: 비즈니스 로직이 모듈화되어 각 기능이 명확하게 구분되며, 유지보수와 확장이 용이합니다.
- 유연한 설계: 행동 기반으로 설계된 시스템은 비즈니스 요구 사항이 변경될 때도 쉽게 적응할 수 있습니다.
행동 기반 모듈화의 한계
- 상태 관리의 복잡성: 행동 기반 모듈화에서는 상태가 여러 서비스에서 관리될 수 있기 때문에, 복잡한 상태 변경이 필요한 경우 관리가 어려워질 수 있습니다.
- 코드 중복 가능성: 여러 행동 모듈이 동일한 상태를 처리할 때 코드 중복이 발생할 수 있습니다.
상태 기반 모듈화 vs. 행동 기반 모듈화
상태 기반 모듈화 | 행동 기반 모듈화 | |
---|---|---|
초점 | 객체의 상태나 데이터 관리 | 객체가 수행하는 행동이나 기능 |
장점 | 상태의 일관성 유지 및 관리 용이 | 특정 작업을 수행하는 기능 제공에 집중 |
단점 | 복잡한 비즈니스 로직에 적합하지 않을 수 있음 | 상태 관리가 필요할 때 복잡도가 증가할 수 있음 |
사용 예시 | 도메인 모델 설계, 엔티티 관리 | 서비스 계층, 비즈니스 로직 처리 |
실무에서의 적용
실무에서는 상태 기반 모듈화와 행동 기반 모듈화를 적절히 혼합하여 설계하는 것이 중요합니다. 도메인 모델이나 엔티티와 같은 객체는 상태 기반으로 설계하는 것이 일반적이며, 서비스 계층은 행동 기반으로 설계하여 비즈니스 로직을 처리할 수 있습니다.
- 상태 기반 모듈화는 도메인 엔티티가 내부 상태를 관리하고, 상태의 일관성을 유지하는 데 유리합니다.
- 행동 기반 모듈화는 복잡한 비즈니스 로직이나 기능을 모듈화하여, 행동을 중심으로 작업을 수행하는 데 유리합니다.
맺음말
상태 기반 모듈화와 행동 기반 모듈화는 각각의 방식이 가진 장점을 잘 이해하고, 상황에 맞게 사용하는 것이 중요합니다. 모듈화 설계에서는 시스템의 요구 사항에 맞게 이 두 가지 방식을 혼합하여 사용함으로써, 유지보수성과 확장성을 높일 수 있습니다.
심화 학습
도메인 모델과 상태 불변성
상태 기반 모듈화에서 중요한 개념은 상태 불변성immutability입니다. 상태 불변성은 객체의 상태가 변경되지 않도록 설계함으로써 시스템의 예측 가능성을 높이는 데 도움을 줍니다. 특히 도메인 모델에서는 상태가 변화할 수 없는 불변 객체로 설계하여 상태의 일관성을 보장하고, 예기치 않은 오류를 방지할 수 있습니다.
예시: 도서 관리 시스템에서의 상태 불변성 적용
public class Book
{
public string Title { get; }
public bool IsBorrowed { get; private set; }
public Book(string title)
{
Title = title;
IsBorrowed = false;
}
public Book Borrow()
{
if (IsBorrowed)
{
throw new InvalidOperationException("Book is already borrowed.");
}
return new Book(Title) { IsBorrowed = true };
}
public Book Return()
{
return new Book(Title) { IsBorrowed = false };
}
}
- 이 예시에서
Book
클래스는 불변 객체로 설계되었습니다. 도서가 대출되거나 반납될 때마다 새로운Book
객체가 생성되며, 원래 객체의 상태는 변경되지 않습니다. - 이를 통해 상태 불변성을 보장하여, 시스템의 예측 가능성과 신뢰성을 높일 수 있습니다.
상태 기반과 행동 기반의 혼합 설계
복잡한 시스템에서는 상태 기반 모듈화와 행동 기반 모듈화를 혼합하여 사용하는 것이 일반적입니다. 예를 들어, 도메인 엔티티는 상태 기반 모듈화로 설계하고, 서비스 계층은 행동 기반 모듈화를 사용하여 비즈니스 로직을 처리하는 방식입니다.
예시: 혼합된 모듈화 설계
public class BorrowingService
{
private readonly IBookRepository _bookRepository;
private readonly IUserService _userService;
public BorrowingService(IBookRepository bookRepository, IUserService userService)
{
_bookRepository = bookRepository;
_userService = userService;
}
public void BorrowBook(int userId, int bookId)
{
var user = _userService.GetUserById(userId);
var book = _bookRepository.FindById(bookId);
if (!user.CanBorrow())
{
throw new InvalidOperationException("User cannot borrow more books.");
}
// 상태 기반 모듈화를 활용한 도서 상태 변경
book.Borrow();
// 행동 기반 모듈화를 활용한 대출 로직 처리
_bookRepository.Save(book);
}
}
- 이 설계는 도서의 상태를 변경하는 부분에서 상태 기반 모듈화를 사용하고, 대출 로직을 처리하는 부분에서는 행동 기반 모듈화를 사용하여 혼합 설계의 예를 보여줍니다.
CQRS와의 연계
상태 기반 및 행동 기반 모듈화는 CQRSCommand Query Responsibility Segregation 패턴과도 잘 결합될 수 있습니다. CQRS는 명령Command과 조회Query를 분리하여 설계하는 방식으로, 상태 기반 모듈화는 조회 측면에서, 행동 기반 모듈화는 명령 측면에서 설계할 수 있습니다.
예시: CQRS와의 연계
// 상태 기반 조회 모듈
public class BookQueryService
{
private readonly IBookRepository _bookRepository;
public BookQueryService(IBookRepository bookRepository)
{
_bookRepository = bookRepository;
}
public Book GetBookById(int bookId)
{
return _bookRepository.FindById(bookId);
}
}
// 행동 기반 명령 모듈
public class BookCommandService
{
private readonly IBookRepository _bookRepository;
public BookCommandService(IBookRepository bookRepository)
{
_bookRepository = bookRepository;
}
public void BorrowBook(int bookId)
{
var book = _bookRepository.FindById(bookId);
book.Borrow();
_bookRepository.Save(book);
}
}
- BookQueryService는 상태 기반으로 도서 정보를 조회하는 역할을 하고, BookCommandService는 행동 기반으로 도서를 대출하는 명령을 처리합니다.
- 이와 같은 구조는 복잡한 시스템에서 명령과 조회를 분리하여 성능과 유지보수성을 높일 수 있습니다.