본문으로 건너뛰기
안동민 개발노트 아이콘

안동민 개발노트

본문 시작
1장 : Java 소개와 개발 환경

소스 파일을 컴파일하고 실행하기

첫 프로그램은 짧지만 Java의 파일 이름, 클래스 이름, 컴파일 결과, 클래스 경로 규칙을 한꺼번에 보여 줍니다.

이 규칙을 IDE가 가려 준 상태로만 배우면 터미널이나 배포 환경에서 오류가 났을 때 원인을 찾기 어렵습니다.

본문의 예제는 별도 표기가 없는 한 기본 패키지의 독립 단일 파일로 작성합니다.

코드 블록의 public class 이름과 파일 이름을 같게 저장하면 그대로 컴파일할 수 있습니다.

이 절에서는 javacjava가 각각 어떤 입력을 받는지 확인합니다.


공개 클래스가 파일 이름을 정한다

public class HelloJava가 있는 소스는 HelloJava.java로 저장합니다.

이름이 다르면 컴파일러가 공개 타입을 찾을 파일을 결정할 수 없어 오류를 냅니다.


컴파일은 클래스 파일을 만든다

javac HelloJava.java는 문법과 타입을 검사한 뒤 HelloJava.class를 만듭니다.

이 단계에서는 main이 실제로 실행되지 않습니다.

첫 실행에서는 소스 파일과 생성된 클래스 파일을 같은 디렉터리에 두어 도구의 역할만 관찰합니다. javac HelloJava.java가 끝난 뒤 HelloJava.class가 생겼는지 확인하면 컴파일과 실행을 한 번에 처리하는 IDE보다 경계가 잘 보입니다.

HelloJava.java
public class HelloJava {
    public static void main(String[] args) {
        String learner = args.length == 0 ? "Java" : args[0];
        System.out.println("Hello, " + learner + "!");

        // System.out.println(missing); // 컴파일 오류: 선언되지 않은 변수
    }
}

java HelloJava는 파일 이름이 아니라 클래스 이름을 받으므로 확장자를 붙이지 않습니다. 아래 문장이 보이면 컴파일된 HelloJava 클래스를 JVM이 찾아 main 메서드부터 실행한 것입니다.

Hello, Java!

인자를 주면 두 번째 실행은 Hello, Andongmin!을 출력합니다. 컴파일 오류와 실행기 탐색 오류를 구분하세요.

HelloJava.java 저장

공개 최상위 타입 이름이 HelloJava이므로 파일도 HelloJava.java로 저장합니다. 대소문자까지 일치해야 다른 환경에서도 같은 명령이 동작합니다.

javac가 HelloJava.class 생성

javac HelloJava.java를 실행하고 종료 코드와 HelloJava.class 생성을 확인합니다. 오류가 있으면 아직 실행 단계로 넘어가지 않습니다.

java가 main을 찾아 호출

java HelloJava처럼 확장자를 뺀 클래스 이름을 전달합니다. 실행기는 클래스 경로에서 해당 타입을 읽고 정해진 모양의 main을 호출합니다.


실행기는 클래스 이름을 받는다

java HelloJava처럼 확장자 없이 완전한 클래스 이름을 전달합니다.

java HelloJava.class는 파일 경로와 클래스 이름을 혼동한 호출입니다.

java HelloJava.class처럼 파일을 넘기면 실행기가 HelloJava.class라는 이름의 클래스를 찾으려 하므로 실패합니다. 소스 실행 모드인 java HelloJava.java도 가능하지만, 지금은 .class가 만들어지는 과정을 보기 위해 컴파일과 실행을 분리합니다.

비교 1
javac HelloJava.java
java HelloJava
java HelloJava Andongmin
비교 2
// 잘못된 호출
// java HelloJava.class  // 클래스 이름 자리에 파일명을 전달함
// 파일을 Welcome.java로 저장 // public class 이름과 불일치

오류 시점을 세 갈래로 나눈다

소스 문법은 컴파일 오류, 클래스를 찾지 못하면 실행 준비 오류, 실행 중 잘못된 상태는 런타임 오류입니다.

어느 명령에서 멈췄는지를 먼저 기록하면 조사 범위가 크게 줄어듭니다.


클래스 경로는 탐색 시작점이다

실행기는 현재 디렉터리나 지정한 classpath 아래에서 패키지 경로에 맞는 클래스를 찾습니다.

파일이 존재해도 탐색 시작점이 잘못되면 클래스를 찾지 못합니다.

클래스 파일을 out 디렉터리에 생성하도록 javac -d out HelloJava.java를 실행한 뒤 java -cp out HelloJava로 호출해 보세요. 현재 디렉터리가 아니라 out이 클래스 탐색의 시작점이 된다는 사실을 확인하면 이후 패키지 오류도 같은 방식으로 추적할 수 있습니다.


첫 프로그램에서 파일, 클래스, 컴파일러, 실행기의 책임을 분리해 두면 이후 패키지와 모듈도 같은 원리로 확장할 수 있습니다.