지난편에서는 모든 객체가 공유하는 클래스 변수와 각 객체가 독립적으로 소유하는 인스턴스 변수의 차이점 및 메모리 탐색 원리를 다루었습니다. 클래스를 통해 나만의 데이터 타입을 만들고 속성을 다루다 보면 자연스럽게 커다란 문제 하나와 마주치게 됩니다.

바로 객체 외부에서 누구나 마침표(.) 하나만 찍으면 객체 내부의 중요 변수 값을 아무런 제약 없이 임의로 수정하거나 삭제할 수 있다는 점입니다. 예를 들어 은행 계좌 객체의 잔액이 -1,000,000원이 되거나, 게임 캐릭터의 체력이 999,999로 통제 없이 변경될 수 있다면 해당 프로그램은 데이터의 신뢰성을 완전히 잃게 됩니다.

저 역시 초기에는 "내가 만든 코드인데 외부에서 변수를 직접 바꾼들 무슨 상관일까?" 하고 생각했지만, 프로젝트 규모가 커지면서 어디선가 실수로 바꾼 변수 하나 때문에 전체 시스템이 붕괴하는 아찔한 경험을 했습니다. 오늘은 객체 내부의 중요 데이터를 외부의 위험으로부터 안전하게 보호하는 캡슐화(Encapsulation)의 개념과 파이썬 비공개 속성(__) 활용법을 정리해 드립니다.


1. 캡슐화(Encapsulation)란 무엇인가?

캡슐화는 감기 약 캡슐을 떠올리면 쉽게 이해할 수 있습니다. 우리는 캡슐 약을 먹을 때 그 안에 들어있는 알갱이 약품들의 화학적 비율이나 성분을 일일이 알지 못해도, 약을 삼키면 감기가 낫는다는 알약 고유의 기능(메서드)만 활용합니다.

프로그래밍에서의 캡슐화 역시 두 가지 목적을 갖습니다.

  1. 데이터 보호: 중요 데이터(속성)를 감추어 외부에서 무분별하게 조작하지 못하도록 막습니다.

  2. 은닉화(Information Hiding): 복잡한 내부 구현 로직은 숨기고, 외부에는 검증된 안전한 인터페이스(메서드)만 노출합니다.


2. 파이썬의 비공개 속성(Private Attribute): 언더바 2개(__)의 비밀

타 언어(Java, C++ 등)에서는 private, public 같은 접근 제어자 키워드를 직접 명시하지만, 파이썬은 변수나 메서드 이름 앞에 언더바 2개(__)를 붙여 비공개 속성을 선언합니다.

Python
class Account:
    def __init__(self, owner, balance):
        self.owner = owner          # 공개 속성 (Public)
        self.__balance = balance    # 비공개 속성 (Private - 언더바 2개)

    # 잔액 조회를 위한 전용 메서드 (Getter 역할)
    def get_balance(self):
        return f"{self.owner}님의 현재 잔액: {self.__balance}원"

    # 입금을 위한 전용 메서드 (Setter 역할 - 내부 검증 로직 포함)
    def deposit(self, amount):
        if amount <= 0:
            print("[경고] 입금 금액은 0원보다 커야 합니다.")
            return
        self.__balance += amount
        print(f"[입금 완료] {amount}원이 입금되었습니다.")

이제 이 클래스를 사용해 외부에서 접근을 시도해 보겠습니다.

Python
acc = Account("김파이", 10000)

# 공개 속성은 외부 접근 가능
print(acc.owner)  # 출력: 김파이

# 비공개 속성 외부 직접 접근 시도
# print(acc.__balance) 
# AttributeError: 'Account' object has no attribute '__balance' 에러 발생!

# 직접 변경 시도 역시 불가능
acc.__balance = -50000  # 비공개 변수가 바뀌는 것이 아니라 새로운 변수가 생성됨

# 정의된 안전한 메서드를 통한 접근
acc.deposit(5000)      # 출력: [입금 완료] 5000원이 입금되었습니다.
print(acc.get_balance()) # 출력: 김파이님의 현재 잔액: 15000원

acc.__balance에 직접 접근하려고 하면 파이썬은 해당 속성이 존재하지 않는다는 에러(AttributeError)를 내뿜습니다. 이제 잔액 데이터는 오직 deposit() 같은 내부 검증 메서드를 거쳐서만 안전하게 변경될 수 있습니다.


3. 네임 맨글링(Name Mangling): 파이썬 비공개 속성의 진짜 원리

여기서 한 가지 재미있는 파이썬만의 특징이 있습니다. 파이썬의 비공개 속성(__)은 완벽하게 문을 잠그는 철통 보안이라기보다는, "개발자끼리의 강력한 약속이자 이름 변형"에 가깝습니다.

파이썬 내부에서는 변수명 앞에 __가 붙으면 이 변수의 이름을 _클래스명__변수명 형태로 몰래 바꾸어 버립니다. 이를 네임 맨글링(Name Mangling)이라고 부릅니다.

Python
# 네임 맨글링된 진짜 이름을 우회하여 접근하는 경우
print(acc._Account__balance)  # 출력: 15000 (접근 가능!)

acc._Account__balance처럼 바뀐 진짜 이름을 강제로 치고 들어오면 여전히 수정이 가능합니다. 파이썬의 철학 중 하나인 "우리는 모두 성숙한 어른이다(We are all consenting adults here)"에 따라, 시스템이 100% 강제로 막기보다는 개발자가 실수로 데이터를 건드리는 사고를 예방하는 데 초점을 맞추었기 때문입니다.


4. 캡슐화를 완성하는 Getter와 Setter 메서드

비공개 속성으로 보호된 데이터를 외부에서 읽거나 수정해야 할 때는 Getter(조회) 및 Setter(수정) 메서드를 제공하는 것이 정석입니다.

특히 Setter 메서드를 사용할 때는 데이터의 유효성을 검사하는 방어 로직을 작성할 수 있습니다.

Python
class Student:
    def __init__(self, name, age):
        self.name = name
        self.set_age(age)  # 생성 시에도 Setter를 거치도록 설정

    def get_age(self):
        return self.__age

    def set_age(self, age):
        # 나이가 음수로 들어오는 비정상적인 데이터를 차단하는 검증 로직
        if age < 0:
            print("[오류] 나이는 음수가 될 수 없습니다. 0세로 설정합니다.")
            self.__age = 0
        else:
            self.__age = age

이처럼 캡슐화를 적용하면 외부 사용자가 데이터를 잘못 입력하더라도 객체 내부의 검증 로직이 작동하여 잘못된 데이터가 저장되는 사태를 완벽하게 차단할 수 있습니다.


핵심요약

  • 캡슐화는 객체의 중요 데이터(속성)를 외부의 직접적인 변경으로부터 보호하고, 검증된 메서드만을 통해 데이터에 접근하게 만드는 기법입니다.

  • 변수명 앞에 언더바 2개(__)를 붙이면 비공개 속성이 되어 외부에서 직접 접근하거나 수정할 때 에러가 발생합니다.

  • 파이썬은 네임 맨글링(_클래스명__변수명) 기법으로 이름을 변형하여 속성을 보호하며, Getter/Setter 메서드를 통해 안전한 데이터 조작 환경을 구축합니다.