Daily Dev Q&A: 자바의 메모리 구조

2025. 11. 26. 17:05·Archive/Daily Dev Q&A

Topic (오늘의 주제)

Java Memory Structure (Runtime Data Area)


Why (왜 사용하는가? 왜 중요한가?)

  • 실무: 멀티 스레드 환경에서 **"어떤 변수가 공유되고, 어떤 변수가 공유되지 않는지"**를 알아야 **동시성 이슈(Thread-Safety)**를 막을 수 있습니다.
  • 구조적 의미: 프로그램 실행에 필요한 데이터를 성격(정적, 동적, 실행 흐름)에 따라 분류하여 효율적으로 관리하고 접근 속도를 최적화합니다.
  • 면접 의도: static 키워드의 의미, 스택 오버플로우 발생 원인, 그리고 멀티 스레드 환경에서의 데이터 공유 문제를 이해하고 있는지 묻기 위함입니다.

Core Concept (핵심 개념 정리)

JVM의 메모리는 크게 스레드마다 하나씩 생성되는 영역과 모든 스레드가 공유하는 영역으로 나뉩니다.

영역 (Area) 스레드 공유 여부 설명
Method Area 공유 (Shared) 클래스 정보(메타데이터), static 변수, 상수(Constant Pool)가 저장되는 곳. 프로그램 시작 시 로드되고 종료 시 해제됨.
Heap Area 공유 (Shared) new 키워드로 생성된 객체와 배열이 저장되는 곳. GC(Garbage Collector)의 주요 대상.
Stack Area 개별 (Private) 메서드 호출 시마다 생성되는 지역 변수, 매개변수, 리턴 값이 저장됨. 메서드가 끝나면 즉시 사라짐 (LIFO).
PC Register 개별 (Private) 현재 실행 중인 JVM 명령의 주소 값을 저장. (스레드가 어디를 실행 중인지 기록)
Native Stack 개별 (Private) 자바 외의 언어(C/C++)로 작성된 네이티브 코드를 실행하기 위한 스택.

💡 핵심 비교: Stack vs Heap

  • Stack: 좁고 빠름. 메서드 실행을 위한 임시 공간. 끝나면 자동 삭제. (예: int a = 10;)
  • Heap: 넓고 복잡함. 데이터를 오래 보관하는 창고. GC가 청소해줘야 함. (예: User user = new User();)

Interview Answer Version (면접 답변식 요약)

"자바의 메모리 구조는 크게 스레드가 공유하는 영역과 공유하지 않는 영역으로 나뉩니다.

Method 영역에는 정적 변수와 클래스 정보가, Heap 영역에는 new로 생성된 객체들이 저장되며 이 두 영역은 모든 스레드가 공유합니다.

반면, 각 스레드마다 독립적으로 Stack 영역이 존재하여 지역 변수나 메서드 호출 정보를 관리합니다. 이 덕분에 지역 변수는 동시성 문제에서 안전합니다.

특히 Heap 영역은 GC가 메모리를 관리하는 핵심 영역이라는 점이 특징입니다."


Practical Tip (사용시 주의할 점 or 활용 예)

1. 스레드 안전성 (Thread Safety) 판단 기준

  • 지역 변수(Stack): 스레드마다 별도로 생성되므로 안전합니다.
  • 인스턴스 변수/정적 변수(Heap/Method): 여러 스레드가 동시에 접근할 수 있으므로, 값을 변경할 때 동기화(Synchronization) 문제가 발생할 수 있습니다.
    • Tip: 그래서 Spring의 Bean(기본적으로 싱글톤)에 상태 값을 저장하는 필드(인스턴스 변수)를 함부로 두면 안 됩니다.

2. 에러의 종류로 문제 파악하기

  • StackOverflowError: 주로 재귀 함수를 잘못 짰을 때 Stack 영역이 꽉 차서 발생합니다. (무한 루프 등)
  • OutOfMemoryError (Heap Space): 생성된 객체가 너무 많거나, 메모리 누수로 인해 Heap 영역이 꽉 차서 발생합니다.

3. Java 8 이후의 변화 (Metaspace)

  • 과거(Java 7 이하)에는 Method Area를 'PermGen'이라고 불렀고 크기 제한이 있어 에러가 잦았습니다.
  • Java 8부터는 이를 Metaspace로 변경하고 Native Memory(OS 메모리)를 사용하여, OS가 허용하는 한 유연하게 크기가 늘어나도록 개선되었습니다.

예상 꼬리 질문 정리

  1. 지역 변수(Local Variable)와 인스턴스 변수(Instance Variable)는 메모리의 어디에 저장되나요?
    • 답변 포인트: 지역 변수는 Stack, 인스턴스 변수는 객체 내부에 존재하므로 Heap에 저장됨을 구분.
  2. 멀티 스레드 환경에서 static 변수를 사용할 때 주의할 점은?
    • 답변 포인트: 모든 스레드가 값을 공유하므로 Race Condition 발생 가능성 언급 (synchronized 필요성 등).
  3. String은 메모리의 어디에 저장되나요? (String Constant Pool)
    • 답변 포인트: 리터럴("")로 생성하면 Heap 내의 String Constant Pool에 저장되어 재사용되고, new로 생성하면 일반 Heap 객체로 생성됨을 비교.

공부하며 몰랐던 개념 (Deep Dive)

단순히 메모리 구조만 외우는 것이 아니라, **"그래서 스프링 개발할 때 이게 왜 위험한데?"**를 이해하는 것이 핵심이었다. 이번 학습을 통해 정리된 내용을 기록한다.

