자바를 시작하기 전에

이 글은 남궁성님의 자바의 정석 3/e을 기반으로 공부한 내용을 정리한 글입니다.

자바(Java Programming Language)

1.1 자바란?

자바는 Sun Microsystems, Inc.에서 개발하여 1996년 1월에 공식적으로 발표한 객체지향 프로그래밍 언어이다.

자바의 가장 중요한 특징은 운영체제(Operating System, 플랫폼)에 독립적이라는 것이다. 자바로 작성된 프로그램은 운영체제의 종류에 관계없이 실행이 가능하기 때문에, 프로그램을 변경하지 않고도 실행이 가능하다.

1.2 자바의 역사

자바의 역사는 1991년 썬의 엔지니어들에 의해서 고안된 오크(Oak)라는 언어에서 시작되었다.

제임스 고슬링과 아서 밴 호프와 같은 썬의 엔지니어들이 가전제품에 탑재될 소프트웨어를 만드는 것이 목표였다. C++을 사용하려 했으나 부족함을 깨달았고, 장점을 도입하고 단점을 보완한 새로운 언어 Oak를 개발했다. 이 후 인터넷이 등장하자 운영체제에 독립적인 Oak를 인터넷에 적합하도록 개발 방향을 바꾸면서 이름을 Java로 변경하였다.

초창기에는 자바로 작성된 애플릿(Applet)은 정적인 웹페이지에 멀티미디어적 요소를 제공할 수 있는 유일한 방법이었기에 많은 인기를 얻었다. 그러나 보안상의 이유로 최신 웹브라우저에서 Applet을 더 이상 지원하지 않게 되었고 대신 서버 쪽 프로그래밍을 위한 서블릿(Servlet)과 JSP(Java Single Pages)가 더 많이 사용되고 있다. 그리고 구글의 스마트폰 운영체제인 안드로이드에서도 Java를 사용한다.

1.3 자바언어의 특징

  1. 운영체제에 독립적이다.
    일종의 에뮬레이터인 자바가상머신(JVM)을 이용하여 운영체제에 독립적이다. 자바 응용프로그램은 운영체제나 하드웨어가 아닌 JVM하고만 통신하고 JVM이 전달받은 명령을 운영체제가 이해할 수 있도록 변환하여 전달한다. 자바로 작성된 프로그램은 독립적이지만 JVM은 종속적이어서 운영체제별로 다른 버전의 JVM이 제공된다.

  2. 객체지향언어이다.
    객체지향개념의 특징인 상속, 캡슐화, 다형성이 잘 적용된 순수한 객체지향언어라는 평가를 받고 있다.

  3. 비교적 배우기 쉽다.
    연산자와 구문은 C++에서, 객체지향관련 구문은 스몰톡(small talk)이라는 객체지향언어에서 가져왔다. 장점은 가져오고 복잡하고 불필요한 부분은 제거하여 단순화함으로서 쉽게 배울 수 있으며, 간결하고 이해하기 쉬운 코드를 작성할 수 있도록 하였다.

  4. 자동 메모리 관리(Garbage Collection)
    자바로 작성된 프로그램이 실행되면, 가비지컬렉터(garbage collector)가 자동적으로 메모리를 관리해주기 때문에 따로 관리 하지 않아도 된다. 자동으로 메모리를 관리한다는 것이 다소 비효율적인 면도 있지만, 프로그래밍에 집중하도록 도와주는 장점이 있다.

  5. 네트워크와 분산처리를 지원한다.
    인터넷과 대규모 분산환경을 염두에 두고 개발되어서, 네트워크 프로그래밍 라이브러리(Java API)를 통해 비교적 짧은 시간에 네트워크 관련 프로그램을 쉽게 개발할 수 있도록 지원한다.

  6. 멀티쓰레드를 지원한다.
    일반적으로 멀티쓰레드(multi-thread)의 지원은 사용되는 운영체제에 따라 구현방법도 상이하며, 처리 방식도 다르다. 그러나 자바에서 개발되는 멀티쓰레드 프로그램은 시스템과는 관계없이 구현가능하며, 관련된 라이브러리(Java API)가 제공되므로 구현이 쉽다. 그리고 여러 쓰레드에 대한 스케쥴링(scheduling)을 자바 인터프리터가 담당하게 된다.

  7. 동적 로딩(Dynamic Loading)을 지원한다.
    보통 자바로 작성된 애플리케이션은 여러 개의 클래스로 구성되어 있다. 자바는 동적 로딩을 지원하기 때문에 실행 시에 모든 클래스가 로딩되지 않고 필요한 시점에 클래스를 로딩하여 사용할 수 있다. 또한 일부 클래스가 변경되어도 전체 컴파일을 다시 하지 않아도 되며, 변경사항이 발생해도 비교적 적은 작업만으로 처리할 수 있는 유연한 애플리케이션을 작성 할 수 있다.

