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

[PYTHON] 객체 생성의 비밀 : __new__와 __init__의 2가지 호출 순서와 역할 차이 및 해결 방법

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

__new__와 __init__의 2가지 호출 순서
__new__와 __init__의 2가지 호출 순서

 

 

파이썬에서 클래스를 정의할 때 가장 먼저 배우는 메서드는 단연 __init__입니다. 하지만 숙련된 개발자로 거듭나기 위해서는 그보다 앞서 실행되는 __new__의 존재를 반드시 이해해야 합니다. 많은 입문자가 __init__을 '생성자'라고 부르지만, 엄밀히 말해 파이썬에서 객체를 실제로 '생성'하는 것은 __new__이며, __init__은 생성된 객체를 '초기화'하는 역할을 수행합니다.

본 포스팅에서는 파이썬의 객체 지향 프로그래밍(OOP) 심층부에서 일어나는 메커니즘을 분석하고, 이를 활용해 싱글톤 패턴(Singleton Pattern)이나 불변 객체(Immutable Object)를 커스텀하는 전문적인 해결 방법을 제시합니다.


1. __new__와 __init__의 개념적 본질

파이썬 클래스가 인스턴스화될 때, 내부적으로는 type.__call__이 호출됩니다. 이 과정에서 두 가지 특수 메서드가 순차적으로 작동합니다. __new__는 클래스 자체를 인자로 받아 새로운 인스턴스를 메모리에 할당하고 반환하는 '정적 메서드' 성격이 강하며, __init__은 그렇게 만들어진 인스턴스(self)에 속성값을 부여하는 역할을 합니다.

2. 호출 순서 및 역할 분담 비교

두 메서드의 핵심적인 차이점을 명확히 이해하기 위해 아래와 같이 비교 분석표를 구성하였습니다.

특징 __new__(cls, ...) __init__(self, ...)
호출 순서 1순위 (객체 생성 시 가장 먼저 실행) 2순위 (객체 생성 후 속성 설정 시 실행)
주요 역할 인스턴스의 메모리 할당 및 반환 인스턴스의 상태 초기화
반환 값 반드시 생성된 객체(인스턴스)를 반환해야 함 아무것도 반환하지 않음 (None)
메서드 성격 스태틱 메서드(Static Method)와 유사 인스턴스 메서드(Instance Method)
사용 사례 싱글톤 구현, 불변 타입(int, str) 상속 커스텀 객체 속성(Attribute) 설정

3. Sample Example: 호출 로그 추적 및 싱글톤 구현

실제 코드를 통해 두 메서드가 어떤 시점에 실행되는지 확인하고, 이를 실무에서 어떻게 활용하여 문제를 해결하는지 살펴보겠습니다.

3-1. 호출 순서 확인 예제

class Trace:
    def __new__(cls, *args, **kwargs):
        print("1. __new__ 호출: 객체를 메모리에 할당합니다.")
        instance = super().__new__(cls)
        return instance

    def __init__(self, *args, **kwargs):
        print("2. __init__ 호출: 객체의 속성을 초기화합니다.")
        self.data = args[0]

obj = Trace("Hello Python")
# 실행 결과:
# 1. __new__ 호출: 객체를 메모리에 할당합니다.
# 2. __init__ 호출: 객체의 속성을 초기화합니다.
    

3-2. __new__를 이용한 싱글톤 패턴 해결 방법

전역적으로 단 하나의 인스턴스만 유지해야 하는 경우, __init__만으로는 해결할 수 없습니다. 이때 __new__를 오버라이딩하여 이미 생성된 인스턴스가 있는지 확인하는 로직을 구현합니다.

class DatabaseConnection:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            print("새로운 DB 연결 객체를 생성합니다.")
            cls._instance = super().__new__(cls)
        else:
            print("기존에 생성된 DB 연결 객체를 반환합니다.")
        return cls._instance

db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2) # True (두 변수는 동일한 객체를 가리킴)
    

4. 전문적인 활용: 불변 객체(Immutable) 커스텀

파이썬의 str, int, tuple 같은 불변 객체는 이미 생성된 후에 값을 변경할 수 없습니다. 따라서 이러한 클래스를 상속받아 동작을 수정하고 싶다면 __init__이 아닌 __new__에서 수정 로직을 처리해야 합니다. 이는 메타 프로그래밍이나 프레임워크 설계 시 매우 중요한 기술적 차이입니다.

5. 결론: 올바른 역할 분담의 중요성

대부분의 애플리케이션 개발에서는 __init__만으로 충분합니다. 하지만 라이브러리 개발, 디자인 패턴 적용, 혹은 시스템의 낮은 레벨에서의 객체 제어가 필요할 때 __new__의 호출 순서와 역할을 정확히 아는 것은 개발자의 역량을 가르는 척도가 됩니다. 객체 생성을 제어하려면 __new__를, 객체의 상태를 제어하려면 __init__을 사용하십시오.


내용의 출처 및 참조

  • Python Software Foundation, "Data Model - Special method names", Official Docs.
  • Fluent Python, Luciano Ramalho (O'Reilly) - Chapter 19: Dynamic Attributes and Properties.
  • Effective Python, Brett Slatkin (Pearson) - Item 50: Annotate Class Attributes with __set_name__.
  • Expert Python Programming, Michal Jaworski - Advanced Object-Oriented Programming.
728x90