Home > CS > 2024 > 💾 [CS] 객체의 생성과 소멸 과정은 무엇일까요?

💾 [CS] 객체의 생성과 소멸 과정은 무엇일까요?
CS

💾 [CS] 객체의 생성과 소멸 과정은 무엇일까요?

  • 객체의 생성과 소멸 과정프로그램이 객체를 메모리에 할당하고 사용하는 과정과, 더 이상 필요하지 않을 때 메모리에서 해제하는 과정을 말합니다.
  • 객체 지향 프로그래밍(Object-Oriented Programming, OOP)에서 이 과정은 매우 중요한 개념으로, 객체가 어떻게 생성되고, 소멸되는지 이해하면 더 효율적이고 메모리 누수(Memory leak)가 없는 프로그램을 작성할 수 있습니다.

🙋‍♂️ 객체 지향 프로그래밍(Object-Oriented Programming, OOP)는 무엇일까요?

1️⃣ 객체의 생성 과정.

  • 객체가 생성될 때는 다음과 같은 과정을 거칩니다.
      1. 메모리 할당.
      1. 생성자 호출.
      1. 객체의 초기화.
      1. 메모리 주소 반환.

1️⃣ 메모리 할당.

  • 객체를 생성하기 위해 먼저 메모리 할당이 이루어집니다.
  • 자바의 경우, 객체는 힙 메모리(Heap)에 할당됩니다.
    • 객체를 생성할 때는 new 키워드를 사용하여 힙 메모리(Heap)에서 필요한 만큼의 메모리를 할당합니다.
MyClass obj = new MyClass();
  • 위 코드에서 new MyClass()는 힙 메모리(Heap)에 MyClass 타입의 객체를 생성하고, 생성된 객체의 매모리 주소obj 변수에 할당합니다.

📝 힙 메모리(Heap Memory)

힙 메모리(Heap Memory)는 프로그램 실행 중에 동적으로 메모리를 할당할 수 있는 영역으로, 필요한 만큼의 메모리를 런타임에 동적으로 할당하고 해제할 수 있습니다.
이는 전역 변수나 지역 변수처럼 컴파일 시점에 크가가 결정되지 않고, 프로그램 실행 중에 메모리 요구량이 달라질 때 유용하게 사용됩니다.

2️⃣ 생성자(Constructor) 호출.

  • 메모리가 할당되면, 생성자(Constructor)가 호출되어 객체의 초기화 작업이 이루어집니다.
    • 생성자(Constructor)는 객체의 초기 상태를 설정하고 필요한 리소스를 준비하는 역할을 합니다.
  • 개발자는 객체를 생성할 때 생성자를 통해 객체의 초기값을 설정할 수 있습니다.
public class MyClass {
    private int value;
    
    // 생성자
    public MyClass(int value) {
        this.value = value; // 초기화 작업
    }
}

MyClass obj = new MyClass(10); // 생성자를 통해 초기값 설정.

3️⃣ 객체의 초기화.

  • 생성자가 호출되면서 객체의 필드(멤버 변수)가 초기화됩니다.
    • 이 단계에서 객체의 상태가 설정되고, 필요한 리소스가 준비됩니다.
  • 자바는 기본 생성자(인자가 없는 생성자)를 제공하여, 개발자가 별도로 생성자를 정의하지 않아도 객체를 생성할 수 있습니다.

4️⃣ 메모리 주소 반환.

  • 객체가 생성된 후, 참조 변수는 생성된 객체의 메모리 주소를 가리키게 됩니다.
    • 이로 인해 생성된 객체를 프로그램 내에서 접근하고 사용할 수 있게 됩니다.

2️⃣ 객체의 소멸 과정.

  • 객체의 소멸은 더 이상 사용되지 않는 객체를 메모리에서 해제하는 과정입니다.
    • 객체의 소멸은 언어에 따라 다르게 처리됩니다.

1️⃣ 자바에서의 가비지 컬렉션(Garbage Collection)

  • 자바는 객체의 소멸을 개발자가 직접 제어하지 않고, 가비지 컬렉터(Garbege Collector)가 자동으로 처리합니다.
  • 가비지 컬렉터(Garbage Collector)는 더 이상 참조되지 않는 객체를 감지하고, 힙 메모리(Heap Memory)에서 해제하여 메모리 누수(Memory Leak)를 방지합니다.
  • 가비지 컬렉터(Garbage Collector)는 백그라운드에서 주기적으로 실행되며, 사용되지 않는 객체를 탐지하여 메모리에서 제거합니다.

📝 메모리 누수(Memory Leak)

프로그램이 더 이상 사용하지 않는 메모리를 해제하지 않고 계속해서 점유하고 있는 상태를 말합니다.
메모리 누수(Memory Leak)가 발생하면 사용하지 않는 메모리가 계속 쌓여서 시스템의 가용 메모리가 줄어들게 되고, 결국에는 프로그램이나 시스템 전체가 메모리 부족으로 인해 성능 저하를 일으키거나 비정상 종료될 수 있습니다.

MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();
obj1 = null; // obj1이 참조하던 객체는 더 이상 사용되지 않음
  • 위 코드에서 obj1이 가리키던 객체는 더 이상 참조되지 않으므로, 가비지 컬렉터(Garbage Collector)가 이 객체를 메모리에서 제거할 수 있습니다.