1.4 JVM(Java Virtual Machine)

JVM은 ‘Java Virtual Machine’을 줄인 것으로 자바 가상 머신이라고 불린다.

‘가상 기계(Virtual Machine)’는 소프트웨어로 구현된 하드웨어를 뜻하는 넓은 의미의 용어인데, 예를 들어 TV와 비디오를 소프트웨어한 윈도우 미디어 플레이어 같은 것들이다. 마찬가지로 ‘가상 컴퓨터(Virtual Computer)’는 실제 컴퓨터(하드웨어)가 아닌 소프트웨어로 구현된 컴퓨터로 컴퓨터 속의 컴퓨터라고 생각하면 된다.

자바로 작성된 애플리케이션은 모두 JVM에서만 실행되기 때문에, 자바 애플리케이션이 실행되기 위해서는 반드시 JVM이 필요하다.

일반 애플리케이션의 코드는 OS만 거치고 하드웨어로 전달되는데 비해 Java애플리케이션은 JVM을 한번 더 거치고, 하드웨어에 맞게 완전히 컴파일된 상태가 아니고 실행 시에 해석(interpret)되기 때문에 속도가 느리다는 단점을 가지고 있다. 하지만 요즘엔 바이트코드(Byte Code : 컴파일된 자바코드)를 하드웨어의 기계어로 바로 변환해주는 JIT컴파일러와 Hotspot과 같은 향상된 최적화 기술이 적용되어서 속도의 격차를 많이 줄였다.

자바개발환경 구축하기

2.1 자바 개발도구(JDK) 설치하기

자바로 프로그래밍을 하기 위해서는 먼저 JDK(Java Development Kit)를 설치해야 한다. JDK를 설치하면, JVM과 Java API외에 자바를 개발하는데 필요한 프로그램들이 설치된다.

JDK의 설치가 끝났으면 설치된 디렉토리의 bin디렉토리(ex: c:\jdk1.8\bin)를 path에 추가해주어야 한다. 이 디렉토리에는 자바로 프로그램을 개발하는데 필요한 실행파일들이 들어있다. path는 OS가 파일의 위치(디렉토리)를 파악하는데 사용하는 경로로, path에 디렉토리를 등록하면, 해당 디렉토리에 포함된 파일을 파일 경로없이 파일 이름만으로도 사용할 수 있게 된다.

JDK의 bin 디렉토리에 있는 주요 실행파일들은 다음과 같다.

  • javac.exe 자바 컴파일러. 자바소스코드를 바이트코드로 컴파일한다.
  • java.exe 자바 인터프리터. 컴파일러가 생성한 바이트코드를 해석하고 실행한다.
  • javap.exe 역 어셈블러. 컴파일된 클래스파일을 원래의 소스로 변환한다.
  • javadoc.exe 자동 문서 생성기. 소스파일에 있는 주석(/* */)을 이용하여 Java API문서와 같은 형식의 문서를 자동으로 생성한다.
  • jar.exe 압축프로그램. 클래스파일과 프로그램의 실행에 관련된 파일을 하나의 jar파일(.jar)로 압축하거나 압축해제한다.

| 참고 | JDK와 JRE
∙ JDK - 자바개발도구(Java Development Kit)
∙ JRE - 자바실행환경(Java Runtime Environment). 자바로 작성된 응용프로그램이 실행되기 위한 최소환경.
∙ JDK = JRE + 개발에 필요한 실행파일(javac.exe 등등)
∙ JRE = JVM + 클래스 라이브러리(Java API)

