본문 바로가기

첫 Java 프로그램

Hello.java를 직접 저장하고 javac로 컴파일한 뒤 java로 실행합니다.

첫 프로그램의 목적은 문법을 많이 배우는 것이 아니라 작성 → 컴파일 → 실행의 한 바퀴를 성공시키는 것입니다.

편집기는 메모장, Visual Studio Code, IntelliJ IDEA 등 무엇을 사용해도 됩니다.

다만 서식 있는 문서가 아니라 일반 텍스트로 저장해야 합니다.

Hello.java의 파일, 클래스, main, 출력 문장 포함 관계

NESTED · SOURCE CONTAINMENT

Hello.java를 바깥에서 안쪽으로 읽는 세 범위

코드의 단어를 따로 외우기보다 포함 관계를 따라간다. 파일 안에 공개 클래스가 있고, 그 클래스 안의 main에서 출력 문장이 실행된다.

Hello.java를 바깥에서 안쪽으로 읽는 세 범위 Hello.java 파일이 public class Hello를 포함하고, 그 클래스의 main 메서드 안에 System.out.println 문장이 있으며 세미콜론이 문장을 끝내는 포함 관계다. FILE · Hello.java 클래스 이름 = 파일 이름 public class Hello 가장 바깥 코드 범위 public static void main(String[] args) 이 예제의 실행 시작점 System.out.println("Hello, Java!"); 세미콜론은 이 실행 문장의 종결 표식 파일 → 클래스 → main → 출력 문장
Hello.java를 바깥에서 안쪽으로 읽는 세 범위 파일→공개 클래스→main→출력 문장의 네 포함 영역; 포함은 호출 화살표가 아님. 상세 문구와 명령은 바로 아래 원래 설명에서 확인합니다. FILE · Hello.java 공개 클래스 이름 = 파일 이름 public class Hello 가장 바깥 클래스 범위 public static void main(String[] args) 이 예제의 실행 시작점 System.out.println ("Hello, Java!"); 문장 끝은 세미콜론 ;
  1. 파일 · Hello.java

    파일은 공개 클래스 선언을 담고, 공개 클래스 이름 Hello와 파일명이 정확히 일치합니다.

  2. 클래스 · public class Hello

    첫 중괄호부터 마지막 중괄호까지가 Hello 클래스에 속하는 가장 바깥 코드 범위입니다.

  3. 진입점 · main

    JVM은 클래스 범위 안의 public static void main(String[] args)를 찾아 실행을 시작합니다.

  4. 실행 문장 · println

    main 안의 System.out.println(...);이 문자열 한 줄을 표준 출력에 쓰고, 세미콜론이 문장을 끝냅니다.

포함 관계는 파일 → 클래스 → 메서드 → 문장 순서이며, 각 중괄호 쌍이 어느 범위에 속하는지 먼저 확인한다.


5줄짜리 Hello World

java-board/src 폴더에 Hello.java 파일을 만들고 다음 내용을 그대로 저장합니다.

src/Hello.java — 완전한 파일
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}

처음에는 모든 단어를 외울 필요가 없습니다.

각 줄의 역할은 다음과 같습니다.

  • public class Hello는 Hello라는 프로그램 단위를 선언합니다.
  • 첫 {와 마지막 }는 Hello에 속하는 범위를 표시합니다.
  • main은 프로그램이 시작할 위치입니다.
  • System.out.println(...)은 괄호 안의 글을 한 줄 출력합니다.
  • 세미콜론 ;은 출력 문장이 끝났음을 표시합니다.

Java는 대소문자를 구분합니다.

hello, Hello, HELLO는 서로 다른 이름입니다.

공개 클래스 이름이 Hello이므로 파일명도 정확히 Hello.java여야 합니다.

저장할 때 인코딩은 UTF-8로 선택합니다. Windows 편집기에서 파일 형식을 “모든 파일”로 선택하지 않으면 Hello.java.txt가 될 수 있으므로 파일 탐색기의 확장자 표시를 켜 실제 이름을 확인하세요.

명령에 적는 src/Hello.java는 java-board에서 출발한 위치입니다. 터미널이 src 안에 있다면 먼저 한 단계 위인 java-board로 돌아와야 합니다.


컴파일하기

PowerShell이 java-board 폴더에 있는지 확인한 뒤 다음 명령을 실행합니다.

javac -d out src/Hello.java

아무 메시지도 나오지 않으면 컴파일에 성공한 것입니다.

성공한 명령이 조용히 끝나는 것은 이상한 일이 아닙니다.

out 폴더를 확인합니다.

Get-ChildItem out
Hello.class

Hello.java는 사람이 편집하는 소스 파일이고 Hello.class는 javac가 만든 실행용 파일입니다.

.class를 편집하지 않습니다.


실행하기