2️⃣ 객체의 소멸과 종료자(Finalizer)

  • 자바는 객체가 소멸되기 전에 호출되는 finalize() 메서드를 제공합니다.
    • 그러나 가비지 컬렉터(Garbage Collector)의 동작을 제어하거나 보장할 수 없기 때문에, finalize()는 권장되지 않습니다.
  • 가비지 컬렉션이 언제 일어날지 예측할 수 없으므로, 리소스를 명시적으로 해제할 필요가 있다면, try-with-resourcefinally 블록을 사용하는 것이 좋습니다.

3️⃣ 가비지 컬렉터가 객체를 소멸시키는 기준.

  • 객체가 더 이상 참조되지 않거나, 순환 참조가 발생해 사용되지 않는 경우 가비지 컬렉터(Garbage Collector)는 이 객체를 메모리에서 제거할 수 있습니다.

📝 순환 참조(Circular Reference)

두 개 이상의 객체나 리소스가 서로를 참조하면서 참조의 순환 고리가 형성되는 상황을 의미합니다.
이러한 상황이 발생하면, 객체나 리소스가 서로를 참조하고 있어 해제되지 않는 상태가 되며, 특히 메모리 누수를 유발할 수 있습니다.

순환 참조(Circular Reference)는 객체 지향 프로그래밍(Object-Oriented Programming, OOP)에서 객체 간의 관계가 복잡하게 얽힐 때 발생할 수 있으며, 주로 동적 메모리 할당과 수동 메모리 해제가 필요한 언어(C/C++)에서 문제가 됩니다.
Java, Python과 같은 가비지 컬렉션이 있는 언어에서도 문제가 될 수 있지만, 순환 참조(Circular Reference)를 처리할 수 있는 메커니즘(예: 약한 참조)이 존재합니다.

  • 가비지 컬렉터(Garbage Collector)는 메모리 압박이 심하거나 프로그램이 오랜 시간 동안 실행될 때 주기적으로 실행됩니다.

3️⃣ 다른 언어에서의 객체 소멸.

1️⃣ C++와 수동 메모리 관리.

  • C++에서는 자바와 달리 수동 메모리 관리가 필요합니다.
    • 개발자가 객체의 소멸 시점에 delete를 사용하여 직접 메모리를 해제해야 합니다.
  • C++에서는 소멸자(Destructor)가 있어 객체가 메모리에서 해제될 때 자동으로 호출되어, 메모리 해제나 리소스 반환 작업을 수행할 수 있습니다.
class MyClass {
public:
    ~MyClass() { // 소멸자
        // 메모리 해제 작업 수행
    }
};

MyClass* obj = new MyClass();
delete obj; // 직접 메모리 해제

2️⃣ 파이썬과 참조 카운팅

  • 파이썬은 참조 카운팅(Reference Counting)을 사용하여 객체의 소멸을 관리합니다.
    • 객체를 참조하는 변수가 없을 때, 해당 객체는 메모리에서 해제됩니다.
  • 그러나 순환 참조(Circular Reference) 문제가 발생할 수 있어, 파이썬은 추가로 가비지 컬렉션도 사용합니다.

4️⃣ 객체 생성과 소멸에서 주의할 점.

1️⃣ 메모리 누수(Memory Leak).

  • 객체를 더 이상 사용하지 않음에도 불구하고, 참조를 해제하지 않으면 메모리가 반환되지 않고 계속 사용된 상태로 남을 수 있습니다.
    • 이를 메모리 누수(Memory Leak)라고 하며, 프로그램 성능에 치명적인 영향을 미칠 수 있습니다.
  • 자바에서는 가비지 컬렉터가 자동으로 메모리를 해제하지만, C++와 같은 언어에서는 직접 메모리 관리를 잘해야 합니다.

2️⃣ 정확한 리소스 해제.

  • 데이터베이스 연결, 파일 입출력, 네트워크 소켓 등과 같은 외부 리소스는 명시적으로 해제해야 합니다.
    • 자바에서는 try-with-resources를 사용하여 이러한 리소스를 자동으로 해제할 수 있습니다.
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    // 파일을 읽는 작업 수행
} // try 블록이 끝나면 BufferedReader가 자동으로 닫힘

📝 네트워크 소켓(Network Socket)

네트워크를 통해 통신을 수행하기 위한 양 끝단의 연결 인터페이스로, 두 컴퓨터 간에 데이터 통신을 할 수 있게 해주는 소프트웨어 엔드포인트입니다.
소켓(Socket)은 네트워크 연결을 설정하고 데이터를 주고받기 위한 네트워크 프로그래밍의 기본 단위로 사용됩니다.

📝 소프트웨어 인터페이스(Software Interface)

소프트웨어 시스템이나 애플리케이션이 다른 소프트웨어, 하드웨어, 사용자 또는 시스템과 상호작용하는 방식을 정의하는 개념입니다.
인터페이스(Interface)는 소프트웨어 컴포넌트(Component) 간의 커뮤니케이션 방법을 표준화하여, 서로 다른 시스템이나 모듈이 효율적으로 데이터를 주고받고 기능을 호출할 수 있도록 해줍니다.

5️⃣ 요약.

  • 객체의 생성은 메모리 할당, 생성자 호출, 초기화 작업을 포함하며, 힙 메모리(Heap Memory)에서 이루어집니다.
  • 반대로 객체의 소멸은 더 이상 사용되지 않는 객체를 메모리에서 해제하는 과정으로, 자바에서는 가비지 컬렉터(Garbage Collector)가 이를 자동으로 처리합니다.
  • 객체의 생성과 소멸을 잘 이해하고 관리하면, 메모리 누수 없이 효율적인 프로그램을 작성할 수 있습니다.
  • 개발자는 객체의 생명 주기를 잘 파악하고, 적절한 시점에 리소스를 해제하여 프로그램의 성능을 최적화해야 합니다.