[스프링 입문을 위한 자바] 2. 자바와 절차적/구조적 프로그래밍

@lim · March 08, 2025

이번 장에서는 자바에 관한 기본 개념을 소개하고 있다.

자바 기본 개념

JDK, JRE, JVM

  • JDK (Java Development Kit): 자바 개발 도구, 자바 소스 코드를 컴파일하는 javac.exe를 포함, JDK는 JRE를 포함
  • JRE (Java Runtime Environment): 자바 실행 환경, 자바 프로그램을 실행하는 java.exe를 포함, JRE는 JVM을 포함
  • JVM (Java Virtual Machine): 자바 가상 머신, 각 플랫폼에 맞게 자바 프로그램을 구동

Write Once, Run Anywhere (WORA)

  • 자바 특징 중 하나, 자바 프로그램은 한 번 작성하면 어떤 플랫폼에서도 실행할 수 있다.

## 자바 메모리 구조 1. 프로그램이 메모리를 사용하는 방식 : 코드 실행 영역/데이터 저장 영역 2. 객체 지향 프로그램에서는 데이터 저장 영역을 세 개의 영역으로 분할 : 스태틱(Static)/스택(Stack),힙(Heap) - 이러한 구조를 앞으로 책에서는 T 메모리 구조라 명명

T 메모리 구조

메모리 구조 42p
메모리 구조 42p

  • Static 영역(=Method, Class 영역)
    • 클래스, Static 변수 및 메서드, 상수(final), 생성자, 메서드 정보 등을 저장
    • 프로그램 시작 시 로딩, 종료될 때 까지 유지 (클래스 파일의 바이트 코드가 로드됨)
  • Stack 영역
    • 메서드 호출 시 생성되는 스택 프레임 저장
    • 지역 변수(Primitive 타입의 데이터)와 매개 변수들 관리
    • 메서드가 종료되면 해당 스택 프레임은 소멸
    • Stack은 후입선출(LIFO, Last-In-First-Out) 특성을 가지고 있고, 스코프(Scope) 범위를 벗어나면 스택 메모리에서 소멸됨
  • Heap 영역
    • 객체와 인스턴스 변수(Referency Type) 저장
    • GC(Garbage Collection)에 의해 메모리 관리가 이루어짐 (그 전까지는 호출이 끝나도 메모리에 남아 있음)
    • (이후 3장에서 자세히 다룬다)

T 메모리 실행 과정

  1. 프로그램 시작
    • JRE가 먼저 프로그램 안에 main() 메서드가 있는 지 확인 이후 JVM 기동
    • java.lang 패키지 및 import 된 클래스 static 영역에 로딩
  2. main() 메서드 실행
    • main() 메서드의 스택 프레임 생성
    • 지역 변수와 매개변수 공간 할당
  3. 메서드 호출
    • 메서드 호출 시 새로운 스택 프레임이 생성되며, 호출된 메서드의 지역 변수과 반환값 공간이 할당
    • 값 전달(Call by Value) 방식으로 매개변수를 복사하여 전달
    • 메서드가 종료되면 스택 프레임 소멸
  4. 객체 생성
    • Heap 영역에 객체 생성
    • 객체 참조 변수는 스택 영역에 저장
  5. 프로그램 종료
    • main 메서드가 종료되면 JVM도 종료
    • 모든 메모리 할당 해제

스택 프레임(Stack Frame)

  • 메서드가 호출될 때 생성되는 메모리 저장 공간 (Stack 영역에 위치)
  • 현재 실행중인 메서드 상태 정보를 저장 (지역변수, 매개변수, 리턴 주소 등...)
  • 메서드가 종료되면 해당 스택 프레임은 소멸

## 전역 변수와 멀티 스레드
  1. 전역 변수 사용의 문제점
    • 전역 변수는 어디에서나 접근이 가능하나, 값의 변경 추적이 어렵고 코드 유지보수를 어렵게 할 수 있다.
    • 멀티스레드 환경에서는 전역 변수 사용 시 데이터 충돌(동시성 문제)가 발생할 수 있다.+

멀티 프로세스와 멀티 스레드 69p
멀티 프로세스와 멀티 스레드 69p

  1. 멀티스레드와 멀티프로세스 (cf. 운영체제)
    • 멀티스레드 : 하나의 메모리를 공유하며 스택 영역만 분할하여 사용
    • 멀티프로세스 : 각 프로세스가 독립적인 메모리 공간을 가짐

Cf.

  • Virtual Thread (경량화된 스레드)
    • 최근 JDK 21부터 도입되어 기존 멀티스레드의 복잡성을 줄이고 성능을 향상시키고자 함
    • 전통적인 스레드보다 더 많은 수의 스레드를 효율적으로 관리할 수 있게 함

## 절차적/구조적 프로그래밍의 유산 1. **goto 문** (쓰지마라) - 자바에서는 `goto`문을 사용할 수 없도록 설계 - 프로그램의 흐름을 복잡하게 만들 수 있기 때문 (스파케티 코드로 인해 유지보수가 어려워짐) 2. **함수(Function)/메서드(Method)** - 함수를 사용하여 코드를 모듈화하고 중복을 줄임 - 둘은 같은 의미 (객체지향 진영에서 차별화를 위해 다르게 명명되었을 뿐) - 차이점이 있다면 객체지향에서는 클래스 내에서만 정의 가능 - 전역 변수보다는 지역 변수를 쓰자 3. **제어문 (if, for 등)**

Cf.

  • Kotlin에서는 main() 함수는 클래스 외부에서 정의가 가능하다.
  • Java도 JDK 21의 JEP 445라는 Preview 스펙으로 클래스 작성을 생략할 수 있다. (디컴파일 하게 되면 클래스명이 파일명으로 되어 있다.)

근본적으로는 클래스 내 정의되어 있지만 코드를 짤 때 생략하게 될 지도...?

IntelliJ에서 다음과 같이 오류가 나타다면 Alt + Enter로 옵션 적용

인텔리제이 Preview 에러
인텔리제이 Preview 에러

실행 결과
실행 결과

@lim
기억은 기록기록