안녕하세요! 이번 글에서는 자바의 프로그램 실행 구조에서 메모리는 어떻게 사용되는가, 그리고 그 기반이 되는 절차적/구조적 프로그래밍 유산에 대해 살펴보겠습니다.
특히 자바의 실행 환경(JVM)이 어떻게 메모리를 나누고 관리하는지 이해하는 것은,
이후 객체지향과 스프링의 구조를 파악하는 데도 큰 도움이 됩니다.
🧠 T메모리란?
T메모리는 JVM이 자바 프로그램을 실행할 때 사용하는 메모리 구조입니다.
이 구조는 크게 세 가지 영역으로 나뉘며, 스레드(Thread) 단위로 생성되기 때문에 T메모리(Thread Memory)라고 부릅니다.
| 메모리 영역 | 설명 |
|---|---|
| static 영역 | 클래스와 static 멤버들이 올라가는 공간 |
| stack 영역 | 메서드 호출 시 생성되는 지역 변수 공간 |
| heap 영역 | new로 생성한 객체들이 저장되는 공간 |
📦 static 영역 – 클래스의 놀이터
public class Counter {
static int count = 0;
}
- 클래스나 static 멤버는 처음 호출될 때 JVM의 static 영역에 로드됩니다.
- static 멤버는 프로그램 어디서든 접근 가능하여, 전역 변수처럼 사용됩니다.
- 단, 이로 인해 스레드 간 공유되어 동시성 문제 발생 가능성이 있습니다.
💡 static 변수는 되도록 사용을 최소화하고,
읽기 전용으로 사용할 경우
final static상수로 선언하는 것이 좋습니다.
🧱 stack 영역 – 메서드의 놀이터
public static void main(String[] args) {
int a = 10;
String name = "Java";
}
- 메서드가 호출되면 스택 프레임이 생성되어, 지역 변수들이 저장됩니다.
- 메서드가 종료되면 해당 스택 프레임은 자동으로 소멸합니다.
- 기본형 타입은 값 자체가 저장, 참조형은 주소값이 저장됩니다.
int x = 5; // 값 저장
String str = "Hi"; // 주소값 저장 → 실제 객체는 heap에 존재
💡 내부 블록(if, for 등)에서 선언된 변수는 해당 블록의 스택 프레임에만 존재합니다.
🧶 heap 영역 – 객체의 놀이터
User user = new User("Alice");
new키워드를 통해 생성된 객체 인스턴스가 저장됩니다.- 인스턴스 필드들은 모두 heap 영역에 존재하며, GC(Garbage Collector)가 관리합니다.
- 더 이상 참조되지 않는 객체는 자동으로 소멸합니다.
💡 상속 관계에 있는 객체는 상위 클래스의 인스턴스도 함께 생성되며,
Object클래스까지 포함됩니다.
🔄 절차적/구조적 프로그래밍, 그리고 Java
자바는 객체지향 언어이지만, 그 뿌리는 절차적/구조적 프로그래밍에서 출발했습니다.
이를 이해하면 객체지향 개념이 왜 필요한지 자연스럽게 와닿습니다.
🔁 절차적 프로그래밍
- 프로그램을 위에서 아래로 순서대로 실행하는 방식
goto사용은 복잡한 흐름을 만들기 때문에 Java에선 예약어지만 사용 불가
// 이런 식의 흐름이 복잡해지기 때문에 지양
goto line14;
🧩 구조적 프로그래밍 = 함수 중심
- 중복 코드 제거, 유지보수 용이
- 논리를 함수 단위로 모듈화
- Java에서는 이 개념이 메서드(method)로 이어짐
💡 함수는 클래스와 독립적이지만,
메서드는 클래스 내부에 반드시 존재해야 합니다.
⚙️ main() 실행부터 메모리까지
Hello, World!를 출력하는 간단한 코드도, 실제로는 복잡한 실행 구조를 가집니다.
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
실행 순서 요약
- JRE가 프로그램 실행 요청
- JVM 부팅 및 static 영역 준비
java.lang등 필수 패키지 static에 적재- 클래스 로딩 → static 영역에 등록
main()메서드 호출 → stack 프레임 생성- 지역 변수 확보 → 코드 실행
main()종료 → 스택 프레임 소멸- JVM 종료 → static, heap 메모리 해제
🖼️ [여기에 JVM 실행 다이어그램 삽입]
📌 변수는 어디에 저장될까?
| 변수 종류 | 저장 위치 | 소멸 시점 |
|---|---|---|
| 전역 변수 | static 영역 | JVM 종료 시 |
| 지역 변수 | stack 영역 | 메서드/블록 종료 시 |
| 객체 필드 | heap 영역 | 참조 해제 시 (GC) |
🔄 스레드와 메모리 구조
| 구분 | 멀티 스레드 | 멀티 프로세스 |
|---|---|---|
| 스택 영역 | 스레드마다 별도 | 프로세스마다 별도 |
| static / heap 영역 | 공유 | 공유하지 않음 |
| 메모리 효율 | 높음 | 낮음 |
| 안전성 | 동시성 이슈 가능 | 상대적으로 안전 |
💡 서블릿(Servlet)은 요청마다 스레드를 생성 → 멀티 프로세스보다 메모리 효율성 높음
🚨 전역 변수보다 전역 상수!
public class Shared {
static int value = 55;
}
- 전역 변수는 여러 스레드에서 동시에 수정 가능
- → 데이터 무결성 문제 발생
✅ 올바른 예시
public class Constants {
public static final int MAX_COUNT = 100;
}
- 읽기 전용 상수로 사용 → 안전 + 공유 가능
📝 해당 단원을 읽고 배운 점 (TIL)
- JVM이 프로그램 실행을 위해 메모리를 static, stack, heap으로 나누어 관리한다는 점을 알게 되었다.
- 메서드 호출과 블록 스코프의 변수 소멸 타이밍을 이해하면, 예상치 못한 변수 접근 에러를 방지할 수 있다.
- 멀티 스레드 환경에서는 static 영역과 heap을 공유한다는 점에서 전역 변수 사용 시 동기화 이슈에 주의가 필요하다.
- 전역 변수는 피하되, 전역 상수는 적극 활용하자!
다음 장에서는 본격적으로 객체지향 개념이 어떻게 자바에 녹아있는지를 살펴보겠습니다.
클래스, 인스턴스, 메서드, 필드 등 객체지향의 핵심 요소들을 차근히 정리해볼게요. 😊
참고 자료: 스프링 입문을 위한 자바 객체 지향의 원리와 이해 (김종민 저)
'CS > Java' 카테고리의 다른 글
| [Java] String은 참조형인데 왜 값이 안 바뀔까? – Pass by Value 와 Immutable (1) | 2026.01.08 |
|---|---|
| [Java] 스프링 입문을 위한 자바 객체 지향의 원리와 이해 1장 - 사람을 사랑한 기술 - Java 역사 이야기 (0) | 2025.06.18 |