다음 명령에서 -cp out은 실행할 클래스를 out 폴더에서 찾으라는 뜻입니다.

마지막 Hello는 파일 경로가 아니라 실행할 클래스 이름이므로 .class를 붙이지 않습니다.

java -cp out Hello
Hello, Java!

이 출력이 보이면 작성·컴파일·실행 세 단계가 모두 성공했습니다.

src/Hello.java  --javac-->  out/Hello.class  --java-->  화면 출력

소스를 바꾸면 다시 컴파일한다

출력 문자열을 다음처럼 바꿔 저장합니다.

System.out.println("회원가입 시작");

java 명령만 다시 실행하면 이전 출력이 나옵니다.

JVM은 방금 고친 .java 파일이 아니라 기존 Hello.class를 실행하기 때문입니다.

직접 확인하려면 문자열을 바꿔 저장한 직후에는 실행 명령만 입력하고, 이어서 컴파일과 실행을 차례로 입력해 두 출력을 비교하세요. 첫 출력이 이전 문구인 까닭과 두 번째 출력이 바뀐 까닭을 설명할 수 있으면 세 단계를 구분한 것입니다.

먼저 다시 컴파일한 뒤 실행합니다.

javac -d out src/Hello.java
java -cp out Hello
회원가입 시작

IDE의 실행 버튼은 저장과 컴파일을 대신 처리할 수 있습니다.

이 교재에서는 각 단계가 보이도록 처음에는 터미널 명령을 사용합니다.

java는 최신 소스가 아니라 마지막 class를 실행한다

소스 저장 뒤 class가 즉시 바뀌지 않고 javac 성공 때만 갱신되는 상태 전환입니다. 본문의 이전 출력 재현과 직접 연결돼 저장·컴파일·실행 장면이 유용합니다.

Hello 소스와 class의 신선도 및 실행 흐름

FLOWCHART · ARTIFACT FRESHNESS

java는 최신 소스가 아니라 마지막 class를 실행한다

소스를 저장하는 일과 class를 갱신하는 일은 별개다. java는 out에서 발견한 마지막 class를 실행하므로 재컴파일을 생략하거나 실패하면 이전 출력이 남을 수 있다.

java는 최신 소스가 아니라 마지막 class를 실행한다 Hello.java를 저장한 뒤 javac 성공 여부에 따라 Hello.class가 갱신되거나 기존 상태를 유지하고, java가 out에서 발견한 class의 main을 호출해 그 class 상태에 해당하는 출력을 만드는 흐름이다. src/Hello.java 수정 · 저장 소스 상태만 먼저 바뀜 javac가 성공했나? 마지막 저장 이후 class는 갱신되지 않음 기존 class 유지 · 최초면 아직 없음 미실행·실패 out/Hello.class 갱신 JVM bytecode · 현재 소스 반영 성공 java -cp out Hello out에서 Hello.class를 찾음 발견한 class의 main 호출 표준 출력은 class의 신선도를 반영 이전 출력이면 저장 뒤 컴파일을 다시 했는지 확인합니다.
java는 최신 소스가 아니라 마지막 class를 실행한다 저장과 컴파일 성공 여부의 두 class 상태, 재합류 뒤 class 탐색과 main 호출. 상세 문구와 명령은 바로 아래 원래 설명에서 확인합니다. 미실행·실패 성공 src/Hello.java 수정·저장 소스 상태만 먼저 바뀜 저장 뒤 javac가 성공했나? class 미갱신 기존 값 유지 최초라면 아직 없음 out/ Hello.class 소스 반영 bytecode java -cp out Hello Hello.class 탐색 main 호출·출력 발견한 class 상태를 반영 이전 문구면 재컴파일 확인
  1. 소스 수정과 저장

    src/Hello.java를 저장하면 소스만 바뀌며 out/Hello.class는 자동으로 갱신되지 않습니다.

  2. javac 성공 여부

    javac -d out src/Hello.java가 성공해야 class가 현재 소스를 반영합니다. 명령을 생략하거나 실패하면 기존 class가 남고, 최초라면 class가 아직 없습니다.

  3. classpath에서 class 탐색

    java -cp out Hello에서 out은 classpath root이고 Hello는 확장자가 없는 binary class name입니다.

  4. JVM 진입

    java launcher가 JVM을 시작하고, JVM은 발견한 class의 main을 호출해 표준 출력을 만듭니다.

  5. 오래된 출력 해석

    오류 없이 이전 문구가 보이면 마지막 성공 컴파일 이후 소스만 바뀌었는지 확인합니다. java는 최신 .java를 직접 읽지 않습니다.

컴파일 실패 뒤에도 이전 .class가 남을 수 있으므로, 실행 성공만으로 최신 소스가 반영됐다고 단정하지 않습니다. 최초 컴파일 전에는 .class가 없어 클래스 탐색에서 실패하고, 그림의 main 호출·출력까지 진행하지 않습니다.

