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

[PYTHON] 클래스 변수와 인스턴스 변수의 3가지 차이점과 가려짐(Shadowing) 문제 해결 방법

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

클래스 변수(Class Variables)와 인스턴스 변수(Instance Variables)
클래스 변수(Class Variables) 와  인스턴스 변수(Instance Variables)

 

객체 지향 프로그래밍(OOP)을 지원하는 파이썬에서 클래스 변수(Class Variables)인스턴스 변수(Instance Variables)를 명확히 구분하는 것은 코드의 유지보수성과 직관성을 결정짓는 핵심 요소입니다. 초보 개발자뿐만 아니라 숙련된 개발자조차 흔히 실수하는 부분이 바로 이 두 변수의 혼용으로 발생하는 '가려짐(Shadowing)' 현상입니다. 본 포스팅에서는 두 변수의 근본적인 차이점을 심층 분석하고, 실무에서 마주칠 수 있는 가독성 저해 요소와 런타임 버그를 유발하는 쉐도잉 문제를 완벽하게 해결하는 전략을 제시합니다.


1. 클래스 변수 vs 인스턴스 변수: 핵심 개념과 3가지 차이점

파이썬에서 변수가 선언되는 위치에 따라 그 성격과 메모리 점유 방식이 완전히 달라집니다. 이를 정확히 이해해야 의도치 않은 데이터 공유나 메모리 낭비를 방지할 수 있습니다.

### 변수별 정의 및 특징 비교

구분 클래스 변수 (Class Variable) 인스턴스 변수 (Instance Variable)
선언 위치 클래스 내부, 메서드 외부 __init__ 등 메서드 내부 (self 이용)
메모리 공유 모든 인스턴스가 하나의 값을 공유 각 인스턴스마다 독립적인 공간 점유
접근 방식 ClassName.variable (권장) instance.variable
주요 용도 공통 상태 저장 (예: 전체 카운트, 설정값) 개별 객체의 고유 데이터 저장 (예: 이름, 나이)

2. 가려짐(Shadowing) 현상이란 무엇인가?

파이썬의 속성 조회 메커니즘은 인스턴스 네임스페이스 → 클래스 네임스페이스 → 상위 클래스 네임스페이스 순으로 진행됩니다. 가려짐(Shadowing)은 클래스 변수와 동일한 이름을 가진 인스턴스 변수를 생성할 때 발생합니다.

이 경우, 개발자는 클래스 변수를 수정한다고 착각하지만 실제로는 해당 인스턴스에만 국한된 새로운 변수가 생성되어 클래스 변수를 '가려버리게' 됩니다. 이는 로직의 불일치를 초래하는 위험한 상황입니다.

가려짐 현상의 메커니즘

  1. 인스턴스를 통해 변수에 접근하여 값을 할당하려고 할 때(self.var = value), 파이썬은 해당 인스턴스의 __dict__에 값을 씁니다.
  2. 기존에 같은 이름의 클래스 변수가 있었더라도, 이제 해당 인스턴스에서 그 이름을 호출하면 클래스 변수가 아닌 방금 생성된 인스턴스 변수가 호출됩니다.
  3. 결과적으로 클래스 전체의 공통 데이터가 업데이트되지 않고 특정 객체만 변질되는 현상이 발생합니다.

3. [Sample Example] 쉐도잉으로 인한 버그 시나리오

다음은 실무에서 빈번하게 발생하는 잘못된 사용 사례와 이를 올바르게 수정한 코드 예시입니다.

### ❌ 문제가 발생하는 코드 (Shadowing 발생)

class Employee:
    company_name = "TechCorp"  # 클래스 변수

    def __init__(self, name):
        self.name = name

emp1 = Employee("Alice")
emp2 = Employee("Bob")

# 실수: 인스턴스를 통해 클래스 변수를 바꾸려 시도함
emp1.company_name = "GlobalSoft" 

print(emp1.company_name) # "GlobalSoft" (인스턴스 변수가 생성되어 가려짐)
print(emp2.company_name) # "TechCorp" (클래스 변수는 그대로 유지됨)
print(Employee.company_name) # "TechCorp" (의도한 전체 변경 실패)

### ✅ 올바른 해결 방법 (명시적 접근)

class Employee:
    company_name = "TechCorp"

    @classmethod
    def change_company(cls, new_name):
        cls.company_name = new_name # 클래스 메서드를 통한 명시적 수정

emp1 = Employee("Alice")
emp2 = Employee("Bob")

# 클래스 이름을 통해 직접 접근하거나 클래스 메서드 활용
Employee.company_name = "GlobalSoft"

print(emp1.company_name) # "GlobalSoft"
print(emp2.company_name) # "GlobalSoft"

4. 가독성 및 유지보수 향상을 위한 5가지 실무 수칙

  1. 명시적인 호출: 클래스 변수는 반드시 ClassName.variable_name 형태로 호출하여 가독성을 높입니다. self를 사용하면 인스턴스 변수로 오해받기 쉽습니다.
  2. 불변성 유지: 가급적 클래스 변수는 상수(Constant)처럼 취급하고, 런타임 중에 값을 빈번하게 변경해야 한다면 별도의 관리 클래스를 설계하십시오.
  3. 네이밍 컨벤션: 클래스 변수가 상수의 성격을 띤다면 대문자(UPPER_CASE)를 사용하여 인스턴스 변수와 시각적으로 분리하십시오.
  4. 캡슐화 활용: _(protected) 또는 __(private) 접두사를 활용하여 외부에서 의도치 않게 클래스 속성을 건드리지 못하도록 제어하십시오.
  5. 문서화: 해당 변수가 클래스 수준에서 공유되어야 하는 이유를 Docstring에 명시하여 협업 시 혼선을 방지하십시오.

5. 결론: 왜 이 구분이 중요한가?

파이썬은 유연한 언어이지만, 그 유연함이 때로는 독이 됩니다. 클래스 변수와 인스턴스 변수의 경계를 모호하게 사용하는 코드는 가독성 저하, 예상치 못한 메모리 참조 오류, 그리고 디버깅이 어려운 쉐도잉 버그를 양산합니다. 객체의 고유 상태는 self로, 객체 간의 공통 데이터는 클래스명으로 접근하는 원칙만 지켜도 코드의 질은 비약적으로 상승합니다. 오늘 소개한 3가지 차이점과 해결 방법을 통해 더 견고한 파이썬 애플리케이션을 설계해 보시기 바랍니다.


참고 문헌 및 출처

  • Python Software Foundation. "Classes - Python 3.12 Documentation."
  • Real Python. "Instance, Class, and Static Methods Demystified."
  • Fluent Python by Luciano Ramalho (O'Reilly Media).
  • Effective Python: 90 Specific Ways to Write Better Python by Brett Slatkin.
728x90