TIL: 인터페이스와 가비지 컬렉터 개념 정리

 

인터페이스란 무엇인가?

  • 인터페이스는 클래스가 반드시 구현해야 하는 메서드와 속성의 계약을 정의하는 기능임.
  • 이를 통해 코드의 구조를 명확하게 하고 일관성을 유지할 수 있음.
  • 인터페이스 자체는 구현을 가지지 않으며, 클래스가 이를 상속받아 실제 기능을 구현해야 함.

주요 특징:

  • 다중 상속이 가능함
  • 메서드의 시그니처(이름, 반환값, 파라미터)만 정의됨
  • 다른 클래스들이 동일한 인터페이스를 구현할 수 있어 유연한 설계 가능함

예시 코드:

public interface IAttackable
{
    void Attack();
}

public class Player : IAttackable
{
    public void Attack()
    {
        Console.WriteLine("Player is attacking!");
    }
}

코드 설명:

  • IAttackable은 Attack 메서드를 정의한 인터페이스임.
  • Player 클래스는 이 인터페이스를 구현하여 Attack 메서드를 실제로 정의함.

인터페이스와 추상 클래스의 차이

  • 인터페이스추상 클래스 모두 추상적인 개념을 정의하지만 차이점이 존재함.

구분 인터페이스 추상 클래스

구현 여부 메서드의 구현 없음 일부 메서드 구현 가능
다중 상속 다중 구현 가능 단일 상속만 가능
필드(변수) 포함 불가능 가능
접근 제어자 모든 메서드는 기본적으로 public 접근 제어자 지정 가능
목적 기능의 계약 공통 기능의 일부 구현 제공

간단한 예시:

// 인터페이스
public interface IRun
{
    void Run();
}

// 추상 클래스
public abstract class Animal
{
    public abstract void Eat();
    public void Sleep()
    {
        Console.WriteLine("Sleeping...");
    }
}

가비지 컬렉터란 무엇인가?

  • **가비지 컬렉터(Garbage Collector, GC)**는 프로그램이 더 이상 필요하지 않은 메모리 자원을 자동으로 해제하는 역할을 함.
  • 개발자가 수동으로 메모리를 관리할 필요 없이, 불필요한 객체를 찾아 제거함으로써 메모리 누수를 방지함.

작동 원리:

  1. 프로그램 실행 중 객체의 참조 여부를 검사함.
  2. 참조되지 않는 객체를 탐지하여 메모리에서 해제함.
  3. 가비지 컬렉터의 장점과 단점
  • 장점:
    • 메모리 관리의 자동화로 개발자의 부담 감소
    • 메모리 누수와 같은 오류 방지
    • 코드의 유지보수가 쉬워짐
  • 단점:
    • GC가 실행될 때 성능 저하가 발생할 수 있음
    • 메모리 해제 시점을 개발자가 제어할 수 없음
    • 큰 객체를 다룰 때 오버헤드가 발생할 수 있음

가비지 컬렉터의 세대 개념

  • 가비지 컬렉터는 객체를 세대(Generation)로 나누어 관리함.
  • 각 세대는 객체의 수명에 따라 구분되며, 불필요한 메모리 회수를 효율적으로 수행함.

세대 설명

0세대 새로 생성된 객체가 위치하는 영역
1세대 0세대에서 생존한 객체들이 위치하는 영역
2세대 장시간 동안 참조되는 객체가 위치하는 영역

세대 관리 원리:

  1. 객체는 처음에 0세대에 할당됨.
  2. 0세대 GC 실행 후 살아남은 객체는 1세대로 승격됨.
  3. 1세대에서도 살아남으면 2세대로 이동함.
  4. 2세대 GC는 가장 비용이 많이 들며, 상대적으로 덜 자주 실행됨.
  5. 박싱과 언박싱 사용 시 주의할 점
  • 박싱(Boxing): 값 형식을 참조 형식으로 변환하는 과정
  • 언박싱(Unboxing): 참조 형식을 값 형식으로 변환하는 과정

주의할 점:

  1. 성능 저하: 박싱과 언박싱은 메모리 할당 및 복사를 유발하므로 성능에 영향을 줄 수 있음.
  2. 타입 일치: 언박싱 시 원래 타입과 일치하지 않으면 오류가 발생함.
  3. 불필요한 박싱 방지: 컬렉션 사용 시 제네릭을 활용하면 불필요한 박싱을 줄일 수 있음.

예시 코드:

int value = 10;
object boxed = value; // 박싱
int unboxed = (int)boxed; // 언박싱
  1. 제네릭이란 무엇인가?
  • **제네릭(Generics)**은 데이터 타입을 일반화하여 코드의 재사용성을 높이는 기능임.
  • 컬렉션이나 메서드에서 다양한 타입을 다룰 때, 타입 안전성과 성능을 보장할 수 있음.

장점:

  1. 타입 안전성: 잘못된 타입의 데이터를 컴파일 단계에서 방지함.
  2. 성능 개선: 박싱/언박싱을 줄여 성능을 높임.
  3. 코드 재사용: 여러 타입에 대해 하나의 코드로 대응 가능함.

예시 코드:

public class GenericExample<T>
{
    private T data;

    public void SetData(T value)
    {
        data = value;
    }
    public T GetData()
    {
        return data;
    }
}

// 사용
GenericExample<int> intExample = new GenericExample<int>();
intExample.SetData(5);
Console.WriteLine(intExample.GetData());

설명:

  • T는 제네릭 타입 파라미터로, 실행 시점에 실제 타입으로 대체됨.
  • GenericExample 클래스는 어떤 데이터 타입이든 처리할 수 있음.

주의사항:

  • 제네릭은 값 형식과 참조 형식 모두 사용할 수 있음.
  • 제네릭 메서드를 구현할 때 타입 제약 조건을 사용할 수 있음.

요약

  • 인터페이스: 메서드 시그니처를 정의하는 계약으로 다중 상속 가능
  • 추상 클래스와 차이점: 구현 여부, 필드 포함, 단일 상속 여부 등
  • 가비지 컬렉터: 메모리 자동 관리 도구, 장점과 단점 존재
  • 세대 개념: 0세대, 1세대, 2세대로 객체를 나눠 GC 효율화
  • 박싱과 언박싱: 성능 저하 주의, 제네릭으로 방지 가능
  • 제네릭: 타입 안전성과 코드 재사용성을 높이는 기능