이 예의 조건

  • javac 성공/미실행·실패는 서로 다른 경로이다.
관계도의 보충 설명
원 도표의 설명과 주석
구분내용
전체 읽기 정보java는 최신 소스가 아니라 마지막 class를 실행한다 Hello 소스와 class의 신선도 및 실행 흐름 FLOWCHART · ARTIFACT FRESHNESS java는 최신 소스가 아니라 마지막 class를 실행한다 소스를 저장하는 일과 class를 갱신하는 일은 별개다. java는 out에서 발견한 마지막 class를 실행하므로 재컴파일을 생략하거나 실패하면 이전 출력이 남을 수 있다. 소스 수정과 저장 src/Hello.java 를 저장하면 소스만 바뀌며 out/Hello.class 는 자동으로 갱신되지 않습니다. javac 성공 여부 javac -d out src/Hello.java 가 성공해야 class가 현재 소스를 반영합니다. 명령을 생략하거나 실패하면 기존 class가 남고, 최초라면 class가 아직 없습니다. classpath에서 class 탐색 java -cp out Hello 에서 out 은 classpath root이고 Hello 는 확장자가 없는 binary class name입니다. JVM 진입 java launcher가 JVM을 시작하고, JVM은 발견한 class의 main 을 호출해 표준 출력을 만듭니다. 오래된 출력 해석 오류 없이 이전 문구가 보이면 마지막 성공 컴파일 이후 소스만 바뀌었는지 확인합니다. java 는 최신 .java 를 직접 읽지 않습니다. 컴파일 실패 뒤에도 이전 .class 가 남을 수 있으므로, 실행 성공만으로 최신 소스가 반영됐다고 단정하지 않습니다. 최초 컴파일 전에는 .class 가 없어 클래스 탐색에서 실패하고, 그림의 main 호출·출력까지 진행하지 않습니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
소스 저장

Hello.java의 새 내용을 보관합니다.

  • src: 새 소스
  • class: 기존 상태
  • 파일 저장은 class를 자동으로 갱신하지 않는다.
컴파일 판정

javac 성공이면 out의 class가 갱신됩니다.

  • 성공: 현재 소스를 반영한 class
  • 미실행/실패: 기존 class 유지 또는 최초면 없음
  • 현재 소스와 산출물의 신선도는 성공한 컴파일에 달려 있다.
산출물 실행

java -cp out Hello는 찾은 class의 main을 호출합니다.

  • 입력: out/Hello.class
  • 출력 기준: 그 class의 상태
  • 소스가 최신이어도 실행한 산출물이 오래되면 이전 출력이 남는다.

java는 최신 소스가 아니라 마지막 class를 실행한다

소스 저장 뒤 class가 즉시 바뀌지 않고 javac 성공 때만 갱신되는 상태 전환입니다. 본문의 이전 출력 재현과 직접 연결돼 저장·컴파일·실행 장면이 유용합니다.

Hello 소스와 class의 신선도 및 실행 흐름

FLOWCHART · ARTIFACT FRESHNESS

java는 최신 소스가 아니라 마지막 class를 실행한다

소스를 저장하는 일과 class를 갱신하는 일은 별개다. java는 out에서 발견한 마지막 class를 실행하므로 재컴파일을 생략하거나 실패하면 이전 출력이 남을 수 있다.

java는 최신 소스가 아니라 마지막 class를 실행한다 Hello.java를 저장한 뒤 javac 성공 여부에 따라 Hello.class가 갱신되거나 기존 상태를 유지하고, java가 out에서 발견한 class의 main을 호출해 그 class 상태에 해당하는 출력을 만드는 흐름이다. src/Hello.java 수정 · 저장 소스 상태만 먼저 바뀜 javac가 성공했나? 마지막 저장 이후 class는 갱신되지 않음 기존 class 유지 · 최초면 아직 없음 미실행·실패 out/Hello.class 갱신 JVM bytecode · 현재 소스 반영 성공 java -cp out Hello out에서 Hello.class를 찾음 발견한 class의 main 호출 표준 출력은 class의 신선도를 반영 이전 출력이면 저장 뒤 컴파일을 다시 했는지 확인합니다.
java는 최신 소스가 아니라 마지막 class를 실행한다 저장과 컴파일 성공 여부의 두 class 상태, 재합류 뒤 class 탐색과 main 호출. 상세 문구와 명령은 바로 아래 원래 설명에서 확인합니다. 미실행·실패 성공 src/Hello.java 수정·저장 소스 상태만 먼저 바뀜 저장 뒤 javac가 성공했나? class 미갱신 기존 값 유지 최초라면 아직 없음 out/ Hello.class 소스 반영 bytecode java -cp out Hello Hello.class 탐색 main 호출·출력 발견한 class 상태를 반영 이전 문구면 재컴파일 확인
  1. 소스 수정과 저장

    src/Hello.java를 저장하면 소스만 바뀌며 out/Hello.class는 자동으로 갱신되지 않습니다.

  2. javac 성공 여부

    javac -d out src/Hello.java가 성공해야 class가 현재 소스를 반영합니다. 명령을 생략하거나 실패하면 기존 class가 남고, 최초라면 class가 아직 없습니다.

  3. classpath에서 class 탐색

    java -cp out Hello에서 out은 classpath root이고 Hello는 확장자가 없는 binary class name입니다.

  4. JVM 진입

    java launcher가 JVM을 시작하고, JVM은 발견한 class의 main을 호출해 표준 출력을 만듭니다.

  5. 오래된 출력 해석

    오류 없이 이전 문구가 보이면 마지막 성공 컴파일 이후 소스만 바뀌었는지 확인합니다. java는 최신 .java를 직접 읽지 않습니다.

