Java

최근 수정 시각:

파일:나무위키+넘겨주기.png   관련 문서: 객체 지향 프로그래밍, 이클립스(통합 개발 환경)

파일:나무위키+유도.png   동음이의어에 대한 내용은 자바 문서를 참조하십시오.

파일:나무위키프로젝트.png
이 문서는 나무위키 프로그래밍 프로젝트에서 다루는 문서입니다.
해당 프로젝트 문서를 방문하여 도움이 필요한 문서에 기여하여 주세요!

package wiki.namu.test;

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

TIOBE에서 선정한 프로그래밍 언어 월간 검색어 점유율 순위

[ 펼치기 · 접기 ]

1. Java

2. C

3. Python

4. C++

5. VB .NET

17.436%
4.75% 증가

15.447%
8.06% 증가

7.653%
4.67% 1위 증가

6.361%
+2.82% 증가

5.308%
+3.33% 증가

6. C#

7. PHP

8. JavaScript

9. SQL

10. Objective-C

3.795%
+0.28% 증가

2.832%
-0.26% 감소

2.831%
+0.22% 증가

2.334%
+2.33% 증가

1.453%
-0.44% 감소

2018년 9월 기준이며, 전년 동월 대비 변화 수치이다. 자세한 내용은 TIOBE에서 확인할 수 있으며, 기준은 다음과 같다.

파일:java 로고.png

1. 개요2. 어원3. 분류4. 간략한 역사
4.1. JDK 1.0a4.2. JDK 1.0a24.3. JDK 1.04.4. JDK 1.14.5. J2SE 1.24.6. J2SE 1.34.7. J2SE 1.44.8. J2SE 54.9. Java SE 64.10. Java SE 74.11. Java SE 84.12. Java SE 94.13. Java SE 104.14. Java SE 11
5. C, C++와의 비교6. 특징
6.1. 장점
6.1.1. 수많은 개발자와 레퍼런스6.1.2. 비교적 높은 생산성6.1.3. 기기 호환성6.1.4. 안정성6.1.5. 소스 코드 가독성
6.2. 단점
6.2.1. 속도 문제
6.2.1.1. JVM 로딩 속도 문제6.2.1.2. 가상 머신 바이트코드 실행 속도 문제6.2.1.3. 가비지 컬렉션에 의한 실행 지연 문제
6.2.2. 불편한 예외 처리6.2.3. 소스 코드 길이6.2.4. 언어적 불편함
6.2.4.1. 명사형 생각을 강제6.2.4.2. 클로저 미지원
7. 개발환경, JVM 언어
7.1. 개발환경7.2. JVM 언어
7.2.1. 유명한 JVM 언어 목록
7.3. 유사품에 주의합시다
8. 구글 vs. 오라클: Java 저작권 분쟁9. 불투명한 미래?10. 여담11. 관련 문서


JDK 다운로드 페이지

1. 개요[편집]

썬 마이크로시스템즈에서 1995년에 개발한 객체 지향 프로그래밍 언어. 창시자는 제임스 고슬링이다. 2010년에 썬이 오라클에 인수되어서 현재 Java의 저작권자는 오라클이다. 단, 2017년 9월부로 Java EE에 한해 이클립스 재단이 소유권을 가지게 되었다.

2. 어원[편집]

처음엔 고슬링 사무실 앞에 있는 참나무에서 따와 OAK로 지었다가 그대로 등록하기엔 상표권에 문제가 생겨서 컨설턴트가 극단적인 방법을 도입, 오후에 개발진들을 회의실에 가둬서(...) 마라톤 회의를 시켰다. "기분이 어떤가요"(Excited!), "무엇이 당신 기분을 좋게 만드나요?"(Java!) 같은 연상적인 작용을 거쳐 여러가지 이름을 정하고, 그 중에서 선택했다. Java는 랭킹 중 네 번째. 리스트의 첫 번째 이름은 Silk였고 고슬링이 가장 좋아했던 이름은 Lyrics, 세 번째에 올라왔던 이름이라고.

개발진이 자바산 커피를 좋아해서 그랬다는 설도 있다. 아이콘도 커피잔 모양. 또는 개발자의 이름인 James Gosling, Arthur Van Hoff, Andy Bechtolsheim의 머릿글자를 따온 것이라는 설도 있고, 그냥 사전을 펼쳤는데 눈에 들어온 이름이었다는 설도 있다. 그런데 막 지은 것 치고는 나중에 Sun사의 주식시장 등록 이름이 Java가 되어버릴 정도로 이제는 Sun의 상징이자, 세계적으로도 널리 알려진 단어가 되었다. 출처

3. 분류[편집]

Java는 크게 다음과 같은 4가지 에디션으로 나뉜다.

  • Java SE(Java Standard Edition / J2SE)
    대부분의 사람들이 가장 많이 접하는 표준 에디션. Java의 핵심 API와 기능들을 제공한다. JDK 항목도 참고.

  • Jakarta EE, 구 Java EE(Java Enterprise Edition / J2EE)
    기업에서 운영하는 서버 페이지에 특화된 에디션이다. JSP와 서블릿을 비롯한 웹 애플리케이션 서버에 관련된 기술들이 포함되어 있다.

  • Java ME(Java Micro Edition / J2ME)
    PDA나 셋톱박스, 센서 등의 임베디드 시스템 환경에 특화된 에디션이다.

  • JavaFX
    데스크톱 애플리케이션 개발 및 배포를 위한 에디션으로, 크로스플랫폼 이식과 GUI 라이브러리를 제공한다.

4. 간략한 역사[편집]

버전 정보와 날짜만 확인한다면, Java/버전 정보 문서 참조.

4.1. JDK 1.0a[편집]

1994년 발표.

4.2. JDK 1.0a2[편집]

1995년 5월 23일 발표. 언어 자체가 정식으로 발표된 날이기도 하다.

4.3. JDK 1.0[편집]

1996년 1월 23일 발표. 발표 이전에 불렸던 이름은 Oak였으며, 안정화 작업을 거친 1.0.2 버전에서 Java로 이름이 바뀌었다.

4.4. JDK 1.1[편집]

1997년 2월 19일 발표. 이너 클래스, JavaBeans, RMI, 리플렉션, 유니코드 지원, 국제화(Internationalization) 등이 추가되었다.

4.5. J2SE 1.2[편집]

1998년 12월 8일 발표. 일반 지원은 2003년 11월에 종료되었다. 새로운 GUI, JIT, CORBA 등의 굵직한 기능이 추가되면서 2 부터 약칭을 J2SE(Java 2 Standard Edition) 로 표기하기 시작했으며, 이 표기는 5 까지 사용된다. strictfp, Swing GUI, JIT, Java Applet을 구동하는 웹 브라우저 플러그인, CORBA, Collections 등이 추가되었다. 1999년에 업데이트를 통해 HotSpot JVM이 첫 선을 보인다.

4.6. J2SE 1.3[편집]

2000년 3월 8일 발표. 일반 지원은 2006년 11월에 종료되었다. HotSpot JVM, JNDI, JPDA, JavaSound 등이 추가되었다. RMI가 CORBA를 지원하도록 변경되었다.

4.7. J2SE 1.4[편집]

2002년 2월 6일 발표. 일반 지원[1]은 2008년 10월, 연장 지원[2]은 2013년 2월에 종료되었다. assert, 정규표현식, IPv6, Non-Blocking IO, XML API, JCE, JSSE, JAAS, Java Web Start 등이 추가되었다.

4.8. J2SE 5[편집]

2004년 9월 30일 발표. 일반 지원은 2009년 9월, 연장 지원은 2015년 5월에 종료되었다. J2SE 5.0까지 Windows 9x와 Windows NT 4.0이 지원되었다. 이 때부터 버젼 중 앞의 1을 빼버리고 표기하기 시작했다. 그러나 내부적으로는 여전히 1.5, 1.6, 1.7 등으로 데이터가 들어있다. Generics, Annotation, Auto Boxing/Unboxing, Enumeration, 가변 길이 파라미터, Static Import, 새로운 Concurrency API 등이 추가되었다. Java는 표준 입력(stdin) 지원이 시원찮았는데, J2SE 5에 들어서 java.util.Scanner가 추가되면서 이전보다 편하게 표준 입력을 사용할 수 있게 되었다.

4.9. Java SE 6[편집]

2006년 12월 11일 발표. 일반 지원은 2013년 2월에 종료되었으며, 연장 지원은 2018년 12월에 종료될 예정이다. 이 때부터 표기가 J2SE에서 Java SE로 바뀌었다. Scripting Language Support, JDBC 4.0, Java Compiler API, Pluggable Annotation 등이 추가되었다. 스크립팅 언어 지원과 함께 Rhino JavaScript 엔진이 기본으로 탑재되었다.

4.10. Java SE 7[편집]