2.2 Java API문서 설치하기

자바에서 제공하는 클래스 라이브러리(Java API)를 잘 사용하기 위해서는 Java API문서가 필수적이다. 이 문서에는 클래스 라이브러리의 모든 클래스에 대한 설명이 자세하게 나와 있다.

자바로 프로그램작성하기

3.1 Hello.java

JDK이외에 메모장(notepad)이나 에딧플러스(editplus)와 같은 편집기가 있어야 프로그램을 개발할 수 있다.

class Hello {
  public static void main(String[] args) {
    System.out.println("Hello, world.");
  }
}

위의 예제는 화면에 ‘Hello, world.’를 출력하는 아주 간단한 프로그램이다. 예제와 같이 작성한 후 이름을 ‘Hello.java’로 저장한다. 이 예제를 실행하려면, 자바컴파일러(javac.exe)를 사용해서 소스파일(Hello.java)로부터 클래스파일(Hello.class)을 생성해야한다. 그 다음 자바 인터프리터(java.exe)로 실행한다.

자바에서 모든 코드는 반드시 클래스 안에 존재해야 하며, 서로 관련된 코드들을 그룹으로 나누어 별도의 클래스를 구성하게 된다. 그리고 이 클래스들이 모여 하나의 Java 애플리케이션을 이룬다.

클래스를 작성하는 방법은 키워드 ‘class’ 다음에 클래스의 이름을 적고, 클래스의 시작과 끝을 의미하는 괄호 { } 안에 원하는 코드를 넣으면 된다.

class 클래스이름 {
  /*
    주석을 제외한 모든 코드는 클래스의 블럭 { } 내에 작성해야한다.
  */
}

| 참고 | package문과 import문은 예외적으로 클래스의 밖에 작성한다.

public static void main(String[ ] args)는 main 메서드의 선언부인데, 프로그램을 실행할 때 ‘java.exe’에 의해 호출될 수 있도록 미리 약속된 부분이다. 따라서 항상 똑같이 적어주어야 한다.

class 클래스이름 {
  public static void main(String[] args) {
    //실행될 문장
  }
}

| 참고 | ‘[ ]’은 배열을 의미하는 기호로 배열의 타입(type) 또는 배열의 이름 옆에 붙일 수 있다. ‘String[ ] args’는 String 타입의 배열 args를 선언한 것이며, ‘String args[ ]’로 쓸 수도 있다.

main 메서드의 선언부 다음에 나오는 괄호 { }는 메서드의 시작과 끝을 의미하며, 이 괄호 사이에 작업할 내용을 작성해 넣으면 된다. Java 애플리케이션은 main 메서드의 호출로 시작해서 main 메서드의 첫 문장부터 마지막 문장까지 수행을 마치면 종료된다.

모든 클래스가 main 메서드를 가지고 있어야 하는 것은 아니지만, 하나의 Java 애플리케이션에는 main 메서드를 포함한 클래스가 반드시 하나는 있어야 한다. main 메서드는 Java 애플리케이션의 시작점이므로 main 메서드 없이는 실행될 수 없기 때문이다. 작성된 Java 애플리케이션을 실행할 때는 ‘java.exe’ 다음에 main 메서드를 포함한 클래스의 이름을 적어줘야 한다.

하나의 소스파일에 하나의 클래스만을 정의하는 것이 보통이지만, 하나의 소스파일에 둘 이상의 클래스를 정의하는 것도 가능하다. 단, 소스파일의 이름은 public class의 이름과 일치해야 한다. 만일 소스파일 내에 public class가 없다면, 소스파일의 이름은 소스파일 내의 클래스 이름 중 어떤 것으로 해도 상관없다.

소스파일(*.java)과 달리 클래스파일(*.class)은 클래스마다 하나씩 만들어진다.