컴파일 실패 뒤에도 이전 .class가 남을 수 있으므로, 실행 성공만으로 최신 소스가 반영됐다고 단정하지 않습니다. 최초 컴파일 전에는 .class가 없어 클래스 탐색에서 실패하고, 그림의 main 호출·출력까지 진행하지 않습니다.

이 예의 조건

  • javac 성공/미실행·실패는 서로 다른 경로이다.

관계도의 보충 설명

원 도표의 설명과 주석
구분내용
전체 읽기 정보java는 최신 소스가 아니라 마지막 class를 실행한다 Hello 소스와 class의 신선도 및 실행 흐름 FLOWCHART · ARTIFACT FRESHNESS java는 최신 소스가 아니라 마지막 class를 실행한다 소스를 저장하는 일과 class를 갱신하는 일은 별개다. java는 out에서 발견한 마지막 class를 실행하므로 재컴파일을 생략하거나 실패하면 이전 출력이 남을 수 있다. 소스 수정과 저장 src/Hello.java 를 저장하면 소스만 바뀌며 out/Hello.class 는 자동으로 갱신되지 않습니다. javac 성공 여부 javac -d out src/Hello.java 가 성공해야 class가 현재 소스를 반영합니다. 명령을 생략하거나 실패하면 기존 class가 남고, 최초라면 class가 아직 없습니다. classpath에서 class 탐색 java -cp out Hello 에서 out 은 classpath root이고 Hello 는 확장자가 없는 binary class name입니다. JVM 진입 java launcher가 JVM을 시작하고, JVM은 발견한 class의 main 을 호출해 표준 출력을 만듭니다. 오래된 출력 해석 오류 없이 이전 문구가 보이면 마지막 성공 컴파일 이후 소스만 바뀌었는지 확인합니다. java 는 최신 .java 를 직접 읽지 않습니다. 컴파일 실패 뒤에도 이전 .class 가 남을 수 있으므로, 실행 성공만으로 최신 소스가 반영됐다고 단정하지 않습니다. 최초 컴파일 전에는 .class 가 없어 클래스 탐색에서 실패하고, 그림의 main 호출·출력까지 진행하지 않습니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
소스 저장

Hello.java의 새 내용을 보관합니다.

  • src: 새 소스
  • class: 기존 상태
  • 파일 저장은 class를 자동으로 갱신하지 않는다.
컴파일 판정

javac 성공이면 out의 class가 갱신됩니다.

  • 성공: 현재 소스를 반영한 class
  • 미실행/실패: 기존 class 유지 또는 최초면 없음
  • 현재 소스와 산출물의 신선도는 성공한 컴파일에 달려 있다.
산출물 실행

java -cp out Hello는 찾은 class의 main을 호출합니다.

  • 입력: out/Hello.class
  • 출력 기준: 그 class의 상태
  • 소스가 최신이어도 실행한 산출물이 오래되면 이전 출력이 남는다.

첫 소스를 읽는 순서

긴 선언을 한 덩어리로 외우기보다 바깥에서 안쪽으로 읽습니다.

  1. class Hello: Hello라는 클래스의 범위
  2. main: 실행이 시작되는 메서드의 범위
  3. println: 실제로 실행할 출력 문장

클래스와 메서드가 정확히 무엇인지는 뒤 장에서 작은 예제로 다시 배웁니다.

지금은 중괄호의 짝과 문장의 실행 순서를 확인합니다.


연습 문제

src/NewMember.java를 만들고 가입할 이메일과 역할을 두 줄로 출력하세요.

출력 예
[email protected]
role=member

파일명과 공개 클래스 이름을 NewMember로 맞추고 다음 명령으로 확인합니다.

javac -d out src/NewMember.java
java -cp out NewMember