안녕하세요! 지난 시간에는 상속(Inheritance)과 다형성(Polymorphism)을 통해 코드를 재사용하고, 다양한 객체들이 유연하게 동작하도록 만드는 방법을 알아보았습니다. 이제 OOP의 강력한 장점들을 조금씩 느끼고 계실 거예요.
이번 시간에는 객체지향 프로그래밍의 또 다른 중요한 원칙이자, 데이터의 안전성과 코드의 유지보수성을 높이는 데 필수적인 개념인 **캡슐화(Encapsulation)**와 파이썬에서의 접근 제한자(Access Modifiers) 개념에 대해 알아보겠습니다.
캡슐화는 데이터와 그 데이터를 다루는 기능을 하나로 묶고, 외부로부터 데이터를 보호하는 것을 의미합니다. 그럼, 캡슐화가 무엇이고, 파이썬에서 이를 어떻게 구현하는지 함께 살펴볼까요?
Part 1: 캡슐화 (Encapsulation) - 데이터와 기능을 하나로 묶고 보호하기
캡슐화는 객체의 **데이터(속성)**와 그 데이터를 다루는 **기능(메서드)**을 하나의 단위(클래스)로 묶고, 외부에서 객체 내부의 데이터를 직접 접근하거나 조작하는 것을 제한하여 데이터를 보호하는 객체지향의 원칙입니다.
마치 약 캡슐 안에 약 성분(데이터)과 그 성분을 안전하게 보관하는 기술(메서드)을 담아두고, 캡슐 겉면만 보고 사용법을 아는 것처럼, 객체 외부에서는 메서드를 통해 간접적으로만 객체의 상태에 접근하도록 하는 것입니다.
1. 캡슐화의 목적 및 중요성
- 데이터 보호 및 무결성 유지: 외부에서 객체 내부의 데이터를 함부로 변경하지 못하도록 막아, 데이터가 예상치 못한 상태가 되는 것을 방지합니다. (예: 계좌 잔액을 음수로 직접 설정하는 것 방지)
- 코드의 응집도 증가: 관련 있는 데이터와 기능을 한 클래스 안에 묶어 관리하므로 코드의 응집도(Cohesion)가 높아집니다.
- 유지보수 및 확장 용이: 객체 내부 구현이 외부로부터 숨겨지므로, 내부 구현이 변경되어도 외부 코드에는 영향을 미치지 않아 유지보수와 확장이 쉬워집니다.
- 사용 편의성: 복잡한 내부 로직을 숨기고, 간단한 메서드 호출을 통해 객체를 다룰 수 있게 합니다.
Part 2: 파이썬의 접근 제한자 개념 - 이름 규칙에 따른 약속
다른 객체지향 언어(예: Java의 public, protected, private)와 달리, 파이썬은 변수나 메서드에 대한 엄격한 **접근 제한 키워드(Access Modifier Keywords)**를 제공하지 않습니다. 대신 **이름 규칙(Naming Convention)**을 사용하여 해당 속성이나 메서드가 외부에서 어떻게 사용되기를 '의도'하는지 개발자에게 알려주는 방식을 사용합니다.
파이썬에서는 모든 속성과 메서드가 기본적으로 **공개(Public)**입니다. 하지만 아래와 같은 이름 규칙을 통해 개발자들 간의 약속을 만듭니다.
1. 공개 (Public) 속성/메서드
- 가장 일반적인 형태입니다. 이름 앞에 특별한 기호가 붙지 않습니다.
- 클래스 내부와 외부 어디에서든 자유롭게 접근하고 사용할 수 있습니다.
- 대부분의 속성과 메서드가 이 형태로 정의됩니다.
예시:
# 파일 이름: access_public.py
class Product:
def __init__(self, name, price):
self.name = name # 공개 속성
self.price = price # 공개 속성
def get_info(self): # 공개 메서드
return f"상품명: {self.name}, 가격: {self.price}원"
# 객체 생성
my_product = Product("키보드", 80000)
# 공개 속성에 직접 접근 및 변경 (외부에서 가능)
print(f"상품명: {my_product.name}")
my_product.price = 75000 # 직접 변경 가능
print(f"새로운 가격: {my_product.price}")
# 공개 메서드 호출
print(my_product.get_info())
[VS Code 터미널 출력]