2011년 7월 7일 발표. 일반 지원은 2015년 4월에 종료되었으며, 연장 지원은 2022년 7월에 종료될 예정이다. Dynamic Language 지원, switch문에서 String 사용, try문에서 자동 자원 관리, Diamond Operator <>, 이진수 리터럴, 숫자 리터럴에 _ 지원, 새로운 Concurrency API, 새로운 File NIO 라이브러리, Elliptic Curve Cryptography, Java2D를 위한 XRender, Upstream, Java Deployment Ruleset 등이 추가되었다.

4.11. Java SE 8[편집]

2014년 3월 18일 발표. 일반 지원은 2019년 1월, 연장 지원은 2025년 3월에 종료될 예정이다. Lambda Expression, Rhino 대신 Nashorn JavaScript 엔진 탑재, Annotation on Java Types, Unsigned Integer 계산, Repeating Annotation, 새로운 날짜와 시간 API(사실상 JodaTime이라고 보면 된다), Static Link JNI Library, Interface Default Method, PermGen 영역 삭제, Stream API 등이 추가되었다. 본래 일반 지원은 2017년 9월 종료 예정이었으나 Java 9 발표의 지연 때문에 2018년 9월로 연장되었다가, 이후 라이선스 이관 문제로 인해 2019년 1월로 다시 연장되었다.

32비트를 지원하는 마지막 Java 버전이다.

4.12. Java SE 9[편집]

2017년 9월 21일 발표. 일반 지원은 2018년 3월에 종료되었다.

Project Jigsaw 기반으로 런타임이 모듈화된 것이 가장 큰 특징. 이에 따라 대부분의 콘솔 프로그램 개발에는 더 이상 AWT나 Swing 같은 불필요한 라이브러리를 끌어쓸 필요도 없이, 최상위 모듈인 Base만 사용해도 된다. 더불어 특정 프로그램에 최적화된 최소 런타임을 제작할 수 있게 되면서 패키징 역시 간편해졌다.

여기에 Java를 인터프리터 언어 셸처럼 사용할 수 있는 JShell이 추가되었으며, Java 바이트코드를 기계어로 미리 번역하는 선행 컴파일(Ahead-Of-Time Compilation) 역시 실험 기능으로 추가되었다.[3] 또한 Deprecated 표시에는 해당 버전과 제거 예정 여부를 표시할 수 있게 되었다. 그 외에 구조적 불변 컬렉션, 통합 로깅, HTTP/2, private 인터페이스 메소드, HTML5 Javadoc 등도 지원되며, 프로퍼티 파일에 UTF-8이 지원됨에 따라 더 이상 인코딩 문제로 삽질할 필요가 없어졌다. 대신 Java Applet 기능은 지원이 종료된다.

새로 적용된 버저닝 정책에 따라 이 버전부터는 더 이상 1.x 버전으로 내놓지 않고, 대신 9.0으로 급속한 판올림이 일어났다. 또한 제거 예정인 Deprecated API는 다음 버전인 Java SE 10부터 완전 삭제 예정이므로 해당 API를 쓰는 프로그램은 더 이상 이후의 버전에서 컴파일조차 불가능하게 된다. 그리고 Java SE 9부터는 6개월마다 새로운 버전이 업데이트된다.

본래는 2016년 발표 예정이었으나 2번이나 연기되어 2017년 7월 27일 발표 예정, 그나마도 한번 더 연기되어 9월 21일에 발표되었다. 가장 큰 원인은 역시 Project Jigsaw의 개발 난이도. 많이 사용되고 있는 빌드 관리 툴 Maven과 Gradle도 아직 Java SE 9를 완벽하게 지원하지 못하고 있다. 런타임의 모듈화는 하위 호환성을 어느 정도 포기하고 성능을 추구한 것이기에 아직 현장에서는 Java 9로 넘어가는 것을 꺼리는 분위기다.

32비트 버전이 없어지고 64비트 버전만 출시되었다.

4.13. Java SE 10[편집]

2018년 3월 20일 발표. 일반 지원은 2018년 9월에 종료되었다. var 키워드를 이용한 지역 변수 타입 추론, 병렬 처리 가비지 컬렉션, 개별 쓰레드로 분리된 Stop-The-World, 루트 CA 목록 등이 추가되었다. 또한 JDK의 레포지토리가 하나로 통합되었으며, JVM 힙 영역을 시스템 메모리가 아닌 다른 종류의 메모리에도 할당할 수 있게 되었다. 실험 기능으로 Java 기반의 JIT 컴파일러가 추가되었고, 이전 버전에서 Deprecated 처리된 API는 Java SE 10에서 모두 삭제되었다.

4.14. Java SE 11[편집]

2018년 9월 25일 발표. 일반 지원은 2023년 9월, 연장 지원은 2026년 9월에 종료될 예정이다. 이클립스 재단으로 넘어간 Java EE가 JDK에서 삭제되고, JavaFX도 JDK에서 분리되어 별도의 모듈로 제공된다. # 람다 파라미터에 대한 지역 변수 문법[4], 엡실론 가비지 컬렉터, HTTP 클라이언트 표준화 등의 기능이 추가되었다.

가장 커다란 변화는 바로 라이선스 부분. Java SE 11부터 Oracle JDK의 독점 기능이 오픈 소스 버전인 OpenJDK에 이식된다. 이는 다시 말해 Oracle JDK와 OpenJDK가 완전히 동일해진다는 뜻이다. Oracle JDK는 Java SE 11부터 LTS(장기 지원) 버전으로 3년마다 출시되는데, 출시 후 5년 동안 오라클의 기술 지원이 제공되고 최대 3년까지 지원 기간을 연장할 수 있다. Oracle JDK는 이제 3년에 한 번 출시되니 Java의 실질적인 버전 업을 담당하는 것은 OpenJDK가 된 셈이다. OpenJDK는 기업들을 위한 기술 지원은 없고, 새로운 버전이 나오면 이전 버전에 대한 마이너 업데이트와 보안 업데이트는 중단된다.

그리고 Java 11과 함께 발표된 또 다른 소식은 바로 Oracle JDK가 구독형 유료 모델로 전환된다는 점이다. # 2019년 1월부터 오라클이 제공하는 모든 JDK는 유료화되며, 구독권을 구입하지 않으면 JDK에 접근 자체가 금지된다. 기존의 일반/연장 지원 서비스는 구독권에 포함되므로 별도의 서비스로는 제공되지 않는다. 개인 사용자는 2021년 1월부터 비용을 지불해야 한다. 이 때문에 많은 기업들이 Oracle JDK에서 발을 빼고 있는데, Azul Systems에서 OpenJDK를 이용하여 개발한 Zulu JDK가 대안으로 떠오르고 있다. Zulu JDK는 OpenJDK의 최신 빌드 및 Java SE 표준과 완벽하게 호환되며, 안정성을 검증하는 오라클의 TCK(Technology Certification Kit) 인증을 받은 구현체이다. 개인과 기업 모두 무료로 사용할 수 있고, 기술 지원에 한해서만 유료 서비스가 제공된다.

5. C, C++와의 비교[편집]

기존의 C에 객체지향 기능을 억지로 끼워 맞추다 보니 영 모양새가 좋지 않은 C++과는 다르게 아예 처음부터 객체지향 언어로 개발되었다. 다만 많은 사람들이 착각하는 부분인데, Java는 엄밀히 말하면 완벽한 객체지향 언어가 아니다. 원시(Primitive) 타입은 객체로 취급하지 않기 때문. 모든 것을 객체로 취급하는 언어를 순수 객체지향(Pure object-oriented)이라 하며 이를 지원하는 언어는 Smalltalk가 대표적이다. 최근에 만들어진 언어 중에서는 Ruby가 이에 해당된다.

C, C++, Java의 차이점을 말하자면, C는 포인터 등을 활용한 로우 레벨 시스템 프로그래밍에 강점을 가지며, C++은 C의 그런 강점을 거의 그대로 가져오면서 거기에 객체 지향과 같은 하이 레벨 기능들을 포함하였다. 문제는, 저수준 메모리 액세스를 허용하면서 하이레벨 기능들을 죄다 포함하려다 보니 디자인적인 측면에서도 좋은 소리를 못 들었고, 실제로 상당히 복잡한 언어가 되어 버렸다. 그래서 C++을 제대로 다룰 줄 아는 프로그래머는 거의 없다는 이야기가 널리 퍼지게 된 것. Java는 여기서 포인터라는 강력한 무기를 포기한 대신에 OOP와 같은 하이 레벨 부분에 보다 집중하여 언어적 완성도를 높였다고 볼 수 있다. 실제로, 리누스 토르발스가 C++을 비판하면서 프로젝트에 C++이 아닌 C를 사용하는 이유 중 하나는 C가 좋아서라기보다 C++ 프로그래머들을 의도적으로 배제하기 위해서라고 한 적이 있다. C++의 경우, 고도로 숙련된 프로그래머가 주의 깊게 디자인하고 프로그래밍하지 않을 경우 망측한 코드를 만들어낼 가능성이 매우 높아 제대로 디자인된 언어가 아니라고 주장하였다. 프로그래밍을 해 봤다면 알겠지만, C++ 다루는 프로그래머들은 많지만 C언어에 비해 쉽다는 생각은 들지 않을 것이다.

