IMCAT.DEV
로그인 가입
Dart 고급 자료구조

Dart 가비지 컬렉션 이해

Dart 가비지 컬렉션 이해 — 고급

가비지 컬렉션 이해

1. 도입 (왜 배워야 하는가)

가비지 컬렉션(Garbage Collection, GC)은 프로그램에서 더 이상 사용되지 않는 메모리를 자동으로 회수하는 프로세스입니다. Dart와 같은 현대적인 언어에서는 메모리 관리가 자동으로 이루어지기 때문에 개발자는 메모리 할당과 해제에 대해 덜 걱정할 수 있습니다. 그러나 가비지 컬렉션이 어떻게 작동하는지 이해하지 못하면 다음과 같은 문제가 발생할 수 있습니다.

  • 메모리 누수: 개발자가 객체를 의도적으로 해제하지 않으면 메모리 사용량이 지속적으로 증가하여 애플리케이션이 느려지거나 중단될 수 있습니다.
  • 성능 저하: 가비지 컬렉션이 너무 자주 발생하면 애플리케이션의 성능에 부정적인 영향을 미칠 수 있습니다. 이를 이해하고 조절하지 않으면 사용자의 경험이 나빠질 수 있습니다.
  • 이해를 바탕으로 가비지 컬렉션을 잘 활용하면 안정적이고 효율적인 애플리케이션을 개발할 수 있습니다.

    2. 핵심 개념 설명

    가비지 컬렉션의 주요 개념은 다음과 같습니다.

    용어정의
    가비지더 이상 참조되지 않는 객체로, 메모리에서 해제될 수 있는 상태입니다.
    참조객체가 메모리에 할당되어 있는 경우, 이를 참조하는 변수나 다른 객체를 의미합니다.
    힙(Heap)동적으로 할당된 객체들이 저장되는 메모리 영역입니다.
    스택(Stack)지역 변수와 함수 호출 정보를 저장하는 메모리 영역입니다.

    비유

    가비지 컬렉션은 마치 청소부가 사무실에서 필요 없는 물건들을 정리하는 것과 같습니다. 사무실 내에서 더 이상 사용되지 않는 물건(가비지)을 정리하여 공간을 확보하는 것처럼, 프로그램에서 더 이상 사용되지 않는 메모리도 정리하여 새로운 객체를 위한 공간을 만듭니다.

    3. 기본 코드 예제

    가비지 컬렉션을 이해하기 위한 기본 코드 예제를 살펴보겠습니다.

    class Person {
      String name;
    
      Person(this.name);
    }
    
    void main() {
      Person john = Person('John');
    
      // john 객체는 이제 더 이상 사용되지 않음
      john = null; // 이 시점에서 'john' 객체는 가비지로 간주됨
    
      // 가비지 컬렉션이 호출될 수 있음
      print('가비지 컬렉션이 호출될 수 있습니다.');
    }

    실행 결과:

    가비지 컬렉션이 호출될 수 있습니다.

    코드 동작 설명

    1. Person 클래스를 정의하고, name 속성을 초기화하는 생성자를 만듭니다.
    2. main 함수에서 john이라는 Person 객체를 생성합니다.
    3. john 객체를 더 이상 사용하지 않기 위해 null로 설정합니다. 이 시점에서 john 객체는 더 이상 참조되지 않으므로 가비지로 간주됩니다.
    4. 마지막 줄에서 가비지 컬렉션이 호출될 수 있음을 알리는 메시지를 출력합니다.
    5. 4. 실전 활용 예제

      예제 1: 쇼핑몰에서 장바구니를 구현할 때

      장바구니에 상품을 추가하고, 사용자가 장바구니를 비우는 경우 해당 상품 객체는 더 이상 필요 없으므로 가비지로 처리될 수 있습니다.

      class Product {
        String name;
      
        Product(this.name);
      }
      
      class Cart {
        List<Product> items = [];
      
        void addItem(Product product) {
          items.add(product);
        }
      
        void clearCart() {
          items.clear(); // 장바구니를 비우면 Product 객체들은 가비지로 처리될 수 있음
        }
      }
      
      void main() {
        Cart cart = Cart();
        cart.addItem(Product('Apple'));
        cart.addItem(Product('Banana'));
        cart.clearCart(); // 장바구니를 비움
      }

      예제 2: 사용자가 로그아웃할 때

      사용자가 로그아웃하면 관련된 사용자 정보를 담고 있던 객체를 해제하여 메모리를 확보합니다.

      class User {
        String username;
      
        User(this.username);
      }
      
      void main() {
        User user = User('Alice');
        
        // 로그인 상태에서 사용자 정보를 사용
        print('Logged in as: ${user.username}');
        
        // 로그아웃 시
        user = null; // 더 이상 필요 없으므로 가비지로 처리됨
      }

      5. 흔한 실수와 주의사항

      실수 1: 객체를 해제하지 않고 계속 참조

      class User {
        String username;
        User(this.username);
      }
      
      void main() {
        User user = User('Alice');
        // 사용자 객체를 해제하지 않음
        // 메모리 누수 발생 가능
      }

      올바른 코드:

      user = null; // 더 이상 필요 없을 때 객체를 해제해야 함

      실수 2: 너무 자주 GC를 호출하기

      void main() {
        for (int i = 0; i < 100000; i++) {
          var temp = Person('Temporary $i');
          // GC를 명시적으로 호출할 수 없지만
          // 너무 많은 객체를 생성하면 성능 저하가 발생할 수 있음
        }
      }

      6. 정리

    6. 가비지 컬렉션은 메모리를 자동으로 관리하여 개발자의 부담을 줄여줍니다.
    7. 객체가 더 이상 참조되지 않을 때 가비지로 간주되어 메모리에서 해제됩니다.
    8. 메모리 누수를 방지할 수 있도록 객체를 명확히 해제하는 것이 중요합니다.
    9. 다음에 학습하면 좋은 주제는 메모리 최적화 기법과 Dart의 비동기 프로그래밍입니다.