많은 입문자가 자바 학습 첫 단계에서 통합개발환경(IDE)이라는 무거운 도구를 먼저 설치한다. 프로젝트 생성 버튼을 누르고 실행 버튼을 누르면 코드가 돌아가는 과정을 경험하지만, 정작 그 사이에서 어떤 일이 벌어지는지는 알지 못한 채 다음 단계로 넘어간다. 학습 과정을 지켜보면 열 명 중 여덟 명은 클래스패스(classpath)라는 개념을 접하기 전에 포기하거나, 컴파일과 실행의 차이를 설명하지 못하는 경우가 많다. 개발 도구가 너무 편리해진 탓에 언어의 기본기가 무너지는 셈이다.
자바는 분명히 배우기 좋은 언어다. 객체지향 개념을 강제하고, 메모리 관리를 자동화하며, 플랫폼 독립성을 제공한다. 그런데 이러한 장점이 오히려 입문자에게는 장벽이 되기도 한다. 이클립스나 인텔리제이 같은 도구는 코드 작성, 컴파일, 실행, 디버깅을 하나의 인터페이스에서 처리하므로 사용자가 자바의 동작 원리를 의식하지 못하게 만든다. 결국 학습자는 도구 사용법을 익힐 뿐 언어의 구조를 이해하지 못한다. 따라서 처음부터 통합개발환경을 배제하고 명령 프롬프트나 터미널에서 직접 자바 파일을 다루는 방식이 오히려 더 확실한 학습 경로가 될 수 있다.
먼저 절대적으로 필요한 것은 JDK(Java Development Kit) 설치다. 여기서 주의할 점이 있다. 최신 버전의 JDK를 받았다면 이미 컴파일러와 실행 도구가 포함되어 있으므로 따로 설치할 것이 없다. 다만 환경 변수 설정에서 실수하는 경우가 잦다. PATH에 JDK의 bin 폴더 경로를 등록해야 터미널에서 javac와 java 명령이 동작하는데, 입문자들은 이 과정을 건너뛰거나 경로를 잘못 입력하여 명령어가 인식되지 않는 상황을 겪는다. 이때 본인 컴퓨터의 JDK 설치 위치를 정확히 확인하고, PATH에 추가한 뒤 터미널을 재시작해야 한다. 절대 재시작하지 않고 “왜 안 되지?”라며 헤매는 경우가 많다.
이제 본격적으로 자바 기초 문법과 객체지향 개념을 명령줄 환경에서 익혀보자. 우선 메모장이나 텍스트 에디터로 간단한 소스 파일을 만든다. 파일명은 반드시 public 클래스 이름과 동일해야 하며 확장자는 .java로 저장해야 한다. 예를 들어 “HelloJava.java”라는 파일에 코드를 작성하고 터미널에서 “javac HelloJava.java” 명령을 입력하면 컴파일이 실행된다. 성공적으로 컴파일되면 “HelloJava.class”라는 바이트코드 파일이 생성된다. 이 파일은 사람이 읽을 수 없는 형태이지만, JVM(Java Virtual Machine)이 이 파일을 읽어 실행한다. “java HelloJava” 명령이 바로 실행 단계다. 여기서 확장자 .class를 붙이지 않는 것이 핵심이다. 입문자들은 “java HelloJava.class”라고 입력해 오류를 마주하는데, 이는 매우 흔한 실수다.
이 과정을 통해서 학습자는 컴파일과 실행이 완전히 다른 단계임을 몸소 깨닫게 된다. 통합개발환경에서는 버튼 하나로 처리되던 것이 두 개의 명령어로 분리되면서, 코드가 기계어로 직접 해석되는 것이 아니라 중간 언어인 바이트코드로 변환되고 JVM이 이를 해석한다는 사실을 자연스럽게 받아들일 수 있다. 객체지향 개념도 이 흐름에서 더 명확해진다. 클래스는 설계도면이고, 객체는 그 설계도면으로 찍어낸 실체다. 파일 안에 public static void main(String[] args)라는 시그니처가 왜 필요한지, 클래스와 인스턴스가 어떤 차이를 갖는지 명령줄에서 실행하며 확인하면 이론서에서 수십 번 읽는 것보다 훨씬 빨리 이해된다.
자바에서 자주 쓰는 자료구조 활용법도 명령줄 환경에서 충분히 학습할 수 있다. 배열은 기본이지만 크기가 고정되어 있어 동적으로 데이터를 다루려면 ArrayList나 HashMap 같은 컬렉션을 사용해야 한다. 예를 들어 이름과 점수를 저장하는 프로그램을 만들 때, 배열로 선언해 버리면 나중에 데이터 추가가 불가능해진다. 이때 java.util 패키지의 ArrayList를 import해서 사용하면 크기 제약 없이 데이터를 추가하고 삭제할 수 있다. 문제는 입문자들이 import 문을 생략하거나 패키지 경로를 잘못 입력하는 실수를 저지른다. 컴파일러가 “기호를 찾을 수 없음”이라는 오류 메시지를 던지면, 그래서 우리가 클래스패스와 패키지 개념을 알아야 하는 것이다.
이 지점에서 자연스럽게 예외 처리와 디버깅의 중요성이 드러난다. 명령줄에서 실행 중인 프로그램이 오류를 발생시키면 통합개발환경처럼 친절한 안내가 없다. 다만 스택 트레이스(stack trace)가 터미널에 출력되는데, 입문자들은 이 긴 글을 보고 당황한다. 하지만 스택 트레이스는 오류의 위치와 원인을 추적하는 가장 좋은 도구다. 첫 줄에 예외 종류, 다음 줄에 발생한 파일명과 줄 번호, 그 아래에 호출 경로가 순서대로 표시된다. 자바 예외 처리의 기본인 try-catch 블록을 활용하여 프로그램이 비정상 종료되는 것을 막고, 사용자에게 의미 있는 메시지를 보여주는 방법을 익히면 디버깅 시간이 현저히 줄어든다.
명령줄 학습이 낯설게 느껴질 수 있지만, 이 방식은 단순히 자바 언어만 배우는 데 그치지 않는다. 개발 환경이 어떻게 구성되어 있는지, 실제 서버에서는 어떤 방식으로 프로그램이 배포되고 실행되는지 이해하는 기반이 된다. 예를 들어 리눅스 서버에서 자바 애플리케이션을 운영하려면 통합개발환경이 아닌 명령줄 인터페이스를 사용해야 하는 경우가 많다. 즉 명령줄을 미리 익혀두면 나중에 실무 환경에 적응하는 속도가 훨씬 빨라진다. 입문자들이 이 사실을 인지하지 못하고 통합개발환경 중심으로만 학습하다가 서버 환경에서 막히는 사례는 비일비재하다.
그리고 한 가지 경고할 점이 있다. 처음부터 너무 거대한 프로젝트를 만들려는 욕심을 버려야 한다. 명령줄에서는 자동완성 기능이 없거나 제한적이므로 타이핑 오류가 잦다. 입문자들이 코드 컴파일에서 잦은 문법 오류를 경험하면 자존감이 떨어져서 학습 의욕을 잃을 수 있다. 이런 상황을 피하려면 매우 작은 단위로 코드를 작성하고 매번 컴파일과 실행을 반복하는 습관이 필요하다. 예를 들어 클래스 하나에 메서드 하나만 넣고 동작을 확인한 다음, 점진적으로 기능을 추가하는 방식이 효과적이다. 한 번에 많은 코드를 작성하고 오류 수정에 시간을 쏟는 것은 비효율적이다.
결론적으로 자바 프로그래밍 학습의 첫 단추는 통합개발환경 대신 명령줄에서 시작하는 것이 현명하다. javac와 java라는 두 가지 명령어만으로 컴파일의 의미, 클래스 구조, 패키지와 클래스패스의 관계, 예외 발생 시 대처법까지 차례로 익힐 수 있다. 물론 통합개발환경이 가진 편의성을 부정할 필요는 없다. 다만 그 편의성이 언어 이해를 방해하는 순간이 오기 전에, 명령줄을 통한 기본기를 탄탄히 다져두는 것이 중요하다. 처음엔 불편하고 생소하겠지만, 컴파일 오류를 직접 읽고 해결하는 과정에서 얻는 통찰은 단순히 코드가 실행되는 것을 구경하는 것과는 비교할 수 없이 값지다. 개발 환경의 원리를 이해한 다음에야 비로소 아무리 강력한 도구를 사용하더라도 헤매지 않고 제대로 활용할 수 있다.