일단, 대부분의 프로그래밍 언어가 그렇듯이, C/C++와 비슷한 문법 구조를 가지고 있다. 그러면서도 C/C++보다 생산성이 훨씬 더 좋다. 다만, 상속 같은 객체 지향 개념을 이해하지 못하고 헤맬 경우엔 생산성과는 별개로 배우는 데 상당히 힘이 들 수 있다.

6. 특징[편집]

Java의 가장 큰 특징은 플랫폼에 독립적인 언어라는 점이다. 소스 코드를 기계어로 직접 컴파일하여 링크하는 C/C++의 컴파일러와 달리 자바 컴파일러는 바이트코드인 클래스 파일(.class)을 생성하고, 이 파일의 바이트코드를 읽은 뒤 기계어로 바꾸어 실행하는 것은 Java Virtual Machine(JVM)이다.

예를 들어 C 계열 언어들은 윈도우에서 빌드한 프로그램을 그대로 리눅스macOS에서 실행하려 하면 일반적으로 오류가 나지만 Java로 작성 된 프로그램은 플랫폼에 맞는 JVM만 설치되어 있다면 문제 없이 동작한다. 이는 Java 코드 자체가 플랫폼이 아닌 가상머신에 종속적이라는 점, 그리고 프로그램 실행의 주체가 운영체제가 아닌 JVM이기 때문이며 이러한 점을 통틀어 플랫폼 종속성이 낮은 언어라고 표현한다.

JVM 기반의 프로젝트에서는 하나의 언어만을 고집하지 않는다. 스크립트 언어가 유리(간결하고 짧은 소스코드)한 부분은 Groovy로 작업하고, 함수형 언어가 유리(최근 유행하는 빅데이터 등)한 부분은 Scala로 작업하며, 견고한 인터페이스와 대규모 통합이 필요한 곳은 Java로 작업한 뒤 이들을 서로 합쳐서 운영하는 게 가능하다. (Java에서 만든 객체를 Scala에서 그대로 사용할 수 있다.)

실제 현업에서는 Java와 통합해서 몇몇 인기 언어가 자주 사용되므로 장단점을 잘 알아두는게 좋다. '내가 사용하는 언어를 까는 건 참을 수 없어!'라는 태도보다는 환경이나 주어진 작업의 특성에 따라 적합한 언어를 선택할 수 있는 지혜가 필요하다.

6.1. 장점[편집]

6.1.1. 수많은 개발자와 레퍼런스[편집]

나온지도 오래되었고, 다른 최신 언어에 비해서 여러가지로 욕을 먹는 Java가 그래도 항상 상위권을 유지하는 이유는 바로 수많은 개발자와 레퍼런스를 보유하고 있다는 점이다. 타 언어를 전문적으로 사용하는 개발자들도 Java 정도는 할 줄 안다고 할 정도로 배우기 쉽고 대중적이다. 대중적인 언어라서 참고 자료나 오픈 소스가 많고, 그러한 자료들을 바탕으로 수많은 대형 프로젝트들이 진행되어왔기 때문에 많은 부분에서 안정성이 입증되었다. 즉, 안정적인 인력풀을 유지하면서, 알려진 위협을 제거하고 운영 노하우를 극대화시킬 수 있는 검증된 언어라는 것.

6.1.2. 비교적 높은 생산성[편집]

오늘날 프로그램의 덩치와 다루는 것들이 크고 복잡해지면서 생산성과 퍼포먼스 문제가 생기게 되었는데, C/C++ 같은 언어는 생산성이 너무 떨어지고 관리도 힘들어서 프로그램이 커지면 커질수록 작업이 힘들어지게 된다. 그리고 아무리 컴퓨터 하드웨어가 발달한다고 해도 성능이 더 좋아지면 점점 더 복잡한 것을 다루고, 그것이 새로운 표준이 되면서 하드웨어의 속도 향상이 무색해지기 때문이다. 거기다 리소스를 많이 낭비하는 하이 레벨 언어라면 더 심각하다. 그런데, 그 와중에 나타난 게 바로 Java다. C/C++와 비슷한 문법으로 진입 장벽도 낮고, 객체 지향을 적극적으로 사용하며, 로우 레벨 작업들을 자동으로 처리해 주는 하이 레벨 언어이면서, 퍼포먼스도 다른 하이 레벨 언어들에 비해 빠른 편이다. 거기에 호환성까지! 등장하자마자 순식간에 대세가 된 것도 무리는 아니다. 다만 막강한 스펙을 가진 최신 언어에 비해서라면 Java의 생산성은 상대적으로 낮은 편이다.

6.1.3. 기기 호환성[편집]

장점으로는, 해당 운영체제Java Virtual Machine을 설치하면 Java로 만든 프로그램은 어떤 컴퓨터에서도 완벽히 똑같이 동작한다. 가상머신이 각각의 운영체제에 맞춰서 결과적으로 완벽히 똑같이 돌아갈 수 있도록 제작되는 덕. 가상머신 없는 운영체제라면 아예 Java 프로그램을 사용하지 못하겠지만, 썬 마이크로시스템즈는 주요 OS용의 가상 머신을 발표하고 있고, IBM, 휴렛팩커드 등의 회사는 직접 자사 운영체제용 JDK/JVM을 제작하여 발표하며, 이들과 상관없이 독립적으로 특화된 성능향상 기능을 가진 JVM을 만들어서 발표하는 회사도 존재한다. 그래서 이 부분은 보통 단점으로 꼽히지 않는다. 오히려 여러 운영체제에 발 벌리는 업체라면 윈도우용, 맥용 등을 따로 제작할 필요 따위가 없이 "그냥 하나 만들면 끝!"이라고 Java 초창기에 홍보되었다.

그러나 다른 크로스 플랫폼 언어들과 마찬가지로 각 플랫폼마다 미묘하게 기능이나 작동에 차이가 있는 부분이 결국은 존재하기 때문에, 이러한 부분을 고려하지 않고 작성된 프로그램을 그대로 다른 데에서 돌릴 때에 문제가 발생할 가능성이 존재한다. JVM의 장점은 그나마 이런 부분들이 다른 언어에 비해서 매우 적은 편이라는 점이다. 이런 경우, 대부분 크로스 플랫폼으로 작성된 코드가 그러하듯 타겟 플랫폼을 인지하여 특정 플랫폼에서는 다르게 동작하게 하는 식으로 코딩을 하게 된다. 주로 java.nio 패키지에 속한 API 에서 이러한 경우를 발견할 수 있으며, OS X 에서만 일부 특이하게 동작하는 MIDI 관련 API 또한 이러한 경우에 속한다. Java의 모토는 Write once, run everywhere(한 번 짜서, 어디서나 실행하라)인데 프로그래머들은 이를 비꼬아 Write once, test everywhere(한 번 짜서, 어디서나 테스트하라)라고 말하곤 한다.

C나 C++에서도 크로스 플랫폼 형태로 소스코드를 작성하는 것이 가능하기는 했지만, 개발자가 타겟 플랫폼과 해당 플랫폼용 바이너리 코드를 생성하는 컴파일러에 대해서 잘 이해하고 나서 #define, #if 등 전처리기를 써서 각 타겟 플랫폼에 맞게 동작하도록 코드를 직접 작성해줘야 했다. 이와 달리, Java는 단일 소스코드를 컴파일하여 생성된 바이트코드 클래스 파일을 JVM이 존재하는 환경이라면 어디서나 (대부분은) 추가 컴파일이나 수정작업 없이 그대로 똑같이 실행할 수 있다는 점이 차이점이다. 기업 입장에서 컴파일된 바이너리가 크로스 플랫폼을 보장해주는 Java는 매력적인 언어였다. GNU 측에서는 초기에 GCC를 이용한 Java 컴파일러 구현을 시도했으며, 아파치 소프트웨어 재단에서 만든 수많은 오픈 소스 프로그램과 라이브러리가 존재한다.

6.1.4. 안정성[편집]

다른 언어에 비해 높은 안정성을 꼽고 있다. 우선 C나 C++에 안정성 문제가 제기되는 포인터 연산자[5] 및 메모리 직접접근 함수들을 지원하지 않는다. 여기에 C++과는 다르게 다중 상속을 허용하지 않는다. 이는 객체지향의 특성 중 하나인 '상속'의 자유도를 확 떨어트리는 것이기에 언뜻 보기에는 객체지향적 관점에 위배되는 것처럼 보일 수 있으나, 반대로 오히려 이게 더 객체지향적이라고 볼 수도 있다. 객체지향의 목적 자체가 재사용을 통한 생산성의 향상과 관리 상의 이점인데, 다중 상속은 잘못 사용할 시 극도로 복잡하게 꼬인 프로그램을 만들 위험성을 갖고 있다. 물론 코드 관리의 측면에서도 다중상속에 의해 발생하는 문제는 좋지 않다. 수준 높은 프로그래머라면 이 문제도 잘 해결할 수 있지만, Java는 아예 미연에 방지하기 위해 다중상속을 언어 스펙에서 제거하는 방법을 택했다.[6]

