프로그래밍백엔드 파이썬 개발자

파이썬의 클래스 속성 데코레이터(@property)는 무엇이며, 어떻게 작동하고 왜 필요합니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

데코레이터 @property는 메서드를 클래스의 "가상" 속성으로 변환할 수 있게 해줍니다: 클래스 사용자에게는 일반 속성처럼 보이지만 Python 함수의 논리에 의해 제어됩니다. 원래 파이썬에서 모든 인스턴스 속성은 직접적으로 접근할 수 있었지만, 캡슐화를 지원하기 위해 인터페이스를 변경하지 않고 데이터 접근을 제어할 수 있는 메커니즘이 필요했습니다.

역사:

초기 파이썬 버전에서는 속성에 대한 접근을 제한할 수 있는 명시적인 메커니즘이 없었습니다. 캡슐화 문제는 규약(예: 언더스코어)으로 해결되었지만, 값의 저장/유효성 검증 논리를 변경하는 것은 호환성을 깨뜨리게 되었습니다. @property 데코레이터가 도입됨에 따라 메서드를 속성으로 선언하고, 게터와 세터, 딜리터를 추가하여 클래스의 이전 인터페이스를 유지할 수 있게 되었습니다.

문제:

나중에 필드의 유효성 검사나 값 계산 논리를 추가해야 할 경우, 전체 인터페이스를 재구성하는 것은 비용이 많이 듭니다 — 변수에 대한 모든 접근 지점을 변경해야 합니다. 이 때, 필드의 내부 구현이 클래스의 외부 소비자에게 노출되지 않아야 합니다. @property를 사용하면 접근을 쉽게 "가상화"할 수 있습니다.

해결책:

@property는 "인터페이스 보호가 있는 게터/세터 패턴"을 구현합니다: 계산 가능한 속성을 추가하거나, 클라이언트 코드를 변경하지 않고 값 설정을 제어할 수 있습니다.

코드 예:

class Temperature: def __init__(self, celsius): self._celsius = celsius @property def celsius(self): return self._celsius @celsius.setter def celsius(self, value): if value < -273.15: raise ValueError("절대 영도보다 낮은 온도입니다!") self._celsius = value @property def fahrenheit(self): return self._celsius * 9 / 5 + 32 # 사용 예 obj = Temperature(25) print(obj.celsius) # 25 print(obj.fahrenheit) # 77.0 obj.celsius = -300 # ValueError

주요 특징:

  • 클라이언트 인터페이스를 변경하지 않고 계산된, 유효성 검증된 또는 캐시된 속성을 구현할 수 있습니다.
  • 속성 인터페이스를 제공합니다(접근 시 괄호 없이).
  • 읽기, 쓰기 및 삭제를 모두 제어할 수 있습니다.

함정 질문들.

모든 클래스 속성에 property를 추가할 수 있으며 하위 호환성을 깨지 않습니까?

아니요. 속성이 공용이고 일반 변수로 사용되었다면 property로의 대체가 투명하게 가능합니다. 그러나 어느 곳에서 __dict__를 통해 접근하거나 type(obj.attr)를 통해 타입 검사를 수행했다면 예상치 못한 동작이 발생할 수 있습니다.

속성을 위한 세터만 선언할 수 있습니까?

아니요, 우선 게터가 필수입니다(@property가 있는 메서드), 그렇지 않으면 파이썬은 세터와 "연결"할 속성이 무엇인지 알 수 없습니다.

데코레이터 @property/@setter/@deleter의 순서는 무엇이며 그 이유는 무엇입니까?

항상 먼저 @property를 작성해야 합니다(속성 객체를 생성합니다), 그런 다음 메서드 이름을 통해 @<name>.setter와 @<name>.deleter를 추가합니다(이들은 이전에 생성된 property를 보완합니다).

class A: @property def value(self): ... @value.setter def value(self, v): ...

전형적인 오류와 안티 패턴

  • 클래스 외부에서 비공식 속성(예: self._celsius)에 직접 접근
  • 캡슐화 원칙 위반: 게터/세터에 불필요한 로직 포함
  • 이름 충돌로 인한 하위 클래스에서 property 재정의

실제 사례

부정적 케이스

클래스 속성이 공개되었던 경우, 이후에 공개 API 출시 후 property를 통해 계산된 속성을 추가했습니다. 이전 코드에서 속성에 대한 접근이 암묵적으로 동작 방식을 변경하거나 오류를 발생시킵니다.

장점:

  • 사용자가 속성 접근 방식을 변경할 필요 없음

단점:

  • 접근 조건이 세터/게터 논리에 의해 변동될 경우 코드에서 예상치 못한 오류 발생
  • 클라이언트가 __dict__에 직접 접근했을 경우 호환성이 낮음

긍정적 케이스

처음 설계 시 모든 필드를 비공개(하나의 언더스코어)로 정의하고 사용자는 메서드/properties를 통해 작업했습니다. 이후 property에 새로운 논리를 추가하는 것이 클라이언트 인터페이스 변경 없이 이루어졌습니다.

장점:

  • 캡슐화
  • 유효성 검사 및 계산을 쉽게 추가할 수 있음

단점:

  • 문서화를 위한 규율과 규약 준수가 필요; 완전한 보호를 위한 약한 개인 정보 보호(하나의 언더스코어는 충분하지 않음)