Java를 처음 시작하면 코드보다 먼저 JDK, JVM, javac, .class 같은 용어를 만나게 된다. 처음에는 전부 외워야 할 것처럼 보이지만, 실제로는 Java 코드가 어떤 과정을 거쳐 실행되는지 한 번 이해하면 대부분 자연스럽게 연결된다.
이 글에서는 개발 환경을 준비하는 흐름부터 Java 프로그램이 실행되는 과정까지 한 번에 정리한다.
Java 개발의 핵심은 JDK(Java Development Kit) 다.
JDK에는 Java 코드를 작성하고 실행하는 데 필요한 도구가 들어 있다.
대표적으로 다음 두 명령이 중요하다.
javac: .java 소스 파일을 .class 바이트코드로 컴파일한다.java: 컴파일된 바이트코드를 JVM에서 실행한다.IDE를 사용하면 이 과정이 대부분 자동화된다. IntelliJ IDEA 같은 IDE에서 실행 버튼을 누르면 내부적으로 컴파일과 실행이 이어서 수행된다.
2026년 기준으로 새 학습 환경을 만든다면 안정적인 장기 지원 버전인 JDK 25 LTS를 선택하는 것이 무난하다. 기존 프로젝트가 JDK 17이나 21을 사용한다면 프로젝트 버전에 맞추는 것이 우선이다.
예를 들어 다음 파일이 있다고 해보자.
public class Application {
public static void main(String[] args) {
System.out.println("Service started");
}
}
파일 이름은 Application.java라고 하자.
실행 과정은 다음과 같다.
Application.java
↓ javac
Application.class
↓ JVM
프로그램 실행
개발자는 사람이 읽을 수 있는 Java 문법으로 .java 파일을 작성한다.
javac Application.java
컴파일이 성공하면 Application.class 파일이 만들어진다.
이 파일에는 CPU가 바로 실행하는 기계어가 아니라 Java 바이트코드가 들어 있다.
java Application
JVM(Java Virtual Machine)이 .class 파일을 읽어 현재 운영체제와 하드웨어 환경에서 실행한다.
이 구조 덕분에 Java는 흔히 다음 문장으로 설명된다.
Write Once, Run Anywhere
같은 바이트코드를 Windows, macOS, Linux의 JVM에서 실행할 수 있다는 의미다. 단, 네이티브 라이브러리나 OS 전용 기능을 사용한다면 완전히 동일하게 동작한다고 단정할 수는 없다.
main()은 왜 필요할까?일반적인 Java 애플리케이션은 다음 메서드에서 시작한다.
public static void main(String[] args) {
// 실행 코드
}
처음부터 public, static, String[] args의 모든 의미를 외울 필요는 없다. 입문 단계에서는 프로그램의 시작점이라고 이해하면 충분하다.
코드는 기본적으로 위에서 아래로 실행된다.
public class OrderApplication {
public static void main(String[] args) {
System.out.println("주문 조회");
System.out.println("결제 확인");
System.out.println("배송 요청");
}
}
출력 결과는 다음과 같다.
주문 조회
결제 확인
배송 요청
System.out.println()으로 출력하기콘솔에 데이터를 출력할 때 가장 먼저 사용하는 코드가 System.out.println()이다.
System.out.println("Hello Java");
System.out.println(2026);
println은 출력 후 줄을 바꾼다.
반면 print는 줄을 바꾸지 않는다.
System.out.print("API ");
System.out.print("Server");
API Server
다음처럼 public class를 선언했다면 일반적으로 파일 이름과 클래스 이름을 동일하게 맞춘다.
public class UserService {
}
파일명:
UserService.java
Java는 대소문자를 구분하므로 userservice, UserService, USERSERVICE는 서로 다른 이름이다.
Java에서는 { }가 코드의 범위를 나타낸다.
public class Main {
public static void main(String[] args) {
System.out.println("Hello");
}
}
그리고 대부분의 실행 문장은 세미콜론 ;으로 끝난다.
int userCount = 10;
System.out.println(userCount);
Java 컴파일러는 일반적으로 들여쓰기를 문법으로 강제하지 않는다. 하지만 사람은 코드 구조를 들여쓰기로 파악한다.
if (isLoggedIn) {
System.out.println("마이페이지 표시");
}
블록이 중첩될수록 일정한 들여쓰기가 중요해진다. 팀 프로젝트에서는 IDE 포매터나 코드 스타일 규칙을 사용해 일관성을 유지하는 것이 좋다.
// 사용자 수를 조회한다.
int userCount = 100;
/*
API 호출 테스트를 위한 임시 코드
배포 전 제거 예정
*/
주석은 컴파일 과정에서 실행 코드로 취급되지 않는다.
다만 주석으로 코드의 모든 동작을 설명하기보다는 이름과 구조만으로 이해되는 코드를 먼저 만들고, 이유나 주의사항처럼 코드만으로 표현하기 어려운 내용을 주석에 남기는 편이 좋다.
IntelliJ IDEA 같은 IDE는 다음 작업을 편하게 만들어준다.
IDE가 모든 과정을 대신해주더라도 내부에서 소스 코드 → 컴파일 → 바이트코드 → JVM 실행이 일어난다는 구조는 알고 있어야 한다. 그래야 빌드 오류나 실행 환경 문제를 만났을 때 원인을 찾기 쉬워진다.
아니다.
JDK 안에는 개발과 실행에 필요한 구성요소가 함께 포함된다.
.class 파일은 소스 코드일까?아니다. .java는 개발자가 작성한 소스 코드이고, .class는 컴파일된 바이트코드다.
아니다. JDK만 설치되어 있다면 터미널에서 직접 javac, java 명령으로 컴파일하고 실행할 수 있다.
Java는 6개월 주기로 새 버전이 나오기 때문에 입문할 때는 최신 버전과 LTS(Long-Term Support) 를 구분해 보는 것이 좋다.
2026년 10월 기준 최신 Java는 Java 27이고, 장기 지원 버전은 Java 25 LTS, Java 21 LTS 등이 있다. 처음 실습 환경을 만든다면 특별한 이유가 없는 한 최신 LTS인 Java 25를 선택하면 버전 변화에 덜 흔들리면서 학습하기 좋다.
다만 이 글의 대부분의 기본 문법은 Java 21, 25, 27에서 동일하게 동작한다.
Java 25에서는 Compact Source Files와 Instance main Methods가 정식 기능이 되었다. 그래서 아주 작은 프로그램은 다음처럼 더 짧게 작성할 수도 있다.
void main() {
IO.println("Hello Java");
}
IO는 Java 25부터 java.lang에 포함된 기본 콘솔 입출력 클래스다.
하지만 기존 형태도 그대로 사용할 수 있다.
public class HelloJava {
public static void main(String[] args) {
System.out.println("Hello Java");
}
}
초보 단계에서는 두 형태가 모두 존재한다는 사실만 알아두고, 클래스·메서드·static 개념까지 함께 익히려면 전통적인 public static void main(String[] args) 형태로 연습해도 좋다.
Java는 언어와 플랫폼의 표준 규격이 있고, 여러 벤더가 그 규격에 맞는 JDK를 배포한다.
대표적으로 다음과 같은 배포판이 있다.
입문 문법을 공부할 때는 어느 정상적인 JDK 배포판을 사용하더라도 핵심 Java 문법은 동일하다. 특정 회사의 JDK 자체보다 사용 중인 Java 버전과 프로젝트 요구사항을 확인하는 습관이 더 중요하다.
IDE에서 실행 버튼만 누르면 컴파일과 실행이 한 번에 처리되기 때문에 내부 과정을 놓치기 쉽다.
다음 파일이 있다고 해보자.
public class HelloJava {
public static void main(String[] args) {
System.out.println("Hello Java");
}
}
터미널에서는 직접 다음처럼 실행 과정을 확인할 수 있다.
javac HelloJava.java
java HelloJava
첫 번째 명령은 .java를 JVM이 실행할 수 있는 .class 바이트코드로 컴파일하고, 두 번째 명령은 JVM을 통해 컴파일 결과를 실행한다.
Java는 JDK 11부터 단일 소스 파일을 바로 실행하는 방식도 지원한다.
java HelloJava.java
이 경우 java 런처가 필요한 컴파일 과정을 내부적으로 처리한다.
Java 소스가 곧바로 모든 운영체제에서 실행되는 것은 아니다. 핵심은 컴파일 결과인 바이트코드와 JVM 사이의 역할 분리다.
HelloJava.java
↓ javac
HelloJava.class
↓
Windows JVM / macOS JVM / Linux JVM
↓
각 운영체제에 맞는 실제 실행
개발자는 Java 규격에 맞춰 코드를 작성하고, 운영체제별 JVM 구현이 그 차이를 흡수한다. 그래서 개발 PC가 Windows이고 운영 서버가 Linux여도 동일한 Java 바이트코드를 실행할 수 있는 구조가 만들어진다.
Java를 공부할 때 오류를 두 종류로 나눠 보는 습관이 중요하다.
System.out.println("hello")
세미콜론이 빠지면 컴파일 오류가 발생한다. 프로그램이 실행되기 전에 문법 단계에서 막힌다.
반면 다음은 문법 자체는 맞다.
int result = 10 / 0;
컴파일은 되지만 실제 실행 시 ArithmeticException이 발생한다. 이런 문제는 런타임 오류/예외다.
오류 메시지를 볼 때 "컴파일조차 되지 않는 문제인지", "실행 도중 발생한 문제인지"부터 구분하면 디버깅이 훨씬 쉬워진다.
public class OrderApp {
public static void main(String[] args) {
System.out.println("order service started");
}
}
이 짧은 코드에도 여러 규칙이 들어 있다.
System과 String의 대문자를 정확히 써야 한다.public 최상위 클래스는 파일 이름과 클래스 이름을 맞추는 것이 기본이다.{}는 코드의 범위를 만든다.;으로 끝난다.처음에는 이 규칙을 외우기보다 IDE의 오류 표시와 실행 결과를 계속 확인하면서 익히는 것이 좋다.
.java 파일은 javac를 통해 .class 바이트코드로 컴파일된다.main()은 일반적인 Java 애플리케이션의 시작점이다.;을 사용한다.{ }는 클래스, 메서드, 조건문 등의 코드 범위를 만든다.