Java를 처음 배울 때 잡아야 할 큰 그림
Java는 사람이 읽을 수 있는 소스 코드를 작성한 뒤, 그 코드를 JVM이 실행할 수 있는 바이트코드로 바꾸어 동작시키는 언어입니다. 여기서 핵심은 “한 번 작성하면 여러 환경에서 같은 규칙으로 실행한다”는 설계입니다. 실제 서비스에서는 운영체제, CPU, 서버 배포 방식이 서로 다를 수 있습니다. Java 프로그램은 먼저 .class 파일이라는 공통 형식으로 컴파일되고, 각 환경에 설치된 JVM이 그 바이트코드를 현재 컴퓨터에 맞게 실행합니다.
입문자는 문법보다 이 흐름을 먼저 이해하는 편이 좋습니다. 코드가 보이지 않는 곳에서 마법처럼 실행되는 것이 아니라, 개발 도구가 파일을 검사하고, 컴파일러가 구조를 확인하고, JVM이 정해진 시작점을 찾아 실행합니다. 오류 메시지도 이 과정 중 어디에서 막혔는지 알려주는 신호입니다. javac 단계에서 나는 오류는 대체로 문법, 이름, 타입 문제이고, java 실행 단계에서 나는 오류는 클래스 경로, 시작점, 실행 중 예외와 관련됩니다.
블록 조립장으로 비유하면 Java 소스 파일은 사람이 그린 설계도입니다. javac는 설계도를 장치가 읽을 수 있는 조립 명령 묶음으로 번역합니다. JVM은 그 명령 묶음을 받아 실제 작업대에서 실행합니다. 그래서 Java를 배운다는 것은 설계도 작성법만 배우는 일이 아니라, 설계도가 어떤 검사 과정을 지나 실행되는지 함께 배우는 일입니다.
Java 25 LTS 기준으로 학습한다는 의미
이 과정은 Java 25 LTS를 기준으로 합니다. LTS는 Long-Term Support의 약자로 장기간 유지보수되는 버전이라는 뜻입니다. 회사나 팀은 새 기능만 보고 버전을 고르지 않습니다. 보안 업데이트, 운영 안정성, 빌드 도구 호환성, 배포 환경의 지원 기간을 함께 봅니다. 입문 단계에서는 Preview 기능을 사용하지 않고, 정식으로 포함된 문법과 표준 API만 사용합니다.
Java는 오래된 언어이지만 멈춰 있는 언어가 아닙니다. 최신 Java에는 더 읽기 쉬운 switch 표현식, 간결한 문자열 처리, 개선된 런타임 성능, 현대적인 날짜와 시간 API처럼 실무에서 유용한 기능이 많이 들어 있습니다. 다만 초반에는 모든 최신 기능을 한꺼번에 외울 필요가 없습니다. 지금은 다음 네 가지 흐름만 분명히 잡으면 충분합니다.
- 소스 파일은
.java확장자를 가진 텍스트 파일입니다. javac는 소스 파일을.class바이트코드 파일로 컴파일합니다.java명령은 JVM을 통해 클래스의main메서드를 실행합니다.- 표준 라이브러리는 문자열, 숫자, 날짜, 파일, 컬렉션 같은 공통 기능을 제공합니다.
JDK, JVM, 표준 API의 역할 구분
JDK는 Java Development Kit입니다. 이름 그대로 개발할 때 필요한 도구 묶음입니다. 입문자가 직접 자주 만나는 도구는 java와 javac입니다. javac는 컴파일러이고, java는 프로그램 실행 명령입니다. 여기에 문서화 도구, 패키징 도구, 런타임 구성 도구 등도 포함됩니다. IDE가 버튼 하나로 실행해 주더라도 내부에서는 이 도구들이 비슷한 일을 수행합니다.
JVM은 Java Virtual Machine입니다. .class 파일 안의 바이트코드를 읽고 실행합니다. JVM은 메모리를 관리하고, 필요한 클래스를 불러오고, 실행 중 오류가 발생하면 예외 정보를 만듭니다. Java가 “가상 머신 위에서 실행된다”고 말할 때의 가상 머신은 운영체제 전체를 흉내 내는 거대한 프로그램이라는 뜻이 아니라, Java 바이트코드를 실행하는 규격화된 실행 환경을 뜻합니다.
표준 API는 미리 만들어 둔 기능 모음입니다. 예를 들어 System.out.println은 화면 출력 기능이고, String은 문자열을 다루는 클래스이며, java.time.LocalDate는 날짜를 표현하는 클래스입니다. 모든 기능을 처음부터 직접 만들지 않고 검증된 표준 API를 조합하는 능력이 Java 실력의 큰 부분입니다.
설치 확인과 첫 진단
터미널에서 다음 명령을 각각 실행합니다.
java --version
javac --version
두 명령 모두 Java 25 계열을 표시하면 학습 환경이 준비된 것입니다. java는 실행되는데 javac가 없다고 나오면 JRE 중심 환경만 잡혀 있거나, JDK의 bin 경로가 PATH에 연결되지 않았을 수 있습니다. 반대로 두 명령의 버전이 서로 다르면 여러 JDK가 설치되어 있고 터미널이 서로 다른 위치의 명령을 찾고 있을 가능성이 있습니다.
운영체제마다 PATH를 설정하는 화면은 다르지만 진단 순서는 같습니다. 먼저 설치된 JDK 위치를 확인하고, 그 안의 bin 디렉터리에 java와 javac가 있는지 봅니다. 그다음 새 터미널을 열어 버전을 다시 확인합니다. 기존 터미널은 이전 환경 변수를 계속 들고 있을 수 있으므로 설정 직후에는 새 창에서 확인하는 습관이 좋습니다.
가장 작은 실행 흐름 만들기
작업 폴더를 하나 만들고 Main.java 파일을 생성합니다. 아래 예제는 Chapter 2에서 더 자세히 뜯어볼 예정이므로 지금은 흐름에 집중하세요.
public class Main {
public static void main(String[] args) {
System.out.println("Java 25 학습 환경이 준비되었습니다.");
}
}
같은 폴더에서 컴파일합니다.
javac Main.java
성공하면 별도 메시지 없이 Main.class 파일이 생깁니다. 아무 출력이 없어서 당황할 수 있지만, 터미널 도구는 성공했을 때 조용한 경우가 많습니다. 이어서 실행합니다.
java Main
예상 출력은 다음과 같습니다.
Java 25 학습 환경이 준비되었습니다.
여기서 java Main.java가 아니라 java Main을 입력하는 이유를 눈여겨보세요. 컴파일 후 실행하는 대상은 소스 파일 이름이 아니라 클래스 이름입니다. 파일에는 .java가 붙지만 실행 명령에는 확장자를 붙이지 않습니다.
소스 파일과 클래스 이름
Java에서 public class Main처럼 공개 클래스가 있으면 파일 이름은 Main.java여야 합니다. 대소문자도 맞아야 합니다. main.java, Main.txt, Start.java처럼 이름이 어긋나면 컴파일러가 파일 이름과 공개 클래스 이름이 다르다고 알려줍니다.
초반에는 파일 하나에 클래스 하나만 두고, 클래스 이름은 Main으로 고정해 연습하는 편이 편합니다. 나중에 객체지향을 배우면 여러 클래스를 나누고 패키지를 구성하지만, 지금은 실행 흐름과 문법 오류를 빠르게 경험하는 것이 더 중요합니다.
Main.class는 직접 편집하지 않습니다. 사람이 수정하는 파일은 .java이고, .class는 컴파일 결과물입니다. 소스 코드를 바꾼 뒤 다시 컴파일하지 않으면 실행 결과는 이전 .class 기준으로 남습니다. “분명히 문장을 고쳤는데 출력이 그대로”라면 대부분 컴파일을 다시 하지 않았거나, 다른 폴더에서 실행하고 있는 상황입니다.
IDE와 터미널의 관계
IntelliJ IDEA, Eclipse, VS Code 같은 IDE를 쓰면 실행 버튼으로 컴파일과 실행을 한 번에 처리할 수 있습니다. 그래도 터미널 흐름을 한 번은 직접 해봐야 합니다. IDE의 편리함 뒤에서 어떤 명령이 실행되는지 알아야 오류가 났을 때 원인을 좁힐 수 있습니다.
예를 들어 IDE에서는 실행되는데 터미널에서는 안 된다면 프로젝트 설정, 작업 디렉터리, JDK 선택이 서로 다를 수 있습니다. 반대로 터미널에서는 실행되는데 IDE에서 안 된다면 IDE가 다른 JDK를 바라보거나 파일을 프로젝트 소스로 인식하지 못하는 것일 수 있습니다.
실무에서는 빌드 도구가 컴파일을 담당합니다. Maven이나 Gradle 같은 도구가 대표적입니다. 하지만 빌드 도구도 결국 소스 파일을 컴파일하고 테스트하고 실행 가능한 산출물을 만드는 일을 자동화합니다. 처음부터 도구를 많이 얹기보다 javac와 java의 기본 흐름을 몸에 익혀두면 이후 도구가 훨씬 덜 낯설어집니다.
오류 메시지를 읽는 방법
오류는 실패 통보가 아니라 위치가 표시된 피드백입니다. 다음 코드는 세미콜론이 빠져 있습니다.
public class Main {
public static void main(String[] args) {
System.out.println("세미콜론 확인")
}
}
컴파일하면 ';' expected와 비슷한 메시지가 나옵니다. 메시지는 문제가 발견된 줄을 가리키지만, 실제 원인은 바로 앞 토큰이나 이전 줄에 있을 때도 많습니다. 괄호, 따옴표, 세미콜론 오류는 특히 주변 줄을 함께 확인해야 합니다.
실행 단계 오류도 자주 만납니다. Could not find or load main class Main은 JVM이 Main 클래스를 찾지 못했다는 뜻입니다. 현재 폴더에 Main.class가 있는지, 명령을 실행한 위치가 맞는지, 클래스 이름 대소문자가 정확한지 확인하세요.
실행 흐름을 스스로 설명해 보기
초보 단계에서 가장 좋은 복습 방법은 명령을 외우는 것이 아니라 실행 흐름을 말로 설명하는 것입니다. “나는 Main.java라는 소스 파일을 만들었다. javac가 이 파일을 읽어 문법과 타입을 검사했다. 검사에 성공해서 Main.class라는 바이트코드 파일이 생겼다. java Main 명령은 JVM에게 Main 클래스를 찾아 main 메서드부터 실행하라고 요청했다.” 이렇게 말할 수 있으면 첫 장의 핵심을 이해한 것입니다.
이 설명은 프로젝트가 커져도 그대로 확장됩니다. 파일이 여러 개가 되고, 패키지가 생기고, Gradle이 컴파일을 대신해도 큰 흐름은 같습니다. 개발자는 소스 코드를 작성하고, 도구는 소스 코드를 검사해 실행 가능한 형태로 만들고, 런타임은 정해진 시작점에서 프로그램을 실행합니다. 차이는 자동화 수준과 파일 배치 방식입니다.
또 하나 중요한 점은 Java가 컴파일 언어라는 사실입니다. 소스 파일을 바꾸는 일과 실행 결과가 바뀌는 일 사이에는 컴파일이라는 단계가 있습니다. IDE는 이 단계를 자동으로 처리해 주기도 하지만, 자동 처리에만 기대면 문제가 생겼을 때 원인을 찾기 어렵습니다. 터미널에서 직접 컴파일하고 실행해 본 경험은 빌드 오류, 배포 오류, 클래스 경로 오류를 읽는 기초 체력이 됩니다.
학습 폴더를 깔끔하게 유지하는 법
입문 예제를 많이 실행하다 보면 여러 폴더에 Main.java와 Main.class가 흩어집니다. 처음에는 장별로 폴더를 나누는 방식이 좋습니다. 예를 들어 chapter01, chapter02처럼 폴더를 만들고, 각 폴더 안에서 javac Main.java, java Main을 실행합니다. 그러면 이전 장에서 만든 Main.class를 실수로 실행할 가능성이 줄어듭니다.
파일 탐색기에서 확장자가 숨겨져 있으면 Main.java.txt 같은 파일을 만들고도 알아차리지 못할 수 있습니다. 터미널에서 실제 이름을 확인하세요. 컴파일러가 “file not found”라고 말할 때는 코드 내용보다 파일 이름과 현재 위치를 먼저 확인하는 편이 빠릅니다. 환경을 여러 번 바꾸었다면 java --version과 javac --version도 자주 확인하세요. 이 명령들은 단순 설치 확인이 아니라 지금 이 터미널이 어떤 JDK를 보고 있는지 알려주는 진단 도구입니다.
직접 해보기
workspace-java같은 새 폴더를 만들고Main.java를 저장합니다.javac Main.java와java Main을 순서대로 실행합니다.- 출력 문장을 다른 문장으로 바꾼 뒤 컴파일하지 않고 바로 실행해 봅니다.
- 다시 컴파일한 뒤 실행하여 결과 차이를 확인합니다.
- 파일 이름을 임시로
Start.java로 바꾸어 오류 메시지를 읽고 다시 되돌립니다.
확인 포인트
소스 수정 후 재컴파일하지 않으면 JVM은 이전에 만들어진 Main.class를 실행합니다. Java 학습 초반에는 “수정, 컴파일, 실행”의 세 단계를 의식적으로 분리해 보세요.
복습 체크리스트
다음 질문에 짧게 답할 수 있으면 다음 장으로 넘어가도 좋습니다. JDK와 JVM은 각각 어떤 일을 하나요? javac Main.java와 java Main은 어떤 점이 다른가요? 소스 파일을 고쳤는데 출력이 바뀌지 않을 때 먼저 확인할 것은 무엇인가요? 공개 클래스 이름과 파일 이름은 왜 맞아야 하나요?
답이 막히면 코드를 더 많이 외우기보다 실행 순서를 다시 손으로 그려 보세요. 소스 파일, 컴파일러, 바이트코드, JVM, 출력 결과를 화살표로 연결하면 흐름이 안정됩니다. 앞으로 배우는 모든 문법은 이 흐름 위에 올라갑니다.
이번 장의 정리
Java 프로그램은 .java 파일에서 시작하지만 실행은 .class 바이트코드를 통해 이루어집니다. JDK는 개발 도구 묶음이고, JVM은 바이트코드 실행 환경이며, 표준 API는 자주 필요한 기능을 미리 제공하는 라이브러리입니다. 이 구분이 잡히면 앞으로 배우는 변수, 조건문, 반복문도 단순한 문법 암기가 아니라 JVM에 전달할 명령을 체계적으로 작성하는 과정으로 보입니다.