이번 시간에는 우리가 작성한 코드가 실제로 살아 움직이는 공간, 바로
메모리(Memory)
에 대해 깊이 있게 탐구해 보겠습니다.
메모리가 어떻게 동작하는지 이해하는 것은, 단순히 CS 지식을 쌓는 것을 넘어 우리가 작성하는 프로그램의 성능과 안정성을 직접 제어할 수 있는 힘을 갖게 된다는 의미입니다.
오늘은 메모리를
컴퓨터의 작업대
에 비유하여, 이 작업대가 어떻게 두 개의 공간으로 나뉘어 사용되는지(스택과 힙), 누가 이 작업대를 청소하는지(가비지 컬렉션), 그리고 어떤 문제들이 발생하는지(메모리 누수 등) 그 모든 것을 낱낱이 파헤쳐 보겠습니다.
🚀
메모리: 두 개의 공간, 스택과 힙(Stack and Heap) 🔗
프로그램이 실행되면, 운영체제는 해당 프로그램을 위해 독립된 메모리 공간을 할당해 줍니다.
이 공간은 여러 영역으로 나뉘지만, 개발자에게 가장 중요한 두 공간은 바로
스택(Stack)
과
힙(Heap)
입니다.
✅
1. 스택 (Stack): 질서정연한 임시 작업 공간 🔗
스택은
함수의 호출과 관련된 지역 변수, 매개변수 등이 저장되는 공간
입니다.
이름처럼 데이터가 차곡차곡 쌓이는(Push) 구조이며, 가장 나중에 쌓인 데이터가 가장 먼저 빠져나가는(Pop)
LIFO(Last-In, First-Out)
방식으로 동작합니다.
- 컴파일 시점에 크기가 결정되어, 예측 가능하고 매우 빠릅니다.
- 함수 호출이 끝나면 해당 함수에 할당되었던 메모리(스택 프레임)가 자동으로 정리됩니다.
- 원시 타입(Primitive Type)의 값과, 힙에 생성된 객체를 가리키는 참조 변수가 저장됩니다.
✅
2. 힙 (Heap): 자유롭지만 관리가 필요한 창고 🔗
힙은
개발자가 코드를 통해 동적으로 생성하는 객체(인스턴스, 배열 등)가 저장되는 공간
입니다.
스택처럼 정해진 순서 없이, 필요할 때마다 동적으로 메모리 공간이 할당되고 해제됩니다.
- 런타임에 크기가 결정되며, 매우 큰 메모리 공간을 할당할 수 있습니다.
- 스택보다 상대적으로 느립니다.
- 개발자가 직접 관리하거나(C/C++), 가비지 컬렉터(GC)가 주기적으로 정리해 주어야 합니다.

