2026년 02월 13일

🧠 메모리를 직접 다루면 왜 복잡해질까?

Java Spring Boot
Cover Image

🧠 메모리를 직접 다루면 왜 복잡해질까?

한 줄 결론 : 직접 주소를 다루면 안전성·동시성·보안 문제를 개발자가 전부 책임져야 하기 때문이다.


💡 Java는 왜 포인터가 없을까?

C 언어에서는 이런 코드가 가능하다.

int* p = (int*)0x1000;
*p = 10;  // 메모리 주소를 직접 조작

Java에서는 이런 코드를 아예 작성할 수 없다. 이유는 단순하다.
직접 주소를 다루면 4가지 치명적인 문제가 생기기 때문이다.


⚠️ 직접 메모리 접근의 4가지 문제

1. 메모리 충돌 (Memory Collision)

프로세스 A → 0x1000 사용
프로세스 B → 0x1000 사용  ← 데이터 덮어쓰기 발생!

서로 다른 프로그램이 같은 주소를 사용하면 데이터가 파괴된다.
OS가 가상 메모리(Virtual Memory) 를 도입한 이유가 바로 이것이다.


2. 메모리 누수 (Memory Leak)

int* p = malloc(100);
// free(p)를 호출하지 않으면?
// → RAM이 계속 점유됨 → 서버에서는 치명적

Spring Boot에서 GC(Garbage Collector) 가 존재하는 이유가 바로 여기에 있다.
개발자가 직접 해제하지 않아도 JVM이 사용하지 않는 객체를 자동으로 수거한다.


3. 잘못된 주소 접근 (Segmentation Fault)

int* p = NULL;
*p = 10;  // 프로그램 즉시 종료

Java에서 포인터 직접 접근을 금지하고 JVM이 메모리를 추상화하는 이유가 여기에 있다.
잘못된 주소에 접근하는 순간 프로그램 전체가 크래시된다.


4. 동시성 문제 (Data Race)

Thread A → 주소 0x2000 수정 중
Thread B → 같은 주소 동시에 수정  ← 값이 꼬임!

이 문제를 해결하기 위해 등장한 개념들이다.

해결책설명
synchronized블록 단위 상호 배제
volatile메모리 가시성 보장
CAS원자적 비교-교환 연산

🏗️ Java가 메모리를 다루는 방식

User user = new User();

개발자는 주소를 모른다. 하지만 내부에서는 이렇게 동작한다.

개발자  →  객체(변수명)로 접근
JVM    →  힙(Heap)에 할당 & GC로 관리
OS     →  가상 주소 관리
CPU    →  물리 주소 접근

이 계층 구조 덕분에 개발자는 비즈니스 로직에만 집중할 수 있다.


📌 핵심 요약

문제원인Java의 해결책
메모리 충돌여러 프로세스가 같은 주소 사용JVM + 가상 메모리
메모리 누수수동 해제 누락GC(Garbage Collector)
잘못된 접근NULL·임의 주소 접근포인터 직접 접근 금지
동시성 문제멀티스레드 데이터 레이스synchronized / volatile / CAS
← 목록으로 돌아가기