정보 은닉과 경계 설정

모듈화 설계에서 정보 은닉Information Hiding과 경계 설정은 시스템의 유지보수성, 확장성을 높이는 중요한 원칙입니다. 정보 은닉은 객체의 세부 구현을 감추고, 외부에 노출되는 인터페이스를 통해 상호작용함으로써 모듈 간 의존성을 최소화합니다. 경계 설정은 각 모듈이 독립적으로 변화할 수 있도록 경계를 명확하게 구분하고, 불필요한 결합을 방지하는 설계 전략입니다. 이 글에서는 정보 은닉을 중심으로 모듈 경계를 설정하고 관리하는 방법을 실무적 관점에서 설명합니다.

정보 은닉

정보 은닉Information Hiding은 객체의 내부 구현을 외부에서 볼 수 없도록 숨기고, 필요한 정보인터페이스만 외부에 제공하는 원칙입니다. 이를 통해 모듈 간 불필요한 의존성을 줄이고, 각 모듈의 독립성을 유지할 수 있습니다. 정보 은닉은 객체지향 설계에서 내부 구현과 외부 인터페이스를 분리함으로써, 시스템의 복잡성을 줄이고 유지보수성을 향상시킵니다.

정보 은닉과 캡슐화의 차이

정보 은닉Information Hiding과 캡슐화는 객체지향 설계에서 자주 혼용되지만, 서로 다른 개념입니다. 두 개념은 상호 보완적인 관계에 있으며, 시스템의 복잡성을 줄이고 유지보수성을 높이는 데 중요한 역할을 합니다. 각각의 차이점과 역할을 명확히 이해하는 것이 객체지향 설계를 효율적으로 적용하는 데 필요합니다.

캡슐화

캡슐화Encapsulation는 객체의 속성과 메서드를 하나의 단위로 묶어 외부에서 객체 내부에 직접 접근하지 못하게 보호하는 개념입니다. 캡슐화는 주로 데이터 보호에 중점을 두며, 객체의 상태(데이터)를 외부에서 직접 수정할 수 없도록 하고, 오직 객체 내부의 메서드를 통해서만 접근하게 합니다. 즉, 캡슐화는 데이터의 무결성을 유지하고, 객체가 의도치 않게 잘못 사용되는 것을 방지합니다.

정보 은닉

정보 은닉은 캡슐화보다 더 넓은 개념으로, 객체의 내부 동작을 외부에서 알 필요 없도록 하고, 객체가 어떻게 동작하는지보다는 무엇을 할 수 있는지에만 집중하게 만듭니다. 이를 통해 외부 모듈이 객체의 세부 구현에 의존하지 않게 하고, 객체의 내부 구현이 변경되더라도 외부에 영향을 미치지 않도록 합니다.

차이점 정리

구분캡슐화 Encapsulation정보 은닉Information Hiding
목적데이터를 보호하고, 객체 상태의 무결성 유지객체의 세부 구현을 감추고, 필요한 정보만 외부에 노출
적용 범위주로 데이터 보호에 중점모듈 간 상호작용과 구현 세부 사항 감추기에 중점
초점외부에서 객체의 데이터를 직접 수정할 수 없도록 막음객체의 인터페이스를 통해서만 상호작용하도록 하고, 내부 동작 감춤
연관성정보 은닉의 한 부분으로, 객체의 상태를 보호하는 역할캡슐화를 포함한 더 넓은 개념으로, 객체의 구현을 감추고 경계를 설정함

예시를 통한 이해

public class Person
{
    // 캡슐화: 외부에서 직접 접근할 수 없는 private 필드
    private string name;
    // 캡슐화: 데이터를 보호하고, 내부 상태에 접근할 수 있는 메서드를 제공
    public string GetName()
    {
        return name;
    }
    public void SetName(string newName)
    {
        name = newName;
    }
}
public class Employee : Person
{
    // 정보 은닉: 외부에서 세부 구현을 알 필요 없이, 필요한 메서드만 제공
    public double CalculateSalary()
    {
        // 급여 계산 로직 (구현 세부 사항은 외부에 숨겨짐)
        return baseSalary + bonus;
    }
}
  • 캡슐화: Person 클래스의 name 필드는 private로 선언되어 외부에서 직접 접근할 수 없습니다. 이 필드는 GetName()SetName() 메서드를 통해서만 접근할 수 있습니다. 이렇게 데이터를 보호하는 것이 캡슐화의 핵심입니다.
  • 정보 은닉: Employee 클래스는 급여 계산 로직을 외부에 노출하지 않고, CalculateSalary() 메서드를 통해서만 급여 계산 결과를 반환합니다. 내부에서 어떤 방식으로 급여가 계산되는지는 외부에서 알 필요가 없으며, 이는 정보 은닉을 통해 구현 세부 사항을 감추는 예입니다.

모듈 경계 설정과 정보 은닉

모듈 경계 설정은 시스템 내에서 각 모듈이 다른 모듈과 어떻게 상호작용 할 지를 정의하는 과정입니다. 정보 은닉은 이러한 경계 설정에서 중요한 역할을 합니다. 모듈이 외부에 노출하는 것은 명확하게 정의된 인터페이스뿐이며, 내부 구현은 감춰져 있어야 합니다. 이를 통해 모듈 간 결합도를 낮추고, 각 모듈이 독립적으로 변경될 수 있습니다.

