[JAVA] JAVA8 과 JAVA11 의 차이점을 알아보자.
들어가기 앞서
JAVA 를 버전별로 차이점들을 작성하고 있지만, 정확하게는 추가된 기능이나 특징들을 설명하는 글입니다. 실무에서 SpringBoot 를 사용하시거나, 새로운 SpringBoot 버전이 나와 릴리즈노트를 확인하시게 된다면 권장 자바 버전이 있는 것을 확인하실 수 있습니다.
예를 들어, SpringBoot 3.x 이상 부터는 자바 17 버전 이상을 지원합니다.
신규 버전은 앞으로도 계속 나올 것이고 변화하는 세상에 맞춰가며 공부하는 것이 개발자의 숙명이자 묘미가 아닐까 싶습니다. 비록 지금은 JAVA 11 버전에 대해서 작성하고 있지만 조만간 JAVA 17 버전으로 찾아뵙도록 하겠습니다.
LTS(Long-Term Support) 란?
자바의 LTS(Long-Term Support) 버전은 장기 지원을 받는 안정적인 버전입니다. 이러한 버전은 특히 엔터프라이즈 환경에서 널리 사용되며, 장기적인 지원과 업데이트를 받을 수 있습니다.
물론 자바8 버전 이후에 자바 9 와 자바 10 버전도 있지만, 필자 블로그의 글은 LTS 버전 별로 비교하도록 하겠습니다.
JAVA 8 버전 그리고 JAVA 11 의 차이점 ?
필자는 자바 11 버전과 사실 어색하지만, 어떤 자바 버전이라도 개발자 입장에서는 적응하고 활용할 수 있어야 합니다. 나중에 한 번 찾아보기 위해 간단하게 자바 11 버전의 특징들을 작성해 봅니다.
1. 모듈 (module)
자바 11에서 도입된 모듈은 프로젝트를 더 모듈화 하고 의존성을 관리하는 데 도움을 주는 기능입니다. 모듈은 프로젝트를 작은 단위로 분할하여 각 모듈 간의 의존성을 명시적으로 정의할 수 있게 해 줍니다. 이것은 코드를 더 깔끔하게 구성하고, 의존성 충돌을 방지하며, 애플리케이션을 더 쉽게 유지보수하고 확장할 수 있도록 도와줍니다.
자바 8 모듈화 없음
모듈화가 없는 단일 패키지 구조 예제 코드
// 자바 8에서는 모듈화가 없는 단일 패키지 구조
package com.example.myapp;
public class Main {
public static void main(String[] args) {
System.out.println("Hello, Java 8!");
}
}
자바 11 모듈 도입
1. 모듈 정의 파일(module-info.java)
모듈 1 : 'com.example.module1'
// module-info.java 파일
module com.example.module1 {
exports com.example.module1.utils;
}
모듈 2 : 'com.example.module2'
// module-info.java 파일
module com.example.module2 {
requires com.example.module1;
}
2. 패키지와 클래스 정의 : 각 모듈에는 패키지와 클래스가 포함되어야 한다.
모듈 1 :
// com.example.module1.utils 패키지에 있는 Util 클래스
package com.example.module1.utils;
public class Util {
public static void doSomething() {
System.out.println("Module 1의 Util 클래스에서 작업을 수행합니다.");
}
}
모듈 2 :
// com.example.module2 패키지에 있는 Main 클래스
package com.example.module2;
import com.example.module1.utils.Util;
public class Main {
public static void main(String[] args) {
Util.doSomething(); // 모듈 1의 Util 클래스를 사용
}
}
3. 컴파일과 실행 : 모듈을 컴파일하고 실행합니다.
javac -d out/com.example.module1 com.example.module1/module-info.java com.example.module1/utils/Util.java
javac -d out/com.example.module2 com.example.module2/module-info.java com.example.module2/Main.java
java --module-path out -m com.example.module2/com.example.module2.Main
2. HTTP Client API
동기 방식
HTTP Client API를 사용하여 동기 방식으로 HTTP 요청을 보낼 때, 요청을 보내고 서버로부터 응답을 기다리는 동안 현재 스레드는 차단됩니다. 요청과 응답을 기다리는 동안 다른 작업을 수행하지 못하고 대기해야 합니다.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class SyncHttpClientExample {
public static void main(String[] args) throws Exception {
HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://example.com"))
.GET()
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("HTTP 상태 코드: " + response.statusCode());
System.out.println("응답 내용: " + response.body());
}
}
비동기 방식
비동기적으로 HTTP 요청을 보내는 예제이며, 요청을 보낸 후 응답을 기다리지 않고 다른 작업을 수행할 수 있다.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class AsyncHttpClientExample {
public static void main(String[] args) throws Exception {
HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://example.com"))
.GET()
.build();
CompletableFuture<HttpResponse<String>> futureResponse = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
futureResponse.thenAccept(response -> {
System.out.println("HTTP 상태 코드: " + response.statusCode());
System.out.println("응답 내용: " + response.body());
});
// 다른 작업을 수행하거나 이벤트 루프를 사용해 대기할 수 있음
// ...
}
}
3. Z Garbage Collector (ZGC)
Z Garbage Collector (ZGC)은 자바 11에서 도입된 새로운 가비지 컬렉션(GC) 알고리즘으로, 이전 버전인 자바 8의 기본 GC 알고리즘인 G1(Garbage-First)과 비교하여 여러 면에서 개선된 특징을 가지고 있습니다.
저지연성 (GC Pause Times)
자바 8(G1 GC)
- G1 GC 는 주요 GC 작업 중에도 일시 정지 시간이 상대적으로 길었습니다.
- 특히 대규모 힙(Heap)에서는 긴 일시 정지가 발생할 수 있었습니다.
자바 11 (ZGC)
- ZGC는 주요 GC 작업 중에도 매우 짧은 일시 정지 시간을 제공합니다.
- 이는 실시간 및 대규모 애플리케이션에서 매우 중요한 특징입니다.
대용량 메모리 지원
자바 8 (G1 GC)
- G1 GC 도 큰 힙 크기를 다룰 수 있지만, ZGC 와 같은 대용량 메모리에 대한 지원은 자바 8 에서 제공하지 않았습니다.
자바 11 (ZGC)
- ZGC 는 테라바이트 급의 대규모 메모리를 처리할 수 있도록 설계되었습니다.
멀티 스레드 지원
G1 GC 도 멀티 스레드 환경에서 작동하지만, ZGC 는 멀티 스레드 지원을 더욱 개선하여 성능을 향상했습니다.
자동 조정 기능
자바 8 (G1 GC)
- G1 GC 에서는 GC 관련 매개변수를 수동으로 조정해야 할 때가 있었습니다.
자바 11 (ZGC)
- ZGC 는 자동으로 일시 정지 시간을 최소화하도록 조정됩니다.
- 이를 통해 응용 프로그램 개발자가 더 작은 관리 작업을 수행할 수 있습니다.
설정 및 사용이 간단
자바 8 (G1 GC)
- G1 GC 의 설정 및 조정은 복잡할 수 있었습니다.
자바 11 (ZGC)
- ZGC 는 기본 설정에서도 잘 적동하며, 추가적인 설정 없이도 사용할 수 있습니다.
- 이로 인해 개발자가 더 쉽게 GC 관련 문제를 처리할 수 있습니다.
4. Collection Factory Method 강화
자바 11에서는 컬렉션을 생성할 때 명확하고 편리한 팩토리 메서드가 도입되었습니다. 이러한 팩토리 메서드는 컬렉션을 더 간결하게 초기화하고 코딩을 더 간편하게 만듭니다.
자바 8 에서의 컬렉션 생성
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Java8CollectionExample {
public static void main(String[] args) {
// List 생성
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
// Map 생성
Map<Integer, String> map = new HashMap<>();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");
// Set 생성
Set<String> set = new HashSet<>();
set.add("Apple");
set.add("Banana");
set.add("Cherry");
}
}
자바 11 에서의 컬렉션 생성
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Java11CollectionExample {
public static void main(String[] args) {
// List 생성
List<String> list = List.of("A", "B", "C");
// Map 생성
Map<Integer, String> map = Map.of(1, "One", 2, "Two", 3, "Three");
// Set 생성
Set<String> set = Set.of("Apple", "Banana", "Cherry");
}
}
5. 로컬 변수 타입 추론 “var”
자바 11에서 도입된 var 키워드는 지역 변수의 타입을 추론하는 데 사용됩니다. 이것은 코드를 간결하게 만들고 가독성을 향상시키는 데 도움이 됩니다. 이전 버전의 자바에서는 변수를 선언할 때 반드시 타입을 명시해야 했지만, var를 사용하면 컴파일러가 변수의 타입을 자동으로 추론합니다.
자바 11 에서 변수를 선언하는 예제
var name = "John"; // 문자열 타입으로 추론
var age = 30; // 정수 타입으로 추론
var colors = new ArrayList<String>(); // ArrayList<String> 타입으로 추론
참고 사이트
여기어때 기술 블로그 - 우리팀이 jdk 17을 도입한 이유