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

[PYTHON] 객체 생성의 비밀 2단계 : __new__와 __init__의 실행 순서 및 활용 방법 차이 해결

by Papa Martino V 2026. 3. 3.
728x90
__new__와 __init__
__new__와 __init__

 

파이썬에서 클래스를 정의하고 인스턴스를 생성할 때, 대부분의 개발자는 __init__ 메서드가 가장 먼저 호출된다고 생각합니다. 하지만 파이썬의 객체 생성 매커니즘은 생각보다 정교하며, 실제로는 생성(Construction)초기화(Initialization)라는 두 가지 명확한 단계로 나뉩니다. 이 과정을 이해하는 것은 싱글톤 패턴 구현, 불변 객체(Immutable Object) 커스텀, 또는 메타프로그래밍을 다루는 시니어 개발자에게 필수적인 지식입니다. 본 글에서는 __new____init__의 내부 동작 차이를 완벽하게 분석합니다.


1. 객체 생성의 타임라인: 누가 먼저인가?

파이썬에서 obj = MyClass()를 실행하면 내부적으로 두 개의 매직 메서드가 순차적으로 호출됩니다. 첫 번째는 메모리 공간을 할당하고 실제 객체를 만드는 __new__이며, 두 번째는 만들어진 객체에 속성값을 부여하는 __init__입니다.


2. __new__ vs __init__ 핵심 비교 분석

두 메서드의 역할과 특성을 한눈에 비교할 수 있도록 표로 정리했습니다.

주요 역할객체의 실제 생성 (메모리 할당)생성된 객체의 초기화 (상태 설정)
호출 순서1순위 (가장 먼저 실행)2순위 (__new__ 이후 실행)
메서드 타입정적 메서드 (Static Method 개념)인스턴스 메서드 (Instance Method)
반환값생성된 인스턴스를 반드시 반환반환값이 없음 (내부적으로 None 반환)
첫 번째 인자cls (클래스 자신)self (생성된 인스턴스)

3. __new__를 반드시 조작해야 하는 3가지 상황

일반적인 프로그래밍에서는 __init__만으로 충분하지만, 다음과 같은 방법이 필요할 때는 __new__를 오버라이딩해야 합니다.

첫째, 불변 객체(Immutable Types)의 상속

int, str, tuple과 같은 불변 객체는 이미 생성된 후에 값을 변경할 수 없습니다. 따라서 이들을 상속받아 값을 변형한 서브 클래스를 만들려면 __init__이 아닌, 객체가 생성되는 시점인 __new__에서 값을 결정해야 합니다.

둘째, 싱글톤(Singleton) 패턴의 구현

애플리케이션 전체에서 단 하나의 인스턴스만 존재해야 하는 경우, __new__ 메서드 내에서 기존에 생성된 인스턴스가 있는지 확인하고, 있다면 새로 생성하지 않고 기존 인스턴스를 반환하도록 제어할 수 있습니다.

셋째, 메타프로그래밍과 프레임워크 설계

객체가 생성되기 직전에 가로채서 로깅을 남기거나, 특정 조건에 따라 다른 클래스의 인스턴스를 반환하는 등 동적인 객체 생성이 필요할 때 사용됩니다.


4. Sample Example: 싱글톤 패턴과 실행 순서 확인

아래 코드는 __new____init__이 실행되는 순서를 증명하고, 이를 이용해 싱글톤 객체를 만드는 해결 방법을 보여줍니다.


class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        print("1. __new__ 호출: 인스턴스를 생성합니다.")
        if cls._instance is None:
            # 부모 클래스인 object의 __new__를 호출하여 실제 메모리 할당
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self, name):
        print(f"2. __init__ 호출: {name}으로 초기화합니다.")
        self.name = name

# 두 번의 인스턴스 생성 시도
obj1 = Singleton("첫 번째")
obj2 = Singleton("두 번째")

print(f"obj1 name: {obj1.name}")
print(f"obj2 name: {obj2.name}")
print(f"두 객체는 동일한가? {obj1 is obj2}")

# [출력 결과]
# 1. __new__ 호출...
# 2. __init__ 호출... (첫 번째)
# 1. __new__ 호출... (기존 인스턴스 반환)
# 2. __init__ 호출... (두 번째로 덮어씌워짐)
# 두 객체는 동일한가? True

5. 개발자가 자주 범하는 실수와 주의점

  • 반환값 누락: __new__에서 인스턴스를 반환하지 않으면 __init__은 절대 실행되지 않습니다. super().__new__(cls)를 호출하는 것을 잊지 마세요.
  • __init__의 반복 호출: 싱글톤 구현 시 __new__가 동일한 인스턴스를 반환하더라도, 파이썬은 매번 __init__을 호출합니다. 초기화 로직이 중복 실행되지 않도록 플래그를 두는 처리가 필요할 수 있습니다.
  • 인자 불일치: __new____init__은 동일한 인자를 전달받으므로 가변 인자(*args, **kwargs)를 활용해 유연하게 대처하는 것이 좋습니다.

6. 결론: 파이썬의 객체 철학 이해하기

파이썬에서 __new__는 '무(無)'에서 '유(有)'를 창조하는 조각가이며, __init__은 창조된 조각상에 옷을 입히고 이름을 붙이는 화가와 같습니다. 이 두 단계의 차이를 명확히 이해한다면, 단순히 클래스를 사용하는 수준을 넘어 파이썬 엔진이 객체를 다루는 방식을 제어할 수 있는 고수준의 프로그래밍이 가능해집니다.


글 내용의 출처 및 참고 문헌

  • Python Software Foundation: The Python Language Reference - Data Model
  • Fluent Python 2nd Edition (Luciano Ramalho): "Object References, Mutability, and Customizing Classes"
  • Effective Python (Brett Slatkin): "Item 50: Use __set_name__ and __init_subclass__ for Class Metaprogramming"
  • Stack Overflow: "Real-world use cases for __new__" (Community Discussion)
728x90