예제: 모듈 경계 설정

다음은 도서 관리 시스템의 LibraryBorrowingService 클래스에서 정보 은닉과 모듈 경계 설정이 어떻게 구현되는지를 설명하는 예시입니다.

public class Library
{
    private List<Book> books = new List<Book>();
    // 외부에서 직접 접근하지 않고, 인터페이스를 통해 접근
    public List<Book> SearchBooks(string title)
    {
        return books.Where(b => b.Title.Contains(title)).ToList();
    }
    public void AddBook(Book book)
    {
        books.Add(book);
    }
}
public class BorrowingService
{
    private Library library;
    // 정보 은닉: Library 내부 구현은 감추고, 필요한 메서드만 인터페이스를 통해 사용
    public BorrowingService(Library library)
    {
        this.library = library;
    }
    public List<Book> GetAvailableBooks(string title)
    {
        // 모듈 경계 설정: Library의 구현 세부 사항을 알 필요 없이, 메서드를 통해 상호작용
        return library.SearchBooks(title);
    }
}
  • Library 클래스는 책 목록(books)을 private으로 선언하여 외부에서 직접 접근하지 못하게 하고, 책 검색이나 추가는 메서드를 통해서만 가능하게 합니다. 외부에서는 books의 세부 구조나 구현에 접근할 수 없습니다.
  • BorrowingService는 Library의 내부 구현에 의존하지 않고 SearchBooks 메서드를 사용하여 필요한 책 정보를 가져옵니다. 이로 인해 Library 클래스가 내부적으로 변경되더라도, BorrowingService는 그 변화에 영향을 받지 않습니다.

정보 은닉과 경계 설정의 중요성

정보 은닉과 모듈 경계 설정은 실무에서 모듈 간 결합도를 줄이고, 독립적인 모듈 설계를 가능하게 합니다. 이를 통해 각 모듈이 독립적으로 변경될 수 있으며, 시스템의 복잡성을 줄여 유지보수성과 확장성을 높일 수 있습니다. 특히, 대규모 시스템에서는 모듈 경계가 명확해야 시스템 전반에 미치는 영향을 최소화하고, 각 모듈의 책임과 역할이 분명하게 구분되어야 합니다.

예시: 사용자 대여 정보 관리

BorrowingService가 사용자의 대여 기록을 관리할 때, 정보 은닉과 모듈 경계 설정이 어떻게 중요한 역할을 하는지 살펴보겠습니다.

public class BorrowingService
{
    private Dictionary<int, List<Book>> borrowingRecords = new Dictionary<int, List<Book>>();
    // 정보 은닉: 외부에서는 대여 기록 전체에 접근할 수 없고, 특정 사용자 기록만 가져올 수 있음
    public List<Book> GetBorrowingRecords(int userId)
    {
        if (borrowingRecords.ContainsKey(userId))
        {
            return new List<Book>(borrowingRecords[userId]);
        }
        return new List<Book>();
    }
    // 캡슐화: 대여 기록 추가는 메서드를 통해서만 가능
    public void AddBorrowingRecord(int userId, Book book)
    {
        if (!borrowingRecords.ContainsKey(userId))
        {
            borrowingRecords[userId] = new List<Book>();
        }
        borrowingRecords[userId].Add(book);
    }
}

정보 은닉과 모듈 경계 설정의 실무적 적용

  • BorrowingService 클래스는 사용자 대여 기록을 private 필드로 관리하고, 외부에서 직접 접근할 수 없도록 합니다. 대신, 특정 사용자의 대여 기록을 반환하는 메서드만 외부에 제공하여 필요한 정보만 노출합니다.
  • 대여 기록 추가는 외부에서 직접 리스트를 수정할 수 없고, AddBorrowingRecord 메서드를 통해서만 가능합니다. 이는 정보 은닉과 경계 설정을 통해 모듈 간의 상호작용을 제한하고, 모듈의 독립성을 보장하는 방식입니다.

정보 은닉과 모듈 경계 설정을 통한 유지보수성 향상

정보 은닉과 경계 설정을 잘 적용하면, 모듈 간의 결합도를 낮추고, 변경이 필요한 경우에도 다른 모듈에 영향을 최소화할 수 있습니다. 이는 시스템의 유지보수성을 크게 향상시키고, 확장성 있는 설계를 가능하게 합니다. 모듈의 경계를 명확하게 설정하면, 각 모듈이 자신만의 역할을 독립적으로 수행할 수 있고, 변경이 필요할 때도 다른 모듈과 충돌을 일으키지 않습니다.

맺음말

정보 은닉과 모듈 경계 설정은 객체지향 설계에서 매우 중요한 원칙으로, 시스템을 보다 견고하고 유연하게 만드는 데 기여합니다. 각 모듈의 내부 구현을 감추고, 명확한 경계를 통해 상호작용을 제한하면, 시스템은 더 독립적이고 유지보수성이 높은 구조로 발전할 수 있습니다.