Java

Heap과 Stack 메모리 관리

검은고양이개발자 2025. 1. 24. 09:02
반응형

 

1. 메모리의 두 가지 주요 영역

C#과 같은 언어에서 메모리는 크게 두 가지 영역으로 나뉩니다:

  1. 스택(Stack): 메서드 호출과 로컬 변수, 값 타입의 데이터를 저장하는 공간.
  2. 힙(Heap): 동적으로 할당된 객체와 참조 타입의 데이터를 저장하는 공간.

 

2. 스택(Stack)

 

특징

  • 값 타입 데이터를 저장합니다. (예: int, float, struct 등)
  • 메서드 호출 시, 메서드 내에서 선언된 로컬 변수들이 저장됩니다.
  • LIFO (Last In, First Out) 구조로 동작합니다.
  • 메모리 할당 및 해제가 빠릅니다.
  • 스택 메모리는 메서드가 종료되면 자동으로 정리됩니다.

 

저장되는 데이터

  • 값 타입의 데이터 (int, float, bool, etc.)
  • 참조 타입의 참조(주소) (객체의 실제 데이터는 힙에 저장).

 

예시

 
void MyMethod(){ 

int number = 10; // 값 타입, 스택에 저장 
float price = 20.5f; // 값 타입, 스택에 저장

}

 

스택 동작

  1. 메서드가 호출되면, 스택에 **새로운 프레임(frame)**이 생성됩니다.
  2. 프레임 안에는 메서드의 변수와 데이터가 저장됩니다.
  3. 메서드가 종료되면, 해당 프레임은 스택에서 제거됩니다.

 

3. 힙(Heap)

 

특징

  • 참조 타입 데이터를 저장합니다. (예: class, object, string, 배열 등)
  • 메모리 할당이 동적으로 이루어집니다.
  • 힙의 메모리는 **가비지 컬렉터(Garbage Collector, GC)**가 관리합니다.
  • 메모리 할당 및 해제가 스택보다 느립니다.

 

저장되는 데이터

  • 참조 타입의 실제 데이터.
  • 참조 타입의 필드 (내부 값 타입 데이터도 힙에 포함됩니다).

 

예시

void MyMethod() 
{ 
var obj = new MyClass(); // 객체가 힙에 저장됨 
obj.Name = "John"; // 필드 데이터도 힙에 저장됨 
}
 

힙 동작

  1. new 키워드를 통해 객체가 생성되면, 힙에 메모리 공간이 할당됩니다.
  2. 객체를 참조하는 변수는 스택에 저장되고, 힙에 있는 데이터의 주소를 참조합니다.
  3. 참조가 끊어진 객체는 GC가 자동으로 정리합니다.

 

4. Stack과 Heap의 차이

특성 StackHeap

저장 데이터 값 타입 데이터, 참조 타입의 주소 참조 타입의 실제 데이터
메모리 크기 상대적으로 작음 상대적으로 큼
속도 빠름 (LIFO 구조) 느림 (동적 할당)
메모리 해제 자동 (메서드 종료 시 제거) GC가 자동으로 해제
관리 방식 정적 (고정 크기, 스코프 기반) 동적 (필요 시 메모리 확장 가능)

 

5. 스택과 힙의 상호작용

참조 타입의 저장 방식

 
class MyClass 
{ 
	public int Value; 
} 

void MyMethod() 
{ 
	var obj = new MyClass(); // 힙에 객체 생성 
    obj.Value = 42; // 힙의 객체 데이터 수정 
}
  1. 스택: obj 변수에는 힙에 생성된 객체의 주소가 저장됩니다.
  2. 힙: MyClass 객체와 그 필드(Value)가 저장됩니다.

 

참조 변경

var reader = new MyClass() { Value = 10 }; 
var inReader = new MyClass() { Value = 20 }; 

reader = inReader; // reader는 이제 inReader의 주소를 참조
 
  • 기존 reader가 참조하던 객체는 아무도 참조하지 않으므로, GC가 처리 대상이 됩니다.
  • 이후 reader와 inReader는 동일한 객체를 참조합니다.

 

6. 가비지 컬렉션(GC)

역할

  • 힙에서 더 이상 사용되지 않는 객체를 탐지하고 메모리를 해제합니다.
  • 프로그래머가 직접 메모리 관리를 하지 않아도 되도록 자동으로 동작합니다.

작동 원리

  • GC는 Mark-and-Sweep 알고리즘을 사용합니다:
    1. Mark: 더 이상 참조되지 않는 객체를 탐지.
    2. Sweep: 탐지된 객체를 메모리에서 제거.
  • GC는 앱 실행 중 메모리가 부족하거나 시스템이 필요하다고 판단할 때 실행됩니다.

 

7. 메모리 관리에서 주의할 점

  1. 참조를 명확히 관리:
    • 참조를 끊지 않으면 객체가 메모리를 계속 차지하여 메모리 누수가 발생할 수 있습니다.
  2. Dispose 패턴 사용:
    • 파일, 네트워크 연결 등 힙 메모리 외의 리소스를 사용하는 객체는 IDisposable 인터페이스를 구현하여 명시적으로 해제해야 합니다.
  3. 큰 객체 관리:
    • 큰 객체는 **Large Object Heap (LOH)**에 저장되며, GC에서 다르게 처리됩니다. 큰 객체의 사용을 최소화하거나, 분리된 메모리 관리 전략을 고려하세요.

8. 결론

  • 스택: 빠르고 자동으로 관리되는 값 타입 데이터 저장 공간.
  • 힙: 동적으로 할당되며, GC에 의해 관리되는 참조 타입 데이터 저장 공간.
  • 올바른 메모리 관리는 성능 최적화와 안정적인 애플리케이션 개발의 핵심입니다.
반응형