본문 바로가기

Develop Story

IntelliJ + Java 디버거 완전 정복: 원리부터 사용하는 법까지

728x90

IntelliJ + Java 디버거 기초 & 내부 원리

🔍 1. 왜 디버거인가 — 단순 println의 한계

우리는 흔히 System.out.println()을 써서 값이 어떻게 변하는지를 찍어서 디버깅하곤 합니다.
하지만 복잡한 흐름, 여러 메서드 호출, 조건 분기, 반복문, 예외 처리 등이 많아지면:

  • 어디서 잘못된 값이 들어갔는지 찾기 어렵고
  • 로그가 많아져서 가독성이 떨어지고
  • “이 값이 이 순간 정확히 어땠지?”를 재현하기 어렵습니다.

디버거는 이런 단점을 보완해줍니다. 디버거를 쓰면 원하는 줄에서 즉시 실행을 멈추고,
그 시점의 변수, 호출 스택, 흐름을 바로 들여다볼 수 있습니다.


🛠 2. Java 디버깅 내부 구조 — Java Platform Debugger Architecture (JPDA)

Java 생태계에서 디버깅은 단순히 IDE와 JVM 사이의 직접 통신이 아니라,
아래 세 계층으로 나뉜 표준화된 디버깅 아키텍처 위에서 돌아갑니다. (docs.oracle.com)

계층 역할 요약
Java Debug Interface (JDI) 디버거(front-end)가 사용하는 고수준 Java API. 브레이크포인트 설정, 스텝, 변수/스택 조회 등을 구현. (Baeldung on Kotlin)
Java Debug Wire Protocol (JDWP) 디버거 ↔ JVM 사이 통신을 담당하는 표준 프로토콜. 로컬, 원격(debuggee가 다른 머신) 모두 지원. (IBM)
Java Virtual Machine Tool Interface (JVM TI) JVM 내부에서 디버깅 기능(실행 제어, stack/heap 조회 등)을 제공하는 네이티브 인터페이스. JDWP의 “서버 측” 구현 역할. (위키백과)

이 구조 덕분에:

  • IDE는 단지 JDI만 이용해서 디버깅 요청을 만들고,
  • 내부적으로는 JDWP를 통해 JVM TI가 탑재된 JVM에 “브레이크포인트 설정”, “스택 조회” 등의 요청을 보냄 →
  • 원격 서버에 돌아가는 JVM이라도 똑같이 디버깅이 가능

즉, 디버거는 단지 “IDE 기능”이 아니라, 표준화된 디버깅 인프라 위에 올라간 “원격 제어 컨트롤러”입니다.


📦 3. 디버거가 실제로 어떻게 동작하는가

3-1. 브레이크포인트 설정 → 내부 동작 흐름

  1. 사용자가 IDE에서 “이 줄에 브레이크포인트”를 찍으면 → JDI 호출
  2. JDI는 JDWP 메시지로 변환 → JVM TI가 탑재된 JVM에 전달 (Stack Overflow)
  3. JVM 내부에서는 바이트코드 주소 수준에 감시점(watchpoint / breakpoint) 이 등록됨
  4. 프로그램이 실행되고, 해당 바이트코드 주소에 도달하면 → JVM이 해당 스레드를 suspend + 이벤트 발생
  5. JDWP를 통해 이벤트 정보가 디버거로 전송 → IDE가 변수 / 스택 / 현재 줄 위치를 화면에 표시

이 흐름 덕분에, “소스코드의 줄”과 “실행 중인 바이트코드 위치” 간 매핑이 가능해지고,
실행 중인 애플리케이션을 안전하게 멈춰 상태를 관찰할 수 있습니다.

3-2. Step Into / Over / Out — 호출 스택과 흐름 제어

  • 메서드를 호출하면 JVM은 호출 스택에 새 프레임(push)
  • Step Into → 호출된 메서드 첫 줄의 바이트코드에 도달 → 일시 정지
  • Step Over → 현재 줄 전체 + 메서드 호출 전부 실행 → 호출자 다음 줄에 일시 정지 (단, 그 메서드 안에 breakpoint가 있다면 멈춤) (JetBrains)
  • Step Out → 현재 메서드 끝까지 실행 → 호출자 프레임의 다음 줄에 정지

이렇게 호출 스택과 바이트코드 실행 위치(Program Counter)가 디버거에 의해 제어됩니다.


🖼 4. 그림 설계 및 삽입 위치

📌 그림 A — Java 디버깅 아키텍처 (IDE ↔ JDI/JDWP ↔ JVM)

📌 그림 B — Breakpoint 동작 흐름 & 바이트코드 매핑

💡 5. 실전에서 디버거를 똑똑하게 사용하기 위한 팁

  • 브레이크포인트 남발을 피할 것 (필요한 곳만)
  • 여러 스레드 / 비동기 코드에서는 breakpoint + 스택 + 변수 동시 확인
  • 원격 JVM 디버깅 (서버, 컨테이너 등)에서도 같은 원리로 디버깅 가능 — JVM 옵션 -agentlib:jdwp=... 사용 
  • 디버거가 “마법”이 아니라 “정밀한 원격 제어 + 상태 조회 + 이벤트”라는 점을 이해하면 문제 해결이 더 체계적으로 됨
반응형