2. 보호된 (Protected) 속성/메서드 - 단일 밑줄(_)
- 이름 앞에 **밑줄 하나(_)**를 붙입니다. (예: _protected_attribute, _protected_method())
- 규칙이 아닌 관례: 파이썬 인터프리터는 이를 특별히 다르게 처리하지 않습니다. 즉, 외부에서 여전히 직접 접근 가능합니다. 하지만 개발자들 사이에서는 "이것은 클래스 내부에서 사용되거나 상속받은 자식 클래스에서만 접근하는 것을 권장한다"는 의미의 약속입니다.
- 용도: 클래스 내부에서만 사용되거나, 자식 클래스에서 확장/재정의될 가능성이 있는 내부 구현 상세를 나타낼 때 사용됩니다.
예시:
# 파일 이름: access_protected.py
class Account:
def __init__(self, owner, balance):
self.owner = owner
self._balance = balance # 보호된 속성 (관례적으로)
def _update_balance(self, amount): # 보호된 메서드 (관례적으로)
"""내부적으로 잔액을 업데이트하는 메서드"""
self._balance += amount
print(f"내부적으로 잔액 업데이트: {self._balance}")
def deposit(self, amount):
if amount > 0:
self._update_balance(amount) # 내부 메서드 호출
print(f"{amount}원 입금 완료. 현재 잔액: {self._balance}원")
else:
print("0원 이상만 입금 가능합니다.")
# 객체 생성
my_account = Account("김은행", 10000)
# 보호된 속성에 외부에서 직접 접근 (가능하지만 권장하지 않음)
print(f"잔액 (직접 접근): {my_account._balance}원")
my_account._balance = 15000 # 직접 변경도 가능 (하지 않는 것이 좋음)
print(f"잔액 (직접 변경 후): {my_account._balance}원")
# 보호된 메서드 외부에서 호출 (가능하지만 권장하지 않음)
my_account._update_balance(2000)
print(f"잔액 (보호된 메서드 호출 후): {my_account._balance}원")
# 공개된 메서드를 통한 정상적인 사용
my_account.deposit(5000)
[VS Code 터미널 출력]

3. 비공개 (Private) 속성/메서드 - 이중 밑줄(__)
- 이름 앞에 **밑줄 두 개(__)**를 붙입니다. (예: __private_attribute, __private_method())
- 이름 맹글링 (Name Mangling): 파이썬 인터프리터는 __로 시작하는 속성이나 메서드 이름을 컴파일 시 자동으로 _클래스이름__원래이름 형태로 변경합니다. (예: __private_attribute는 _ClassName__private_attribute로 변경됨)
- 용도: 클래스 내부에서만 사용하도록 강력하게 의도된 속성이나 메서드입니다. 외부에서의 직접 접근을 사실상 막는 효과를 줍니다. (완전히 불가능한 것은 아니지만, 직접 접근 시 이름 맹글링된 이름을 사용해야 하므로 어렵습니다.)
예시:
# 파일 이름: access_private.py
class User:
def __init__(self, username, password):
self.username = username
self.__password = password # 비공개 속성 (이름 맹글링됨)
self.__login_attempts = 0 # 비공개 속성
def __check_password(self, input_password): # 비공개 메서드
"""내부적으로 비밀번호를 확인하는 메서드"""
if input_password == self.__password:
self.__login_attempts = 0 # 성공 시 시도 횟수 초기화
return True
else:
self.__login_attempts += 1 # 실패 시 시도 횟수 증가
return False
def login(self, input_password): # 공개 메서드 (비공개 메서드 사용)
if self.__login_attempts >= 3:
print("로그인 시도 횟수 초과. 계정이 잠겼습니다.")
return False
if self.__check_password(input_password): # 비공개 메서드 호출
print(f"{self.username}님, 로그인 성공!")
return True
else:
print(f"로그인 실패: 비밀번호가 틀렸습니다. (시도 횟수: {self.__login_attempts})")
return False
# 객체 생성
my_user = User("coder_kim", "mysecretpass")
# 비공개 속성/메서드에 외부에서 직접 접근 시도 (오류 발생!)
# print(my_user.__password) # AttributeError: 'User' object has no attribute '__password'
# my_user.__check_password("wrongpass") # AttributeError
# 이름 맹글링된 이름으로 접근 시도 (가능은 하나 권장하지 않음, 내부 구현에 의존)
# print(my_user._User__password) # 직접 접근 가능 (하지만 이렇게 하지 마세요!)
# 공개된 메서드를 통한 정상적인 사용
my_user.login("wrongpass")
my_user.login("wrongpass")
my_user.login("wrongpass") # 3회 실패
my_user.login("mysecretpass") # 계정 잠김 메시지 출력
print("\n--- 정상 로그인 시도 ---")
my_user2 = User("new_user", "1234")
my_user2.login("1234")
[VS Code 터미널 출력]