메모리를 대용량으로 사용하는 프로그램에서 상대적으로 C, C++보다 안정적인 모습을 보일 때도 있는데, 이런 경우에 JVM이 시작될 때 필요한 메모리를 먼저 통으로 잡아버리기 때문이다. 메모리를 많이 쓰는 C, C++로 된 프로그램은 실행되면서 필요에 따라 메모리를 동적으로 할당받게 됨에 따라 오히려 Java보다 버벅거리는 모습을 보여줄 때도 있다.[7] 다만 이는 메모리 할당자 없이 매번 힙 영역 메모리를 할당하는 경우에 해당하는 말이고, 실제 C, C++ 프로젝트에서는 jemalloc 등 커스텀 메모리 할당자를 사용하여 이런 문제를 방지하는 것이 일반적이다.

6.1.5. 소스 코드 가독성[편집]

고급 프로그래밍 언어가 만들어진 첫째 목적은 '좀 더 인간 친화적인' 코드의 작성을 돕는 데 있다. 기계어어셈블리어로 진화하고 그것이 C언어로 진화한 배경에는 '사람이 더 쉽게 읽고 이해할 수 있는 코드'가 있다. Java는 동시기에 발표된 다른 언어에 비해 코드가 명료하고 가독성이 뛰어났다. C++은 어려운 문법으로 인해 코드가 이리저리 꼬이는 경우가 많고, 특히 연산자 오버로딩과 템플릿 일반화 프로그래밍(generic programming) 개념이 코드 난독화에 결정타를 날렸는데 Java는 연산자 오버로딩을 배제하고 오로지 메소드를 통해서만 객체의 조작을 허용함으로써 코드의 일관성을 지켜냈다.[8]

C++ 템플릿 프로그래밍의 주 사용 용도인 일반화 프로그래밍도 제네릭이라는 더 쉬운 개념을 도입해서(Java 5부터 지원) 코드의 가독성을 해치지 않고 일반화 프로그래밍을 성공적으로 도입했다.[9] 키워드에 약어 사용을 자제한 점도 코드 가독성 상승에 기여했다.[10]

6.2. 단점[편집]

6.2.1. 속도 문제[편집]

여기서 잠시 유의할 점은, 느리다는 내용은 대부분 C/C++, Pascal, Fortran같은 네이티브 바이너리 코드를 만드는 언어와 비교했을 때의 이야기이다. Java가 C보다 2~3배 느리다고 하지만 다른 고수준 언어들에 비해서는 그리 떨어지지 않는다. 특히 인터프리터/스크립트 언어는 구조적으로 Java에 비해서도 훨씬 느리다는 것을 기억하자. 예를 들어 요즘 인기있는 Python은 C보다 수십 배(심하면 70배 정도) 느리다. 그나마 빠르다고 하는 JavaScript도 Java에 비해서 2배 정도 느리다.

또한 속도 관련 문제는 하드웨어의 성능이 점점 좋아지고 메모리 가격이 떨어지면서 희석되고 있다. 처음 Java가 나왔을 때인 1995년만 하더라도, 느린 성능 때문에 그다지 많이 쓰이지는 않을 것이라고 예상했지만 현재 Java가 가장 많이 사용되는 곳은 상대적으로 성능이 중요하게 생각되는 서버와 모바일 어플리케이션이다. Java가 네이티브 코드보다 느려도 그렇게 심각하게 느린 것은 아니다.

6.2.1.1. JVM 로딩 속도 문제[편집]

Java의 심각한 단점 중 하나는, 실행하는 과정에서 Java Virtual Machine반드시 완벽하게 로딩되어야 하기 때문에 프로그램의 초기 시작 시간이 완전한 이진 코드로 컴파일된 프로그램을 실행하는 것에 비해 오래 걸리는 것이다. 단적인 예로, 아무것도 안하고 콘솔 화면에 달랑 "Hello, World!" 라고 찍기만 하는 프로그램이 실행되는 데에도 thread가 10개 쯤 뜬다. 특히 그 프로그램에 AWT, Swing, SQL 같이 불필요한 기능을 끌어들이는 것은 매우 심각한 문제이다. 이 문제는 런타임 자체가 아직 모듈화되지 않았다는 점에서 기인한다.

하지만 요즘 같은 고사양 컴퓨터에서는 아주 많은 라이브러리를 끌어오는 것이 아니라면 체감상 차이는 크게 나지 않는다. 또한 Java 9부터는 드디어 런타임 라이브러리를 모듈화하고 있으므로, 필요한 모듈만 끌어서 프로그램을 짤 수 있다.

6.2.1.2. 가상 머신 바이트코드 실행 속도 문제[편집]

C/C++, Pascal, Fortran과 같은 언어와 달리, Java는 바이트코드로 된 프로그램을 실행하기 위해 운영체제와 프로그램 사이에 JVM이라는 두꺼운 계층이 하나 더 자리잡게 된다. 그리고 바이트코드는 실시간으로 각 타겟 플랫폼용 기계어로 번역되어 실행된다. 이로 인해 네이티브 바이너리 코드를 출력하는 언어와 비교하여 실행속도와 성능에 일정 부분 손실이 발생할 수밖에 없다. AWT, Swing 같은 GUI 라이브러리를 사용할 때도 심각하게 느린 것을 체감할 수 있다. 이런 문제점을 썬 마이크로시스템즈도 곧 깨달았고, 최초 발표에서 2년 후인 1998년부터 JIT 컴파일러를 JVM에 내장하여 성능이 상당 부분 개선되었다. 하지만, 그만큼 메모리가 뒷받침해줘야 한다. 현재는 보통 같은 기능/알고리즘을 실행하는 데 C++보다 2~3배 정도의 시간이 더 필요하다고 알려져 있다. 이 부분은 꽤 초기부터 지속적으로 개선되어 왔기 때문에 현재 실행속도 자체에 대한 이슈는 예전에 비해 많이 줄어든 편이다.

이 문제는 Java 9에서 '선행 컴파일'이라는 이름으로 개선될 예정이다. JIT 컴파일로 실행과 동시에 컴파일을 하는 게 아니라 기존의 정적 컴파일처럼 바이트코드를 미리 기계어로 번역하면, 컴파일 속도는 다소 느려지지만 실행 속도는 빨라지게 된다. 물론 컴파일 한 번으로 여러 플랫폼에서 동일하게 실행시키는 건 불가능해진다.

6.2.1.3. 가비지 컬렉션에 의한 실행 지연 문제[편집]

가비지 컬렉션에 의한 메모리 프리징 현상[11]이 초반부터 지속적으로 Java를 괴롭혔다. 멀쩡하게 동작해야 할 프로그램이 순간적으로 뚝 뚝 끊기는 듯한 현상이 발생하는 것. 오늘날 Java의 문제는 바이트코드 변환으로 인한 속도 저하보다 이 가비지 컬렉션의 영향이 더 크다고 할 수 있다. 실행속도와 함께 Java 초기부터 꾸준히 문제로 꼽혀온 것으로, 버전이 올라갈 때마다 다양하게 개선되어 왔다.

Java 8부터는 메모리 누수를 일으키던 메소드 영역의 PermGen Area를 제거하여 static 인스턴스와 리터럴 문자열도 GC의 대상이 되도록 바뀌었으며, 클래스, 메소드, 배열의 메타 정보는 동적 리사이징이 가능한 Metaspace로 이동시켜 시스템 힙 영역에 저장된다. 덕분에 JVM 힙 영역의 공간이 늘어나고 PermGen Area를 스캔/삭제할 필요가 없어져 GC의 성능이 대폭 향상되었다.

6.2.2. 불편한 예외 처리[편집]

