본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] 객체 지향 설계를 바꾸는 Final과 ClassVar 활용 방법 2가지와 실무적 제약 해결

by Papa Martino V 2026. 3. 14.
728x90

Final과 ClassVar 활용
Final과 ClassVar 활용

 

파이썬은 동적 타이핑 언어로서의 유연함을 자랑하지만, 대규모 프로젝트나 엄격한 엔터프라이즈 환경에서는 그 유연함이 때로는 독이 되기도 합니다. 특히 클래스 내부에서 변수의 의도를 명확히 하고, 수정되어서는 안 될 값을 보호하는 것은 코드의 안정성을 결정짓는 핵심 요소입니다. 본 포스팅에서는 Python 3.8 이상에서 도입된 typing.Final과 클래스 네임스페이스 관리를 위한 typing.ClassVar의 깊이 있는 차이점을 분석하고, 런타임 강제성이 없는 파이썬 환경에서 이를 어떻게 실무적으로 활용하여 설계 결함을 해결할 수 있는지 다룹니다.


1. 상수와 클래스 변수의 설계 철학

전통적인 Java나 C++와 달리 파이썬은 언어 차원에서 private이나 constant를 물리적으로 강제하지 않습니다. 관례적으로 언더스코어(_)를 사용해 접근 제한을 표시해 왔으나, typing 모듈의 발전은 이를 정적 분석(Static Analysis) 단계에서 검증할 수 있게 만들었습니다.

Final: 재할당 금지의 선언

Final은 이름 그대로 해당 변수가 한 번 초기화되면 다시는 재할당될 수 없음을 명시합니다. 이는 클래스 속성뿐만 아니라 지역 변수, 전역 변수에도 적용될 수 있습니다.

ClassVar: 인스턴스와의 격리

ClassVar는 특정 변수가 개별 인스턴스(Instance)의 소유가 아닌, 클래스 자체의 소유임을 명확히 합니다. 이는 메모리 절약과 공유 상태 관리에 필수적입니다.


2. Final과 ClassVar의 핵심 차이 및 제약 사항 비교

두 타입 힌트는 목적 자체가 다르지만, 클래스 내부에서 상수를 정의할 때 혼동하기 쉽습니다. 아래 표를 통해 3가지 관점에서 차이를 정리했습니다.

비교 항목 typing.Final typing.ClassVar
주요 목적 값의 재할당 방지 (상수화) 인스턴스 변수와 클래스 변수 구분
적용 범위 변수, 메서드, 클래스 전체 클래스 속성 (Class Attribute) 한정
정적 검사 (Mypy) 재할당 시 에러 발생 인스턴스를 통한 수정 시 경고
런타임 강제성 없음 (값 변경 가능) 없음 (값 변경 가능)

3. 실무적 제약 사항과 해결 방법

파이썬 타입 힌트 시스템에는 입문자가 반드시 알아야 할 '강제성의 부재'라는 제약이 있습니다. Final로 선언했더라도 런타임에서 obj.FINAL_VAR = new_value를 수행하면 파이썬 인터프리터는 아무런 에러를 내뱉지 않습니다.

해결책: Mypy와 프로퍼티의 조합

런타임에서도 값을 보호해야 한다면 @property 데코레이터를 사용하여 setter를 구현하지 않는 방식을 병행해야 합니다. Final은 개발 단계에서의 린팅(Linting)을 담당하고, 프로퍼티는 실제 실행 환경에서의 무결성을 담당하는 2중 방어 체계를 구축하는 것이 모범 사례입니다.


4. Sample Example: 실제 프로젝트 적용 사례

다음은 데이터베이스 연결 설정을 관리하는 클래스에서 두 기능을 혼합하여 사용하는 예시 코드입니다.


from typing import Final, ClassVar

class DatabaseConfig:
    # 모든 인스턴스가 공유하는 클래스 변수
    CONNECTION_COUNT: ClassVar[int] = 0
    
    # 변경되어서는 안 되는 설정값 (Final)
    TIMEOUT: Final[int] = 30

    def __init__(self, db_name: str):
        self.db_name: Final[str] = db_name  # 인스턴스별로 한 번 설정 후 고정
        DatabaseConfig.CONNECTION_COUNT += 1

# 올바른 사용
config = DatabaseConfig("Production_DB")

# Mypy에서 에러로 잡아내는 케이스
# config.TIMEOUT = 60           # Error: Cannot assign to final attribute
# config.db_name = "Dev_DB"     # Error: Cannot assign to final attribute

5. 결론: 언제 무엇을 써야 하는가?

1. 설정값, 수학적 상수, 고정된 ID 등을 정의할 때는 Final을 사용하십시오.
2. 카운터, 공유 캐시, 설정 템플릿 등 모든 인스턴스가 동일한 주소를 참조해야 하는 데이터에는 ClassVar를 사용하십시오.
3. 만약 클래스 레벨에서 절대 변하지 않는 상수를 만들고 싶다면 ClassVar[Final[int]]와 같이 중첩하여 선언하는 것이 가장 완벽한 의도 전달 방법입니다.


출처 및 참고 문헌

  • Python Software Foundation. (2024). PEP 591 – Adding a final qualifier to typing.
  • Python Software Foundation. (2024). PEP 526 – Syntax for Variable Annotations.
  • Mypy Documentation. "Final names, methods and classes".
  • Real Python. "Python Type Checking (Guide)".
728x90