Part 3: 캡슐화 구현 요약
파이썬에서 캡슐화는 주로 다음과 같은 방식으로 구현됩니다.
- 속성 숨기기:
- 중요한 데이터(속성)를 비공개(__변수)로 정의하여 외부에서 직접 접근을 어렵게 합니다.
- 게터(Getter)와 세터(Setter) 메서드 사용:
- 비공개 속성에 접근하거나 값을 변경해야 할 경우, get_속성명() (게터) 또는 set_속성명(value) (세터)와 같은 공개(Public) 메서드를 정의하여 간접적으로 접근하도록 합니다.
- 이를 통해 데이터에 대한 유효성 검사, 로깅 등 추가적인 로직을 삽입할 수 있어 데이터 무결성을 높입니다. (다음 포스팅에서 더 자세히 다룰 예정입니다.)
예시: 간단한 게터/세터
# 파일 이름: encapsulation_getter_setter.py
class Temperature:
def __init__(self, celsius):
self.__celsius = celsius # 비공개 속성
# 게터 메서드 (온도 가져오기)
def get_celsius(self):
return self.__celsius
# 세터 메서드 (온도 설정)
def set_celsius(self, value):
if not isinstance(value, (int, float)):
raise TypeError("온도는 숫자여야 합니다.")
if value < -273.15: # 절대 0도 이하 불가
raise ValueError("온도는 절대 0도(-273.15) 이상이어야 합니다.")
self.__celsius = value
print(f"온도가 {self.__celsius}도로 설정되었습니다.")
# 객체 생성
temp = Temperature(25)
# 게터로 값 가져오기
print(f"현재 온도: {temp.get_celsius()}도")
# 세터로 값 설정 (유효성 검사 포함)
try:
temp.set_celsius(30)
temp.set_celsius(-300) # 오류 발생 시도
except (TypeError, ValueError) as e:
print(f"오류: {e}")
# 직접 접근 시도 (오류 발생)
# print(temp.__celsius) # AttributeError
[VS Code 터미널 출력]

마무리하며
이번 시간에는 객체지향 프로그래밍의 중요한 원칙인 **캡슐화(Encapsulation)**와 파이썬에서 이를 구현하는 **접근 제한자 개념(이름 규칙)**에 대해 알아보았습니다.
- 캡슐화: 데이터와 기능을 묶고 외부로부터 데이터를 보호하는 것.
- 접근 제한자: 파이썬은 엄격한 키워드 대신 이름 앞의 밑줄(_, __)을 통해 속성/메서드의 의도된 접근 수준(공개, 보호된, 비공개)을 나타냅니다.
- _변수: 보호된 (Protected) - 외부 접근 가능하지만, 내부 사용 권장 (관례)
- __변수: 비공개 (Private) - 이름 맹글링을 통해 외부 직접 접근 어렵게 만듦 (강력한 내부 사용 권장)
캡슐화를 통해 데이터의 무결성을 높이고, 코드를 더욱 안정적이고 유지보수하기 쉽게 만들 수 있습니다.
다음 포스팅에서는 클래스와 OOP의 고급 개념인 **추상 클래스(Abstract Class)**와 **인터페이스(Interface)**에 대해 알아보겠습니다.
궁금한 점이 있다면 언제든지 질문해주세요! 다음 포스팅에서 만나요!
'Python' 카테고리의 다른 글
7-2. 제너레이터(Generator)와 yield 키워드 (0) | 2025.07.03 |
---|---|
7-1. 리스트/딕셔너리 컴프리헨션 심화 (0) | 2025.07.02 |
6-6. 오버라이딩과 super() (0) | 2025.07.01 |
6-5. 상속과 다형성 (0) | 2025.07.01 |
6-2. 생성자(__init__)와 인스턴스 변수 (0) | 2025.06.29 |