① 스레드와 스프링 빈의 관계 (싱글톤의 함정)

  • 스레드(Thread): 사용자 요청을 처리하는 일꾼이다. 웹 서버는 수많은 일꾼이 동시에 일하는 멀티 스레드 환경이다.
  • 스프링 빈(Bean): 스프링은 효율성을 위해 Controller나 Service 객체를 **싱글톤(딱 1개만 생성)**으로 관리한다.
  • 문제 상황: 객체는 1개뿐인데 수많은 스레드가 동시에 이 객체를 사용한다. 이때 객체 안에 **상태를 저장하는 변수(인스턴스 변수)**가 있다면? 마치 공용 화이트보드처럼 데이터가 뒤섞이게 된다.

② 위험한 변수 vs 안전한 변수

메모리 위치를 알면 안전한지 아닌지 바로 알 수 있다.

  • 인스턴스 변수 (Heap 영역) 👉 위험!
    • 객체 내부에 저장되므로, 싱글톤 객체에서는 모든 스레드가 공유한다.
    • 예: "철수"가 로그인했는데, 잠깐 사이에 "영희"가 들어와서 변수 값을 바꿔버리면, 철수 화면에 영희 정보가 뜨는 대참사가 발생한다.
  • 매개변수 & 지역 변수 (Stack 영역) 👉 안전!
    • 메서드가 실행될 때마다 스레드별로 할당된 Stack 영역에 따로 저장된다.
    • Stack은 다른 스레드가 절대 침범할 수 없는 Private 공간이다. (마치 직원 개인 주머니와 같다.)

③ 실무 적용: 무상태(Stateless) 설계

스프링 빈을 만들 때는 **"변수를 없앤다"**고 생각해야 한다.

[❌ 잘못된 코드: 인스턴스 변수 사용]

Java
 
@Service
public class JoinService {
    private String memberName; // 위험! 모든 스레드가 공유함

    public void join(String name) {
        this.memberName = name; 
        saveToDB(this.memberName); // 다른 사람이 덮어쓸 수 있음
    }
}

[✅ 올바른 코드: 파라미터와 지역 변수 활용]

Java
 
@Service
public class JoinService {
    // 인스턴스 변수 없음 (깨끗함)

    public void join(String name) {
        // 매개변수(name)는 스레드별 Stack에 저장되므로 안전함
        String tempName = name; 
        saveToDB(tempName); 
    }
}

결론: 멀티 스레드 환경에서는 데이터를 필드(멤버 변수)에 저장하지 말고, 메서드 파라미터로 넘기거나 지역 변수 안에서만 처리해야 한다. 이것이 JVM 메모리 구조를 실무적으로 이해해야 하는 진짜 이유다.


학습 후기 및 발표 피드백(2025.12.01)

이번 학습을 통해 단순히 "암기"하는 공부에서 벗어나 "왜?"를 탐구하는 즐거움을 느꼈습니다.

👨‍🏫 강사님 피드백

"잘했어요. 내용 구성과 방향이 아주 좋습니다. 이제는 내용을 말로 전달하는 연습이 필요해요. 녹음해서 본인의 톤을 들어보고 정리해서 말하는 연습을 하면 훨씬 좋아질 겁니다."

📝 나의 생각 개념을 안다고 생각했지만, 막상 발표하려니 말이 꼬이고 힘들었다. 다음 발표 때는 ① 다시 한번 정리하고, ② 말해보고 녹음해서 들어보고, ③ 관련 영상을 참고하여 더 매끄럽게 전달할 수 있도록 준비해야겠다.

'Archive > Daily Dev Q&A' 카테고리의 다른 글

Daily Dev Q&A: 객체지향언어란? & 왜 JAVA가 객체지향언어인가?  (0) 2025.12.01
Daily Dev Q&A: 자바의 예외 처리(Exception) 구조  (0) 2025.11.28
Daily Dev Q&A: 자바는 컴파일 언어? 인터프린터 언어?  (0) 2025.11.28
Daily Dev Q&A: 자바의 Garbage Collection  (0) 2025.11.25
Daily Dev Q&A: JVM  (0) 2025.11.24
'Archive/Daily Dev Q&A' 카테고리의 다른 글
  • Daily Dev Q&A: 자바의 예외 처리(Exception) 구조
  • Daily Dev Q&A: 자바는 컴파일 언어? 인터프린터 언어?
  • Daily Dev Q&A: 자바의 Garbage Collection
  • Daily Dev Q&A: JVM
tlsgkstj
tlsgkstj
짱구의 성장 일기
  • tlsgkstj
    코딩하는 짱구
    tlsgkstj
  • 전체
    오늘
    어제
    • 분류 전체보기 (159)
      • About (1)
      • Projects (35)
        • Personal Projects (21)
        • Team Projects (14)
      • Engineering (20)
        • CS & Tools (0)
        • Backend Core (15)
        • Frontend (1)
        • Infra & Cloud (2)
        • AI & Tools (1)
      • Trouble Shooting & Issues (0)
      • Growth & Career (38)
        • Interview Prep (0)
        • Retrospectives (38)
      • Archive (65)
        • TIL (8)
        • Daily Dev Q&A (56)
  • 블로그 메뉴

    • 홈
    • About
    • Projects
    • Tech Stack
    • Dev Log
    • GitHub
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    DevFestIncheon2025
    backend
    경기기후바이브코딩
    devlog
    spring
    til
    Project_Review
    데브페스트
    REACT
    SpringBoot
    커리어리셋
    Spring비교
    OrphanRemova
    프로덕트개발자
    network
    클로드코드
    jpa
    프로젝트회고
    java
    aws_s3
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
tlsgkstj
Daily Dev Q&A: 자바의 메모리 구조
상단으로

티스토리툴바