logo

[Python] 캡슐화와 정보 은닉

캡슐화는 객체지향 프로그래밍의 핵심 원칙 중 하나로, 객체의 일부 구현 내용과 그 구현 세부사항을 외부로부터 숨기는 것을 의미합니다. 즉, 객체의 상태(Data)와 행위(Methods)를 하나로 묶고, 어떤 부분은 공개하여 외부에서 사용할 수 있게 하면서, 다른 부분은 숨김으로써 외부에서 직접적인 접근을 방지하는 기법입니다.

 

장점

  1. 코드 안정성: 캡슐화를 통해 클래스 내부의 중요 데이터를 외부에서 임의로 접근하여 변경하는 것을 방지함으로써 프로그램의 안정성을 높일 수 있습니다. 이는 데이터의 무결성을 보장하는데 중요한 역할을 합니다.

  2. 인터페이스와 구현의 분리: 객체를 사용하는 사용자는 해당 객체가 '무엇을 하는지'는 알 수 있지만, '어떻게 그 일을 수행하는지'에 대한 세부사항은 몰라도 되는 구조가 됩니다. 이는 개발 과정에서 인터페이스에 집중할 수 있게 하며, 세부 구현 로직에 대한 이해 없이도 객체를 사용할 수 있게 합니다.

  3. 유지보수와 확장성: 내부 구현이 변경되어도 외부 인터페이스에는 영향을 주지 않기 때문에, 기존 코드를 쉽게 수정하거나 새로운 기능을 추가하는 등의 작업이 용이해집니다. 이는 프로그램의 확장성과 유지보수에 큰 장점을 제공합니다.

 

Python 코드 예시

Python에서는 접근 제한자인 public, protected, private과 같은 명시적인 선언 방법이 없지만, 일반적으로 멤버 변수나 메소드의 이름 앞에 언더바(_)를 붙여서 정보 은닉을 구현합니다.

  • _ : 단일 언더스코어로 시작하는 멤버는 protected로 간주됩니다. 이는 해당 멤버가 해당 클래스와 서브클래스에서만 접근 가능함을 의미하지만, 파이썬에서 강제되지는 않습니다.
  • __ : 더블 언더스코어로 시작하는 멤버는 private으로 취급됩니다. 클래스 내부에서만 접근 가능하며, 외부에서는 접근할 수 없습니다.
class Account:
    def __init__(self, owner, amount=0):
        self.owner = owner
        self.__balance = amount  # private 변수

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(f"입금 완료: 잔액은 {self.__balance}입니다.")
        else:
            print("잘못된 금액입니다.")

    def __display_balance(self):  # private 메소드
        print(f"현재 잔액: {self.__balance}")

acc = Account("홍길동", 1000)
acc.deposit(500)
# acc.__display_balance()  # 이 부분은 오류를 발생시킵니다. private 메소드이기 때문에 외부에서 접근할 수 없습니다.

위 예시에서 __balance는 private 변수로, 외부에서 직접 접근할 수 없으며 오직 클래스 내부의 메소드를 통해서만 값을 변경하거나 조회할 수 있습니다. 이러한 방식은 캡슐화 원칙을 따르는 좋은 예시로, 데이터 보호 및 안정성을 확보할 수 있습니다.


Python에서의 정보 은닉 실현 방법

Python에서 정보 은닉은 클래스 내에서 데이터를 숨기고, 외부에서 직접적인 접근을 제한하는 방법을 말합니다. 이는 클래스의 내부 구현을 외부로부터 보호하고, 객체의 상태가 예상치 못하게 변경되는 것을 방지하는 목적을 가집니다. Python은 완벽한 정보 은닉을 강제하는 메커니즘을 제공하지 않지만, 관례적으로 사용되는 방법들이 있습니다.

 

약한 정보 은닉: _ (싱글 언더스코어) 사용

Python에서 _ (싱글 언더스코어)를 변수 또는 메서드 앞에 붙이는 것은 약한 정보 은닉을 의미합니다. 이는 내부적으로 사용되는 변수 또는 메서드임을 나타냅니다. 구체적으로, 이 방법은 다른 모듈에서 이러한 이름들을 from module import *로 임포트할 때, 해당 이름들이 임포트되지 않도록 합니다. 그러나, 이는 단지 관례일 뿐이고, Python의 특성상 이러한 변수나 메서드에 직접 접근하는 것을 기술적으로 방지하지는 않습니다.

 

강력한 정보 은닉: __ (더블 언더스코어) 사용

더 강력한 정보 은닉 메커니즘은 __ (더블 언더스코어)를 변수나 메서드 이름 앞에 붙여서 사용하는 것입니다. 이렇게 하면 Python은 네임 맹글링(name mangling)을 통해 이러한 변수 또는 메서드의 이름을 변경합니다. 클래스명이 _ClassName__variable과 같이 변환되므로, 외부에서 이러한 이름으로는 직접적으로 접근할 수 없게 됩니다. 이 기법은 클래스를 상속할 때, 자식 클래스에서 부모 클래스의 메서드나 속성을 오버라이드하는 것을 방지하기 위해 주로 사용됩니다.

 

예제 코드를 통한 실습

class MyPrivateClass:
    def __init__(self):
        self.public_var = "I am public!"
        self._weak_private_var = "I am weakly private!"
        self.__strong_private_var = "I am strongly private!"

    def show_vars(self):
        print(self.public_var)
        print(self._weak_private_var)
        print(self.__strong_private_var)

obj = MyPrivateClass()
obj.show_vars()

# 외부에서 접근 시도
print(obj.public_var)
print(obj._weak_private_var)
# 아래 코드는 에러를 발생시킵니다.
# print(obj.__strong_private_var)
# `__strong_private_var`에 접근하기 위한 올바른 방법
print(obj._MyPrivateClass__strong_private_var)
 

한계

Python은 완벽한 정보 은닉을 제공하지 않습니다. ___를 사용하는 관례는 개발자 사이의 약속일 뿐, Python의 기본 언어 기능에 의해 강제되는 것은 아닙니다. 따라서, 정보 은닉의 정책은 클래스를 사용하는 개발자의 책임하에 있습니다.

 

대응 방법

정보 은닉을 효과적으로 유지하려면, 개발자 간의 명확한 커뮤니케이션이 필요합니다. 이름 규칙을 엄격하게 준수하고, 클래스의 내부 구현에 관한 문서를 잘 작성해야 하며, 코드 리뷰 과정에서 이러한 사항들이 지켜지고 있는지 철저히 검토하는 것이 중요합니다. 이러한 노력을 통해, 개발자들은 비록 Python이 완전한 정보 은닉을 지원하지 않더라도, 객체 지향 프로그래밍의 핵심 원칙 중 하나인 정보 은닉을 실천할 수 있습니다.

Previous
다형성