본문 바로가기

개발

메모리: 힙(Heap)과 스택(Stack)의 차이

반응형

컴퓨터 프로그래밍의 핵심 원리를 이해하려면 메모리 구조를 알아야 합니다. 프로그램이 실행될 때 운영체제는 메모리를 여러 영역으로 나누어 사용하는데, 그중 가장 중요하고 기본적인 두 영역이 바로 스택(Stack)힙(Heap)입니다. 이 두 메모리 영역은 데이터가 저장되는 방식, 할당되는 시점, 관리 주체에서 명확한 차이를 보이며, 프로그램의 성능, 안정성, 그리고 동작 방식에 직접적인 영향을 미칩니다.


1. 스택(Stack) 메모리: '쌓아 올리는' 질서 정연한 공간

스택은 '쌓아 올리다'라는 의미 그대로, 데이터가 차곡차곡 쌓이고 나중에 들어온 데이터가 먼저 나가는 '선입후출(LIFO: Last-In, First-Out)' 구조로 관리됩니다. 마치 식당에서 접시를 쌓아 올리는 것과 같습니다. 가장 마지막에 쌓은 접시를 가장 먼저 사용하게 되죠.

  • 할당 시점: 컴파일 타임(Compile Time) 또는 런타임 초반에 할당됩니다. 프로그램이 시작될 때 스택의 크기가 정적으로 결정되므로, 프로그램의 동작 도중에 크기를 변경할 수 없습니다.
  • 할당 주체: 운영체제(OS)와 컴파일러가 관리합니다. 개발자가 직접 메모리를 관리할 필요가 없습니다.
  • 저장 데이터: 함수 내의 지역 변수(Local Variables), 매개 변수(Parameters), 그리고 함수가 호출된 후 돌아갈 반환 주소 등이 저장됩니다. 함수가 호출되면 스택에 해당 데이터들이 쌓이고, 함수 실행이 끝나면 쌓였던 데이터들이 자동으로 해제(Pop)됩니다.
  • 특징:
    • 속도: 메모리 주소가 순차적으로 할당되므로, 데이터에 접근하는 속도가 매우 빠릅니다.
    • 크기: 크기가 정해져 있어 저장 공간이 제한적입니다. 너무 많은 지역 변수를 선언하거나, 재귀 함수가 무한히 호출되면 '스택 오버플로우(Stack Overflow)' 에러가 발생하여 프로그램이 비정상적으로 종료될 수 있습니다.
    • 할당/해제: 자동(Automatic)으로 이루어집니다. 개발자는 변수를 선언만 하면 메모리가 알아서 관리되므로 매우 편리합니다.

C++ 코드 예시:

void myFunction() {
    int local_variable = 10; // 스택에 할당
    // ...
}
// 함수가 끝나면 local_variable은 스택에서 자동으로 해제됨

 


2. 힙(Heap) 메모리: '자유로운' 유동적인 공간

힙은 '쌓다'가 아닌 '더미'라는 의미에 가깝게, 데이터가 무작위로 할당되고 해제되는 유동적인 공간입니다. 스택과 달리 정해진 규칙 없이 필요할 때마다 메모리를 할당받고 해제하는 방식입니다.

  • 할당 시점: 런타임(Run Time)에 프로그램이 실행되는 도중에 동적으로 할당됩니다. 따라서 프로그램의 필요에 따라 메모리 크기를 유연하게 조절할 수 있습니다.
  • 할당 주체: 개발자가 직접 관리해야 합니다. C언어에서는 malloc(), C++에서는 new 키워드를 사용해 메모리를 할당하고, free(), delete로 수동으로 해제해야 합니다. Java나 Python과 같은 언어는 '가비지 컬렉터(Garbage Collector)'가 더 이상 사용되지 않는 힙 메모리를 자동으로 해제해 줍니다.
  • 저장 데이터: 프로그램 실행 중 동적으로 크기가 변하거나, 여러 함수에서 공유해야 하는 객체(Object), 배열(Array), 긴 문자열 등 크기가 큰 데이터가 저장됩니다.
  • 특징:
    • 속도: 데이터가 무작위로 저장되므로, 스택에 비해 접근 속도가 느립니다.
    • 크기: 크기가 매우 크고 유동적이어서 원하는 만큼의 메모리를 할당할 수 있습니다.
    • 할당/해제: 수동(Manual)으로 관리해야 합니다. 할당한 메모리를 해제하지 않으면 '메모리 누수(Memory Leak)'가 발생하여 프로그램 성능 저하 및 메모리 부족 현상의 원인이 될 수 있습니다. 또한, 무작위 할당과 해제가 반복되면 메모리 조각화(Fragmentation)가 발생할 수 있습니다.

C++ 코드 예시:

int* heap_data = new int; // 힙에 정수형 변수 할당
*heap_data = 20;
// ...
delete heap_data; // 사용 후 반드시 수동으로 해제해야 함

3. 스택 vs. 힙 비교 요약 및 예시

구분 스택 (Stack) 힙 (Heap)
할당 방식 선입후출(LIFO), 순차적 동적 할당, 무작위
할당 시점 컴파일 타임 런타임
관리 주체 운영체제, 컴파일러 개발자 (수동), 가비지 컬렉터 (자동)
저장 데이터 지역 변수, 매개 변수, 반환 주소 객체, 배열, 동적 데이터
속도 빠름 느림
크기 제한적 (고정) 유동적 (매우 큼)
예외 스택 오버플로우(Stack Overflow) 메모리 누수(Memory Leak), 단편화

실제 작동 예시 Java에서 int num = 10;과 String str = new String("hello");를 선언하는 경우를 생각해 봅시다.

  • int num = 10;: 기본 자료형인 num 변수는 스택에 저장됩니다.
  • String str = new String("hello");: new 키워드를 통해 생성된 String 객체는 에 저장됩니다. 그리고 이 힙 메모리의 주소를 가리키는 str 변수만 스택에 저장됩니다.

이처럼 스택은 프로그램의 흐름을 제어하는 데 사용되는 빠르고 작은 메모리 공간이며, 힙은 프로그램의 데이터 자체를 보관하는 크고 유연한 메모리 공간입니다. 두 영역의 특성을 이해하고 적절히 활용하는 것은 효율적이고 안정적인 프로그램을 개발하는 데 매우 중요합니다.

반응형