3.2 자주 발생하는 에러와 해결방법

  1. cannot find symbol 또는 cannot resolve symbol
    지정된 변수나 메서드를 찾을 수 없다는 뜻으로 선언되지 않은 변수나 메서드를 사용하거나, 변수 또는 메서드의 이름을 잘못 사용한 경우에 발생한다.

  2. ’;’ expected
    세미콜론 ‘;’이 필요한 곳에 없다는 뜻이다. 자바의 모든 문장의 끝에는 세미콜론을 붙여주어야 하는데 가끔 이를 잊고 실수하기 쉽다.

  3. Exception in thread “main” java.lang.NoSuchMethodError: main
    main 메서드를 찾을 수 없다는 뜻인데 실제 클래스 내에 main 메서드가 존재하지 않거나 메서드의 선언부 ‘public static void main(String[] args)’에 오타가 존재하는 경우에 발생한다. main 메서드가 클래스에 정의되어 있는지 확인하고, 정의되어 있다면 main 메서드의 선언부에 오타가 없는지 확인한다. 자바는 대소문자를 구별하므로 대소문자의 일치여부까지 확인해야한다.
    | 참고 | args는 매개변수의 이름이므로 args 대신 argv나 arg와 같이 다른 이름을 사용할 수 있다.
  4. Exception in thread “main” java.lang.NoClassDefFoundError: Hello
    Hello라는 클래스를 찾을 수 없다는 뜻이다. 클래스 ‘Hello’의 철자, 특히 대소문자를 확인해보고 이상이 없으면 클래스파일(*.class)이 생성되었는지 확인한다. 클래스파일이 존재하는데도 동일한 메시지가 반복된다면 클래스패스(classpath)의 설정이 바르게 되어있는지 확인해본다.

  5. illegal start of expression
    문장(또는 수식, expression)의 앞부분이 문법에 맞지 않는다는 의미인데, 문장에 문법적 오류가 있다는 뜻이다. 괄호 ‘( )’나 ‘{ }’을 열고서 닫지 않거나, 수식이나 if문, for문 등에 문법적 오류가 있을 때 또는 public이나 static과 같은 키워드를 잘못 사용한 경우에도 발생한다.

  6. class, interface, or enum expected
    키워드 class나 interface 또는 enum이 없다는 뜻이지만, 보통 괄호 ‘{ }’의 짝이 맞지 않는 경우에 발생한다.

3.3 자바프로그램의 실행과정

콘솔에서 ‘Hello’라는 Java 애플리케이션을 실행시켰을 때 내부적인 진행 순서는 다음과 같다.

1. 프로그램의 실행에 필요한 클래스(*.class파일)를 로드한다.

2. 클래스파일을 검사한다.(파일형식, 악성코드 체크)

3. 지정된 클래스(Hello)에서 main(String[] args)를 호출한다.

main 메서드의 첫 줄부터 코드가 실행되기 시작하여 마지막 코드까지 모두 실행되면 프로그램이 종료되고, 프로그램에서 사용했던 자원들은 모두 반환된다.

3.4 주석(comment)

작성하는 프로그램의 크기가 커질수록 프로그램을 이해하고 변경하는 일이 어려워진다. 자신이 작성한 프로그램도 의문이 드는데, 남이 작성한 코드를 이해하는 것은 더욱 어렵다.

이러한 어려움을 덜기 위해 사용하는 것이 바로 주석이다. 주석을 이용해서 프로그램 코드에 대한 설명을 덧붙여 놓으면 이해하는데 도움이 많이 된다. 그 외에도 주석은 프로그램의 작성자, 작성일시, 버전과 그에 따른 변경이력 등의 정보를 제공할 목적으로 사용된다. 주석을 작성하는 방법은 두 가지가 있다. ‘/*‘와 ‘*/’ 사이에 주석을 넣는 방법과 앞에 ‘//’를 붙이는 방법이 있다.

범위 주석    '/*'와 '\*/' 사이의 내용은 주석으로 간주된다.

한 줄 주석    '//'부터 라인 끝까지의 내용은 주석으로 간주된다.

한 가지 주의해야할 점은 문자열을 의미하는 큰따옴표 안에 주석이 있을 때는 주석이 아닌 문자열로 인식된다.