Stack and Heap
🚀
가비지 컬렉션 (GC): 누가 힙을 청소하는가? 🔗
힙 영역은 개발자가 직접 관리하지 않으면, 더 이상 사용되지 않는 객체(쓰레기)들이 계속 쌓여 메모리 부족 문제를 일으킵니다.
자바, 자바스크립트, C# 등 대부분의 최신 언어는 이 문제를 해결하기 위해
가비지 컬렉터(Garbage Collector, GC)
라는 자동 메모리 관리 시스템을 제공합니다.
GC는 마치
창고를 주기적으로 순회하며 버려진 물건을 치워주는 자동 청소 로봇
과 같습니다.
힙 영역을 돌아다니며, 더 이상 어떤 변수도 참조하지 않는 객체를 찾아내어 메모리에서 해제해 줍니다.
단점 (Stop-the-World)
GC가 동작하는 동안에는, 애플리케이션의 모든 스레드가 일시적으로 멈추는 Stop-the-World
현상이 발생할 수 있습니다.
이 시간이 길어지면 사용자가 서비스의 일시적인 멈춤을 경험할 수 있으므로, GC 튜닝은 고성능 애플리케이션에서 매우 중요한 과제입니다.
메모리를 직접 다루다 보면 여러 가지 문제에 부딪히게 됩니다.
✅
문제 1: 스택 오버플로 (Stack Overflow) 🔗
스택 영역은 크기가 고정되어 있는데, 이 한정된 공간을 넘어서도록 데이터를 계속 쌓으려고 할 때 발생하는 에러입니다.
✅
문제 2: 메모리 누수 (Memory Leak) 🔗
힙 영역에서, 더 이상 필요하지 않은 객체가 가비지 컬렉터에 의해 회수되지 않고 계속해서 메모리 공간을 차지하는 현상입니다.
메모리 관리는 모든 개발의 기본이므로, 그 원리를 깊이 있게 묻는 질문이 반드시 나옵니다.
✅
1. 스택과 힙의 차이점을 설명해주세요. 🔗
두 메모리 영역의 핵심적인 특징을 비교하여 설명하는 것이 중요합니다.
스택과 힙은 용도와 관리 방식이 다른 메모리 공간입니다.
스택
은 함수의 호출과 함께 생성되는 지역 변수와 매개변수가 저장되는 공간으로, 정적인 크기를 가지며 컴파일 시점에 할당되고 LIFO 방식으로 자동 관리됩니다.
매우 빠르다는 특징이 있습니다.
반면
힙
은 개발자가 코드를 통해 동적으로 생성하는 객체들이 저장되는 공간으로, 런타임에 크기가 결정되며 동적으로 관리됩니다.
스택보다 상대적으로 느리지만, 크기가 훨씬 크고 유연합니다.
힙에 할당된 메모리는 가비지 컬렉터에 의해 관리됩니다.
✅
2. 가비지 컬렉션의 역할과 단점에 대해 설명해주세요. 🔗
GC의 필요성과 그 이면의 트레이드오프를 이해하고 있는지 묻는 질문입니다.
GC는 힙 영역에서 더 이상 사용되지 않는 객체, 즉 쓰레기(Garbage)를 찾아내어 자동으로 메모리를 해제해주는 역할을 합니다.
이를 통해 개발자가 직접 메모리를 관리하는 부담을 덜어주고, 메모리 누수와 같은 실수를 방지해 줍니다.
하지만 GC의 가장 큰 단점은, GC가 실행되는 동안 애플리케이션의 모든 스레드가 일시적으로 멈추는
Stop-the-World
현상이 발생할 수 있다는 점입니다.
이로 인해 서비스의 응답 시간이 길어지거나 일시적인 멈춤이 발생할 수 있습니다.
✅
3. 메모리 누수란 무엇이며, 어떻게 탐지할 수 있나요? 🔗
문제 해결 능력을 확인하는 실무적인 질문입니다.
메모리 누수는 힙 영역에 할당된 객체 중 더 이상 사용되지 않음에도 불구하고, 참조가 계속 남아있어 가비지 컬렉터가 회수하지 못하고 메모리를 계속 점유하는 현상입니다.
이러한 누수가 누적되면 결국 메모리 부족(Out of Memory) 에러로 이어질 수 있습니다.
메모리 누수를 탐지하기 위해서는, JDK의 VisualVM이나 MAT(Memory Analyzer Tool)와 같은
프로파일링 도구
를 사용하여 주기적으로 힙 메모리 사용량을 모니터링하고,
힙 덤프(Heap Dump)
를 분석하여 어떤 객체가 비정상적으로 많이 쌓여있는지 확인하는 방법을 사용할 수 있습니다.
오늘은 프로그램의 보이지 않는 작업 공간, 메모리에 대해 깊이 있게 알아보았습니다.
- 메모리는 크게
스택
과 힙
이라는 두 공간으로 나뉘어 각기 다른 역할을 수행합니다.
GC
는 힙을 자동으로 청소해 주지만, 때로는 서비스를 잠시 멈추게 하는 비용이 따릅니다.
- 개발자는
스택 오버플로
와 메모리 누수
와 같은 잠재적인 문제들을 항상 경계해야 합니다.