그리고 프로그램을 돌리다가 프로그램이 의도된대로 동작하지 않는 상황에서 예외를 발생시켜 처리를 할 수 있다. 대부분의 언어에서 차용하고 있는 좋은 기능이지만... 유독 Java는 다른 언어와는 달리 프로그래머의 검사가 필요한 예외(Exception을 직접 상속하는 예외 클래스)가 등장한다면 무조건 프로그래머가 선언을 해줘야 한다. 그렇지 않으면 컴파일조차 거부한다. 원래 의도는 철저한 예외 처리를 하니까 만약에 발생할 수 있는 모든 상황에 안정성을 확보할 수 있겠지...였으나, 결국 대부분의 경우엔 귀찮다는 이유로, 가장 일반적인 예외(Exception 더 막나가면 Throwable) 하나만 써서 넘어가버리고[12] 폭탄 돌리듯 넘기기만 하거나(예외 던지기만 하고 try~catch 안하면 메소드를 돌고 돌다가 콰광!), 예외 나든 말든 무시해 버리는 경우가 가장 흔하다.[13] 이런 코드가 너무 흔해 빠진 나머지 이딴 식으로 쓸 거면 왜 넣었냐고 까는 사람도 많다. 그런데 선언이 필요없는, 검사 안하는 예외도 Java에 많다(...).[14] 그리고 C++이나 C# 같이 예외가 있는 언어라도 Java처럼 예외를 쓰는 경우는 별로 없다. 두 언어는 모든 예외가 검사 안하는 예외이다. 사실 예외 처리를 한다는 것은 귀차니즘과 견고함을 맞바꾸는 일인데, 안할 사람은 문법으로 강제해도 안한다는 것을 보여준다(...).

대부분의 다른 언어에서는 원하는 에러만 try-catch문으로 뽑아내고 그렇지 않은 경우에는 그냥 아무 처리를 해주지 않아도 된다. 이러한 언어를 접하던 사람이 Java를 접하면 그 특유의 경직된 예외처리에 불편해하기도 한다. 오히려 명시적으로 예외처리를 할 수 없는 경우도 존재하는데, 인터페이스를 상속받을 때 인터페이스에 선언된 예외가 아니면 구현 클래스에서 그 예외를 던질 수 없다! 특히, Java에서 제공하는 Iterator 인터페이스에는 throws 선언 따위는 없기 때문에 Iterator를 구현받았을 때 명시적으로 예외를 던질 수 없다. 이 상황을 해결하려면 RuntimeException 계열을 쓸 수밖에 없는 상황이 펼쳐진다.

다만, 상기의 내용은 실무적 접근에 의한 내용이고, 실제로는 이는 장점으로도 취급되기도 한다. Assert문을 자유자재로 쓰면서 예외처리를 하거나 코딩과 동시에 발생할 수 있는 각종 예외들을 인지하고 처리해주는 걸 잊어먹는 경우에 대한 대처가 가능하다.[15]

6.2.3. 소스 코드 길이[편집]

Java는 소스 코드의 길이가 다른 언어에 비해 상당히 긴 편이다. 같은 기능을 하는 코드를 짠다고 했을 때 Java만큼의 고생산성을 발휘하는 다른 언어에 비해 타이핑해야 할 양이 많다. 구체적으로 말하자면 일명 Boilerplate라고 부르는, 기본적인 구조를 짜기 위해서 무조건 의무적으로 작성해 주어야만 하는 서식과 코드의 분량이 많다.

인터프리터 언어에서는 puts("Hello") 정도로 끝났을 일을 Java에서는

package wiki.namu.test;

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

이만큼을 써야 한다. 같은 일을 하는 C언어 코드는
#include <stdio.h>

int main() { 
    printf("Hello\n");
    return 0;
}

파이썬의 경우
print("Hello")

극단적으로 GW BASIC에서는
? "Hello"


더 극단적으로 HQ9+에서는 H 한 글자가 코드이다

위키책에 있는 Hello World 프로그램의 목록이나, 나무위키 내의 프로그래밍 언어/예제 문서를 보면 고생산성 언어 중에서는 코드량이 긴 편인 걸 알 수 있다.

오죽하면 이런 포스트가 만들어질까. 물론 이건 Java의 문제가 아니고 마세라티 문제[16]라고 알려진 프로그래머의 과욕이 부른 참상이지만 코드에 유연성을 조금 추가하기 위해 써 넣어야 할 코드의 길이가 기하급수로 증가한다는 하나의 예시로 볼 수 있다. 참고로 저 포스트의 5년차 코드는 Spring의 패러디다. Java 이후에 나온 차세대 언어들은 같은 수준의 유연성을 확보하기 위해 들여야 할 노력의 양이 훨씬 적다.

이렇게 의도적인 장황함(verbosity)을 추구하는 언어 설계와 커뮤니티의 문화가 아이러니하게도 위에서 언급한 장점이 무색하게 가독성을 저해하는 요인이 되기도 한다. 같은 기능을 하더라도 수십 줄의 보일러플레이트 코드를 가지는 Java 코드보다 다른 언어의 코드가 보통은 더 읽기 쉽기 때문.

게다가 다른 고수준 언어(C#, Python, Ruby 등)에 비해 문법적 설탕(Syntactic sugar)[17]이 적어 이쪽에서 넘어오면 꽤 불편해하는 편. 하지만 최근 Java 8로 넘어오면서 람다 표현식, 스트림[18] 등을 지원하는 식으로 문법적 편리함을 늘려가는 추세다. 이 흐름은 다음 Java 9에서 더욱 강화될 것으로 보는 추세.[19]

그러나 꼭 명심해야할 점은, 무조건 타이핑의 양이 많다고 해서 나쁜 것만 있는 것이 아니다. 일단 Java는 명색이 클래스지향적이기 때문에 어쩔 수 없는 부분이며 프로젝트 단위의 큰 단위에서 봤을 땐 오히려 읽기가 편하기 때문에 협동 작업이라는 측면에선 장점이 있다. 축약어의 사용을 최대한 자제하는 방향으로 만들었기 때문에 그렇다. 그리고 IDE에서 기본적으로 코드를 자동 생성해주기 때문에 코드의 길이로 장단을 판별할 수는 없다. 오히려 Python의 경우 dynamic 타입 때문에 파일 하나 가지고 장난치기엔 좋겠지만 대형 프로젝트로 가면 머리 아파진다.

6.2.4. 언어적 불편함[편집]

6.2.4.1. 명사형 생각을 강제[편집]

Java는 모든 동작이 객체 상위에서 이루어지게 함으로써 명사형으로 생각하는 것을 강제한다. 그 결과로 Java에는 전역 함수가 없고 모든 함수는 어떤 클래스에 종속되어있다. 이 때문에 기능적인 부분을 작성하는데 자잘한 클래스들을 작성해야 한다는 불편함이 있다.

이런 명사 중심적 생각은 확실히 많은 경우 편리하나 동사 중심으로 생각해야하는 상황도 생각보다 흔하다는 게 문제. 예를 들어서, 퀵소트를 Java에서 엄격하게 의도된 대로 짜려면 QuickSort(array)라는 함수 대신에 Quicksorter라는 객체의 생성자에 배열을 넣고 run()을 호출하여 동작시켜야 하는 것이다.[20]

디자인 패턴을 사용해서 어느 정도 동사형 사고방식으로 코드를 작성할 수 있긴 하다. 디자인 패턴에서 핵심적 지위를 차지하는 인터페이스라는 놈을 사용하면 상당히 동사적인 관점으로 객체를 다룰 수 있다. Java의 리플렉션 API를 사용하는 방법도 있고. 하지만 애초에 언어가 생겨먹은 것 자체가 명사 기준으로 생각하게 디자인된 건 사실이다. Java의 근간을 이루는 표준 java.lang 클래스와 java.util 클래스를 동사형 사고방식으로 재작성하기 전에는 힘들다. 이 재작성 삽질은 이미 Scala에서 해 놨으므로 Java의 이러한 특징이 싫다면 Scala를 쓰면 된다.

6.2.4.2. 클로저 미지원[편집]

명사형 생각을 강제한다는 것의 연장선. Java에서 함수는 일급 객체로 취급되지 않는다. 어떤 '동작'을 넘겨야 할 때는 그 동작을 추상화한 인터페이스를 만들고, 그것을 클래스로 구현한 뒤, 객체를 파라미터로 넘겨야 한다. 반면에 클로저를 지원하는 언어는 그냥 함수를 파라미터로 넘기면 된다.

Java 8에서는 람다 표현식을 지원함과 더불어 Function, 즉 함수를 멤버 표현이라는 방식(this::add)으로 다른 함수의 파라미터로 넘길 수도 있다. Functional Interface는 수십여 종이 있으며 인자가 복수개인 것도 당연히 있고, 하나의 추상 메소드를 가진 인터페이스를 새로 만들어서 써도 된다. 또한 리턴이 없는 Functional Interface로는 Consumer<T>가 있다.

클로저 미지원 문제 때문에 저 수많은 디자인 패턴들이 만들어졌다. Java라는 언어가 설계될 당시에는 클로저라는 개념 자체가 LISP, Haskell, ML 등의 언어을 사용하거나 프로그래밍 언어를 연구하는 사람들이나 아는 몹시 마이너한 개념이었기 때문에 동시기에 만들어진 다른 많은 프로그래밍 언어들도 클로저를 지원하고 있지는 않았다. 따라서 설계 결함이라고 부를 수는 없고 현대에 들어서 단점으로 부각되기 시작했다는 편이 더 적절하다.

7. 개발환경, JVM 언어[편집]

7.1. 개발환경[편집]

Java에 특정한 라이브러리를 가미해서 웹에서 돌릴 수 있게 한 것이 Java Applet이다. 애플릿 특유의 제약으로 인해 ActiveX보다는 훨씬 안전하다는 이유로 물 건너에서는 인터넷 뱅킹이나 결제용도로 사용하기도 한다. 근데 상대적으로 안전하다는 것일 뿐, 애플릿을 사용한 결제시스템도 툭하면 뚫려서 문제가 발생하곤 한다(…). 더군다나 아이폰안드로이드에서는 되지 않는다. 게다가 크롬과 파이어폭스 등의 브라우저들이 NPAPI 지원 중단 선언을 하고, Java 9부터 애플릿의 개발이 중단되면서 결국 수명이 끝나게 되었다.

웹 애플리케이션 제작을 위해 Java 언어를 사용하는 규격으로 Java 서블릿과 JSP(Java 서버 페이지)가 있다.[21] 주로 기업에서 사용한다. 개인 웹호스팅에서는 이를 지원하는 경우는 많지 않다. 그러나 최근 Java를 지원하는 여러 클라우드 컴퓨팅 서비스가 싼 가격에 등장하고 있고, Java 뿐만이 아닌 JVM 언어를 이러한 환경에서 구동하는 사례가 늘고 있다.

오라클에서 제공하는 Java Development Kit(Java 개발 도구)를 설치하면 javac라는 컴파일러가 제공된다. 하지만 통합 개발 환경은 제공해 주지 않기 때문에, 반드시 별도의 개발용 프로그램을 써야 한다. 대표적으로 이클립스, 넷빈즈, IntelliJ IDEA 등이 있다. 만약 이것들을 안 쓰겠다고 한다면, 당신에게는 메모장과 javac.exe가 있을 뿐이다. 그리고 Java는 IDE 없이 타이핑만으로 짜기엔 굉장히 불편한 언어라는 것을 명심하자.[22] 실전 Java 개발을 할 때 프로젝트에 필요한 라이브러리 관리나 프로젝트 결과물 배포 등 프로젝트 빌드 관리를 위한 도구로는 아파치 소프트웨어 재단에서 만든 Ant와 Maven, 그 중에서도 Maven이 많이 사용되고 있다. 최근에는 이 두 가지의 단점을 보완한 Gradle이 각광을 받고 있으나 아직 Maven보다 많이 쓰이지는 않고 있다.

TDD 개발을 위한 방법으로는 Jenkins를 통한 CI 관리, SonarQube를 통한 코드 분석, Maven을 통한 빌드 관리, JaCoCo를 통한 Code Coverage 관리 등이 있다.

7.2. JVM 언어[편집]

이외에 Java와 똑같이 Java 바이트 코드를 생성하지만 언어 규격이 다른 ScalaClojure라는 언어들도 있다. Scala는 'Scalable Language'에서 따왔는데, Java와 비슷한 부분이 많으며 Java API를 그대로 가져다 쓸 수도 있다. 또한, syntactic sugar가 많고 함수형 프로그래밍의 여러 가지 요소들을 가져와서 Java에 비해 생산성도 높다. 일례로 일일히 타입을 명시하지 않고 var x === 1.5와 같이 넣으면 알아서 float 형으로 추론해준다.[23] 또, switch-case의 확장판이라 할 수 있는 패턴 매칭을 지원하며 클로저도 지원된다. 단점으로는 이런 고수준-고생산성의 언어에서 많이 볼 수 있듯이 같은 Java 코드에 비해 약간 느리다. Clojure는 Java 플랫폼에서 동작하는 LISP의 방언으로 설계되었으며 Common Lisp와 Scheme과 함께 주요 LISP 방언 중 하나로 꼽힌다. 이 언어도 마찬가지로 Java API를 가져다 쓸 수 있다.

Java 6부터 Scripting API라는 것이 추가되었다. JVM 언어 구현체에서 javax.scripting 관련 API를 제공하면 Java 코드에서 동적으로 인터프리터를 생성하고 연동하여 사용할 수 있게 해주는 표준 API이다.

7.2.1. 유명한 JVM 언어 목록[편집]

아래에 나열된 언어들이 유명하며, Common LISP, Scheme, Pascal 등 여러 다양한 언어들이 구현되어 있다.

  • Clojure

  • Groovy: Java에 Python, Ruby, SmallTalk 등의 특징을 버무린 동적 타입 언어. 2003년에 등장했다.

  • JRuby: Ruby의 대부분을 Java로 구현한 언어 구현체. 역시 Java와 호환된다.

  • Jython: 파이썬의 Java 구현체. JVM 위에서 동작하며, 따라서 Python 모듈과 함께 Java 클래스, JAR 사용이 가능하다. 참고로 로고는 Java의 커피 컨셉과 Python의 뱀 컨셉을 섞어서 커피잔에서 이 연기처럼 피어나오는 로고다(...)

  • Kotlin : IntelliJ IDEA를 만든 JetBrains에서 개발한 JVM 언어. Google I/O 2017에서 안드로이드의 공식 언어로 지정되었다.[24]

  • Rhino: JVM으로 돌아가는 JavaScript 엔진으로, 모질라 재단이 100% Java로 개발했다. JavaScript와 Java의 API를 동시에 사용해 개발할 수 있다. Java 7 에 내장되어 있다.

  • Nashorn: 또 다른 JVM 위에서 돌아가는 JavaScript 엔진이다. Java 8과 함께 등장했다. 참고로 Nashorn 은 Rhino(코뿔소)의 독일어다.

  • Scala

7.3. 유사품에 주의합시다[편집]

  • 유사품 A : 자바스크립트(JavaScript)
    JavaScript는 이 Java와는 아무 상관도 없다. 넷스케이프사에서 Mocha, LiveScript로 개발하던 스크립트 언어를 1996년 전후 열풍이던 Java의 유명세에 묻어가기위해 Sun에서 상표권을 라이선스해 JavaScript라고 이름붙였을 뿐이다. 이름 하나 생각없이 잘못 붙여서 여러 사람 지금도 헷갈리게 만든 대표적인 케이스.
    이름 말고는 언어 성격 상 연관성은 희박한 편이다. 문법조차 별로 비슷하지도 않으며, 사용되는 라이브러리나 개념 또한 많이 다르다. 기초 패러다임상 당연한 요소들을 제외하고 나면 둘의 유사점은 오직 객체지향 뿐인데 그 마저도 JavaScript는 프로토타입 베이스라 클래스를 쓰는 Java와 많이 다르다. (하지만 ECMAScript 6에서 Class가 생겼다!) 또 Java는 컴파일 언어이지만 JavaScript인터프리터 언어다. 그나마도 요즘은 둘 다 JIT로 통일되어가는 추세다. 여담으로 JavaScript에 JIT를 최초로 도입한 브라우저는 다름아닌 크롬이 아니라 파이어폭스.
    떠도는 말로 'Java와 JavaScript의 차이는 인도인도네시아의 차이와 같다'라고도 한다.햄스터, 오리오리너구리의 차이와 같다는 버전도 있다. Stack Overflow에서는 Car와 Carpet이 최다 추천을 받았다간혹 인도와 인도네시아의 차이를 이걸로 설명하는 사람도 있다. 왜냐하면 인도인도네시아가 이름만 비슷하고 서로 다른 국가이듯이 Java와 JavaScript도 다른 프로그래밍 언어이기 때문이다.
    참고로 이 JavaScript의 표준안에 대한 정식 명칭은 ECMAScript다.

  • 유사품 B : Visual J++/Visual J#
    Visual J++은 마이크로소프트에서 Java를 변형하여 윈도우 전용으로 만든 언어. 위의 JavaScript는 이름만 바꿨지만 이건 Java 자체를 윈도우에 맞도록 변형한 것이다. 이 때문에 Java 가상머신 없이 윈도우에서 네이티브로 돌아가지만, 다른 플랫폼에서는 전혀 돌아가지 않는다. 거기다 썬 마이크로시스템즈의 허락없이 마구 변형해서 썼기 때문에 소송크리를 먹고 개발이 중단되었다.
    이후 윈도우의 프로그램이 닷넷으로 넘어가면서 닷넷 기반의 Visual J#도 만들었다. Visual Studio 2005에 포함되었지만 이것도 개발이 중단되었다. 이때는 썬이 소송하지도 않았는데 중단된 것을 보면 시장성이 없었던 듯 하다. 이미 이 때는 C#이 어느 정도 자리를 잡았기 때문일 수도 있고.

8. 구글 vs. 오라클: Java 저작권 분쟁[편집]

Java를 처음 개발한 썬 마이크로시스템즈오라클에게 인수되었고, 2010년에 오라클은 구글안드로이드를 개발하면서 Java API 37개의 소스 코드를 무단 복제하여 사용했다는 이유로 소송을 제기했다. 오라클은 구글이 Java를 이용해 OS를 개발하려는 상업적 목적을 가지고 있었으므로 사전에 허가를 받았어야 했다는 주장이고, 구글은 Java API가 저작권자의 허락 없이 이용할 수 있는 공정 이용(Fair Use)의 대상이라며 맞섰다. #

2012년에 이루어진 첫번째 재판에서는 구글이 승소하였고, 2014년 항소심에서는 오라클이 승소하였으며 2015년에는 구글의 상고가 기각되었다. 이후 2016년 두번째 1심에서는 공정 이용이라는 주장이 받아들여지며 구글이 승소했지만, 결국 2018년 두번째 항소심에서 다시 오라클이 승소하게 되었다. #

항소심 재판부의 결론은 Java API 역시 저작권이 존재하는 엄연한 저작물이라는 것이다. 재판부는 구글이 Java API를 수정 없이 그대로 긁어다가 안드로이드를 만들어 모바일 OS 시장을 점령하였으며, 단순히 어떤 애플리케이션을 개발한 게 아닌 별도의 운영체제와 플랫폼을 무기로 향후 오라클이 Java를 이용하여 모바일 시장에 진출할 가능성을 꺾어버렸기 때문에 Java의 무단 이용은 불공정한 행위라고 판결했다. 현재 구글이 오라클에게 배상해야 할 금액은 90억 달러에 달할 것으로 예상되고 있다.

이 판결이 가져다 줄 여파에 대해 안드로이드 생태계가 큰 위기를 맞이했다는 시각이 있지만, 사실 소송기간 동안 안드로이드는 이미 모바일 OS 시장을 iOS와 함께 5:5로 양분하고 있을 만큼 거대하게 성장했기 때문에 이번 일로 안드로이드가 휘청거릴 일은 단연코 없다. 왜냐면 사실 90억 달러라고 해서 큰 돈이라고 생각하지만 구글은 한창 성장하던 시절인 2006년에 이미 유튜브 인수금액으로 16억 5,000만 달러를 한번에 지불해낼 정도였고, 2007년에는 광고 회사인 더블클릭을 31억 달러에 살 정도로 현금 창출력이 대단하다. 그리고 안드로이드는 직접적인 로열티 수입은 없지만 구글 검색과 광고, 구글 플레이와 유튜브 같은 구글 앱에서 나오는 수익만 해도 매년 수백억 달러에 달한다는 평가를 받고 있는데, 모바일 OS 시장 양분 댓가로 90억 달러를 낸다면 구글 입장에선 거저 먹는 것이나 다름없다.

9. 불투명한 미래?[편집]

이러한 분쟁과는 별도로, 오라클이 Java를 포기하려고 한다는 주장이 있다. "Oracle Mysteriously Fires Almost All of Its Top Java Evangelists"(Softpedia News) 자바 에반젤리스트, 오라클 퇴사의 변 "자바 구하려"(ZDNet Korea)

자바 에반젤리스트는 Java의 전체적인 업계 내에서의 분위기를 결정지을 수 있는, 비교하자면 리눅스계의 리누스 토르발스 같은 사람들인데, 오라클이 이 사람들을 꾸준히 해고하고 있다는 것이다. 장사를 독하게 하기로 유명한 오라클인지라, Java 자체가 지금은 물론이고 미래에도 그다지 수익성이 좋다고 할 수 없기에 망설임 없이 포기하려는 것이 아니냐라는 관측이 있다. 제임스 고슬링도 한마디 했다.

다만 이 부분은 사람에 따라 극단적으로 반응할 수도 있는 문제이므로[25] 업계 분위기에 대한 판단은 스스로 하도록 하자. 위에서도 언급했지만 Oracle JDK를 유료로 전환한 걸 보면 포기할 생각은 없는 듯하다.

2017년 8월 17일, 오라클이 Java EE를 포기한다고 발표했다. 오픈오피스, 넷빈즈 때와 같이 오픈 소스 생태계로 보내려 하고 있으며, 아파치 소프트웨어 재단이클립스 재단이 Java EE를 넘겨받을 유력한 후보로 알려져 있다. Opening Up Java EE 결국 이클립스 재단이 맡는 것으로 확정되었으며, Java EE의 오픈 소스화를 위한 9개 프로젝트를 추진한다고 밝혔다. ## 다만 오라클이 Java EE라는 상표권까지 넘긴 것은 아니기 때문에, 새로운 이름을 공모하였고 이후 자카르타 EE(Jakarta EE)라는 새 명칭이 결정되었다. 엔터프라이즈 자바의 새 이름 ‘자카르타 EE'[26]

10. 여담[편집]

  • Java의 창시자인 제임스 고슬링 옹은 진성 앱등이다.[27] 집에서 쓰는 IT 기기에 대해 묻는 질문에 폰, 태블릿, 데스크탑, 랩탑 등 거의 모든 IT 기기를 애플사 제품으로 도배해놨음이 밝혀졌다. 가족들도 마찬가지. 정작 애플은 OS X 레오파드 업데이트 때 Java를 찬밥 취급했지만...[28]

  • 조엘온 블로그로 유명한 조엘이 엄청나게 싫어하는 언어. 외부링크 조엘 스폴스키가 Java를 싫어하는 이유로는 성능상의 문제나 문법상 너무 쉽다(...)[30]는 이유도 있지만, Java 자체가 "위원회 기술"이라는 이유도 큰 몫을 차지한다.[31] 사실 이는 Java가 가진 태생적 문제인데 Java라는 언어가 C#처럼 어느 특정 단체나 회사가 주도적으로 끌고가는 물건이 아니다 보니 위원회를 구성하는 각 기업들의 파워게임에 따라 중요한 문제의 해결방안이 빨리 처리되지 않는 경우도 있고 배가 산으로 가는 경우도 있다.

  • Java를 설치하고 환경변수를 설정할 때 CLASSPATH의 디렉토리를 보통 %JAVA_HOME%\lib로 설정하는데, 이렇게 하면 파일 실행 시 JVM이 무조건 \lib 경로에서 클래스 파일을 찾기 때문에 해당 파일을 찾거나 로드할 수 없다는 오류 메시지를 뿜게 된다. 매번 실행할 때마다 -classpath . 옵션을 주거나 CLASSPATH 환경변수의 디렉토리 끝에 ;.을 붙이면 해결할 수 있다.[32] 물론 대부분의 IDE는 클래스 패스 설정을 자동으로 처리해 주지만, 역으로 그렇기에 클래스 패스에 대한 이해를 제대로 하지 않고 넘어가 버리는 경우가 많다.

  • Java에서 UI를 만들 때도 고려를 해야할 게, Java는 UI를 만들 때 AWT나 Swing 둘 중 하나 혹은 둘 다 선택하여 UI를 만드는 게 가능하다. 조심해야 할 점은, AWT로 생성한 UI는 Swing UI에 가려져버린다. 그래서 멀쩡히 잘 돌아가는 코드인데도 불구하고 배경이 컨트롤(콤보박스라거나)을 가려버리는 일이 있을 수 있다. 어차피 요즘은 둘 다 안 쓴다

  • Java 클래스 바이트코드 매직넘버가 0xCA 0xFE 0xBA 0xBE다. 이것을 붙이면 CAFEBABE다. CAFEBABE인 이유는, 제임스 고슬링과 다른 연구원들이 St. Michael's Alley라는 곳에 점심을 먹으러 가곤 했다고 한다. 그 지방 전설에 의하면 그곳에서 더 그레이트풀 데드라는 밴드가 크게 성장하기 전에 연주하던 곳이라고 했다. 그리고 제임스 고슬링과 연구원들은 그곳을 Cafe Dead라고 불렀다. 그러다 CAFE DEAD가 헥스 넘버인 것을 알아냈다고 한다.[33] 그 때 마침 그는 파일 포맷 소스와 매직넘버를 개편하고 있었다.[34] 결국 Object 파일의 매직 넘버는 CAFEDEAD가 되었다. 나머지 하나, 클래스 파일의 매직넘버는 CAFE 다음에 맞을 만한 번호를 정하는 것인데, 그 때 적은 것이 BABE다.

  • 2012년 말에는 Java에 보안 취약점이 발견되어 오라클에서 긴급 보안 패치를 발표했지만 또 다른 취약점이 발견돼버리는 바람에 Java를 계속 써야 하나 말아야 하는 논쟁이 벌어지기도 했다. 지금은 잠잠해진 상태.

  • 기존의 32bit용은 64bit 웹 브라우저에 사용할 수 없기에 64bit용 Java가 공개되어 있다. 그러나 32bit 웹 브라우저와 64bit 웹 브라우저를 각각 돌아가며 사용해야 할 필요가 있을 경우 둘 다 설치해야 제대로 돌아가기 때문에 번거로운 편이다.

  • 2018년 초부터 자바 설치파일로 위장한 랜섬웨어가 기승을 부리고 있다. 어느날 갑자기 직접 설치파일을 다운받거나 하지도 않았는데 설치파일이 저절로 실행되며, 대부분의 감염자들은 이를 자동 업데이트로 인지하고 그대로 업데이트 해버려서 감염된다고 한다. 심지어 사용하는 운영체제의 언어를 인지하여 해당 언어의 자바 설치파일에 있는 문장과 이미지까지 철저하게 재현되어서 의심할 여지가 없다고 한다.

11. 관련 문서[편집]

[1] Premier Support. 오라클에 비용을 내고 기술 지원을 받는 서비스이다.[2] Extended Support. 일반 지원이 종료된 후 추가적인 비용을 지불하여 기술 지원을 더 받을 수 있는 기간이다.[3] GCC 계열 Java 컴파일러인 GCJ에서는 이미 지원하고 있던 기능이다.(현재는 출시 중단)[4] '@Nonnull var x, @Nullable var y'를 'x.process(y)'로 간략화할 수 있게 되었다.[5] 정말로 포인터를 써야 할 경우 Unsafe 클래스를 쓰면 된다. 다만 팩토리 메소드가 막혀있 어 리플렉션을 사용해야만 이용할 수 있다.[6] 어차피 Java에서는 다중 상속을 포기함으로써 생기는 문제를 interface를 다중 구현할 수 있도록 하여 어느 정도 해결하기도 했다.[7] 물론 이는 게임 등 어느정도 사용되는 메모리를 예측하여 제한하는 프로그램이 아닌, 크기를 예측 가능한 빅 데이터를 가공하고 처리하는 프로그램에서 주로 발견되는 차이점이다.[8] 하지만 연산자 오버로딩은 분명 제네릭 프로그래밍에 도움을 준다. 가령 제네릭 클래스 내에서 주어진 타입의 변수 두 개를 더하는 연산을 하고 싶다면? 더하는 연산 등 여러 일반적인 작업들은 Java의 primitive 타입에만 필요한 것은 아니다. 행렬 등이 그런 대표적인 예다. 이러한 측면에서 본다면 프로그래머의 작업에 있어서의 일관성은 훼손됐다고 볼 수도 있다.[9] 다만 제네릭은 Type Erasure를 사용하기 때문에 개념적으로 C++의 템플릿과 다르며, 할 수 있는 일도 거의 일반화 프로그래밍 자체로만 한정돼 있다.[10] 기존에 앞 문단 서술에 사용되었던 용어인 "템플릿 메타 프로그래밍"은 개념을 오해하여 사용한 것이므로 "템플릿 일반화 프로그래밍"으로 대체하였다. 일반화 프로그래밍(generic programming)은 자바나 C#에서 "제네릭"이라는 형태로 제한적으로 구현되어있다. 그러나 템플릿 메타 프로그래밍(template meta-programming)은 자바나 C#에서 전혀 구현되지 않는 별도의 개념이다. 아마도 C++에서 쓰는 "템플릿"이라는 용어랑 자바의 "제네릭"이라는 용어가 같은 것을 지칭한다고 착각해서 나온 결과로 추정된다. C++ 템플릿 프로그래밍 = 제네릭 프로그래밍 + 템플릿 메타 프로그래밍, Java generics = 제네릭 프로그래밍으로 이해하면 쉽다. "템플릿 메타 프로그래밍"은 C++, D등의 극 소수의 언어만 지원한다.[11] 메모리를 훑으면서 순간적으로 프로그램이 얼어붙어 멈추는 현상.[12] 이를 gotta catch 'em all 패턴이라고 한다.[13] 물론 이렇게 짜면 안되지만 구조적으로 강요받는 형편.[14] 이쪽은 RuntimeException 계열의 예외로, 이것을 던지는 메소드가 throws에 명시적으로 던진다고 선언하지 않았을 경우 검사를 하지 않아도 된다.[15] 대한민국에 국한되는 경향이 강하긴 하지만 현재 한국에서 이러한 예외처리를 코딩하는 순간에 인지하는 개발자는 드물다. 국비지원 학원을 막 졸업한 신입들은 말 할 것도 없으며 현업 몇년 한 초중급 경력자들 역시 이를 인지하지 못하는 경우가 허다하기 때문에, 어찌보면 대한민국 IT계의 버그처리와 예외처리에 있어서만큼은 장점으로 볼 수도 있다.[16]마세라티가 맞다. 자신이 탈수나 있을지도 모르는 마세라티를 타면 어떻게 해야 될까... 라는 쓸데없는 고민을 하는 것을 비유하는 문제로, 당장에 쓸데없는 기능을 위해 과도하게 투자하는 것을 의미한다.[17] 프로그래밍 언어를 좀 더 쉽게 표현할 수 있도록 하는 보조문법. C에서 구조체 포인터를 쓸 때 (*ptr).num은 ptr->num으로도 표현 가능하므로, ->는 문법적 설탕이라고 할 수 있다.[18] 컬렉션(Collection)의 이터레이터를 확장해서 처리할 수 있는 개념으로, 이터레이터의 원소를 필터링해서 원하는 원소만 뽑거나, 원소갯수를 줄여버리고, 이렇게 다시 뽑혀진 원소들로 갖가지 처리를 만드는 등 '함수적인(functional)' 기능을 제공한다.[19] 정작 람다 표현식의 추가는 자바 내에서 논란이 있다. 이제서야 자바에 추가된 것도 논란이 심했기 때문.[20] 실제로 자바에서 기본 제공하는 정렬 기능은 Collections 클래스의 정적 메소드인 sort(array);를 호출하도록 작성되어 있다.[21] JSP의 목적이 HTML 페이지를 동적으로 만들어내는 것이다. JSP 소스는 Java 서블릿 코드로 변환되어 서버에서 실행되고, 서버는 이 HTML 결과를 브라우저에 보여준다. JSP 페이지는 HTML 페이지에 Java 코드가 포함되어 있는 식으로 되어 있는 경우가 많고, 이 점은 PHP, ASP.NET 등과 비슷한 편이다. 반면 Java 서블릿은 서버 쪽에서 하는 일에 관심이 많지만 출력에 대한 관심은 적다. 필요하다면 브라우저에 출력을 전혀 안 보낼 수도 있다. 최근에는 Server side script language로 HTML 페이지를 동적으로 만드는 식으로는 프로그래밍을 하지 않는다. JSP, PHP와 같은 Server side script language로는 서버에 있는 자원의 접근을 주로 하고(DB 연산, File 연산 등등) 화면에 보여주는 UI는 HTML/CSS/JavaScript로만 한다. 따라서 Client side와 Server side 간에 통신이 필요한데 이는 XHR(XML HTTP Request)를 이용한다. 이러한 프로그래밍 기법을 나타내는 표현이 REST 내지는 Open API이다.[22] Java는 현용 프로그래밍 언어 중에서는 가장 Verbose한(장황한) 언어로 꼽힌다. 즉, 같은 의미인데 많은 타이핑이 필요하다.[23] Java는 버전 10에서 와서야 이와 같은 타입 추론 기능이 가능해졌다.[24] 안드로이드의 Java 라이선스 무단 사용으로 구글이 오라클과 법정 싸움을 한 여파로 보인다.[25] 각 언어 프로그래머들의 자신의 언어에 대한 자부심은 가히 종교의 신앙과 비견할 만한 것이다.[26] 원래 아파치 소프트웨어 재단이 '자카르타'라는 이름의 Java 오픈 소스 프로젝트(현재는 종료)를 소유하고 있었으나, 해당 명칭을 사용해도 된다고 허가하였다.[27] Java가 안드로이드의 기반이 되는 언어라는 점을 생각하면 아이러니...[28] 사실 애플은 독자적인 JDK를 제공하는지라 Java 개발자들을 매우 피곤하게 하는 회사이기도 하다.[29] 단지 징역을 살지는 않고 FBI에서 1년 근무하는 것으로 퉁쳤다.[30] 이 부분은 대학의 교육용 언어로서의 이야기다. 산업용으로서는 같은 기능을 개발하기 위한 언어는 쉬우면 쉬울수록 좋은것이 당연하다. 물론 성능과 생산성 사이에서 적절한 균형을 잡아야 하지만.[31] Java 상임 위원회에는 인텔, 오라클, 젯브레인즈, 레드햇, ARM Holdings 등이 속해 있다. 모두 각자의 분야에서 내로라하는 기업들이다.[32] '.'은 Java 클래스 파일이 위치한 해당 디렉토리를 의미한다.[33] CAFEDEAD를 0xCA 0xFE 0xDE 0xAD로 바꿨을 때의 얘기인 듯하다.[34] 그때 필요한 매직넘버는 2개였다. 하나는 오브젝트 파일이고, 또 다른 하나는 클래스 파일 매직넘버였다.