Programming/Java

Java 8, 11, 17 버전별 추가된 기능 (+ 무슨 버전을 써야할까?)

Jan92 2023. 7. 5. 01:20

java 8, 11, 17 버전이 많이 사용되는 이유와 버전별 추가된 기능

java 8, 11, 17

최근 몇 년 동안 java에서 가장 많이 사용되는 버전은 'java 8'으로 저 역시 실무에서는 java 8만 계속 사용하고 있는데요.

자바는 2021년 9월 출시된 LTS 버전 java 17 이후로 2023년 7월 현재 java 20 버전까지 출시가 된 상태입니다.

 

이처럼 java에는 다양한 버전이 있는데요. 아래 jetbrains의 '2022년 개발자 생태계 설문조사'를 살펴보면 자바 개발자들이 사용하는 버전이 java 8, 11, 17에 집중되어 있는 것을 볼 수 있는데, 그 이유는 무엇일까요?

 

해당 포스팅은 자바 생태계에서 java 8, 11, 17이 많이 사용되는 이유와 각 버전별로 추가된 기능에 대해 정리한 내용입니다.

 

 


다양한 java 버전과 그중에서 java 8, 11, 17이 많이 사용되는 이유

출처 - https://www.jetbrains.com/ko-kr/lp/devecosystem-2022/java/

jetbrains의 developer ecosystem survey 2022 중에서 '어떤 버전의 java를 주로 사용하는지'에 대한 설문의 결과를 살펴보면 대부분의 자바 개발자들이 java 8, 11, 17을 사용하는 것을 볼 수 있는데요.

 

이 세 가지 버전이 많이 사용되는 이유는 해당 버전들이 LTS(Long Term Support) 버전이기 때문이며, LTS 버전이란 'Long Term Support'라는 말 그대로 장기간에 걸쳐 지원하도록 고안된 소프트웨어 버전을 뜻합니다.

 

 

***

LTS 버전은 출시 이후 8년간 보안 업데이트 및 버그 수정이 지원되는 반면, 6개월 간격으로 출시되는 non-LTS 버전의 경우 출시되는 주기가 짧은 만큼 업데이트되는 양도 적고, 지원 기간도 6개월 밖에 되지 않는다는 특징이 있습니다.

 

 


가장 최근에 나온 java 17

가장 최근에 출시된 LTS 버전인 java 17은 2021년 9월 출시되었습니다.

java 17 출시 전까지는 java 8의 종료 일정(EOL, End of Life)이 java 11의 종료 일정 이후인 JDK 제품들이 많다는 이유와 기존 서비스와의 호환성 때문에 8 버전에서 11 버전으로 업그레이드하는 경우가 적었는데요.

 

17 버전이 출시된 이후 8 버전의 사용 비율이 상당히 줄었고, java 17을 사용하는 비율이 많아졌다는 것을 볼 수 있습니다.

(하지만 Oracle에서 JDK 8을 '현재까지 출시된 버전 중 가장 오랜 기간 지원될 버전'이라고 발표한 만큼 8 버전의 지원 기간이 17 버전의 지원 기간보다 조금 더 긴 상태입니다.)

 

 

spring boot 3.0 release notes

이처럼 17 버전으로의 전환율이 높은 이유 중 하나는 바로 'Spring Boot 3.0'이라고 생각되는데요.

Spring Boot 3.0 Release Notes를 참고해 보면, 스프링 부트 3.0은 Spring Framework 6을 기반으로 하며, 최소 버전으로 java 17을 사용해야 한다고 명시되어 있습니다.

 

 


그래서 무슨 버전을 쓰는 것이 좋은가? (개인적인 생각)

'그래서 무슨 버전을 쓰는 것이 좋은가?'라고 한다면, 단순히 사용할 버전만 생각하는 것이 아니라 개발 환경과 여러 요소들이 모두 고려되어야 하는 문제이기 때문에 정답은 없다고 생각하는데요.

 

하지만 스프링 부트 3.0에서 java 17 이상을 사용해야 한다는 점과 java 8의 사용 비율이 줄어들고 있는 추세를 봤을 때, 11 버전 또는 17 버전을 사용하는 것에 큰 문제가 없다면 신규 프로젝트에서는 11 이상의 버전을 도입해 보는 것도 좋을 것 같다는 것이 개인적인 생각입니다.

 

 


각 버전별로 추가된 기능

아래 내용은 각 버전별로(8, 11, 17) 추가된 기능들과 해당 기능들 중 몇 가지 예시를 정리한 것입니다.

 

 

1. Java 8 (was released on March 18, 2014)

  • Oracle이 Sun Microsystems 인수 후 출시한 첫 번째 LTS 버전의 자바
  • 32bit를 지원하는 마지막 공식 Java 버전
  • Oracle사에서 지원하는 유료 버전인 Oracle JDK와 오픈소스 기반의 무료 버전인 Open JDK로 나뉨
  • new Date and Time API(LocalDateTime 등)
  • Lambda, Stream API
  • PermGen Area 삭제
  • Static Link JNI Library
  • Unsigned Integer 계산
  • Annotation on Java Types
  • Interface Default Method
  • Optional class
  • Nashorn JavaScript engine 탑재

 

1-1. Lambda

int max(int a, int b) {
    return a > b ? a : b;
}

//람다식으로 변환
(a, b) -> a > b ? a : b;

'람다식(Lambda Expression)'이란 함수를 간단한 식으로 표현하는 방법을 말하는데요.

메서드의 이름과 반환값(return)이 생략된다는 점에서 '익명 함수(anonymous function)'라고도 불립니다.

 

 

1-2. Stream API

List<String> lowercase = Arrays.asList("a", "b", "c", "d", "e");
lowercase.stream()
        .map(String::toUpperCase)
        .forEach(System.out::println);

Steam은 컬렉션의 저장 요소를 하나씩 순회하면서 처리할 수 있는 코드 패턴입니다.

람다식을 지원한다는 점과 내부 반복자를 사용하기 때문에 병렬 처리가 쉽다는 특징이 있습니다.

 

 

1-3. interface default method

public interface TestInterface {
    void doSomething();
    default void doSomethingDefault() {
        System.out.println("doing something default");
    }
}

//implements the interface
public class TestClass implements TestInterface {
    @Override
    public void doSomething() {
        System.out.println("doing something");
    }
}

TestClass testClass = new TestClass();
testClass.doSomething();          // Output: "doing something"
testClass.doSomethingDefault();   // Output: "doing something default"

java 8 이전의 인터페이스는 메서드 정의만 할 수 있었고 구현은 할 수 없었는데요.

8 버전부터 default method라는 개념이 생기면서 구현 내용도 인터페이스에 포함시킬 수 있게 되었습니다.

 

 

1-4. Optional class

//create an optional that contains a value
Optional<String> optional = Optional.of("Hello, world!");
//check if a value is present
if (optional.isPresent()) {
	String value = optional.get();
	System.out.println(value);    // Output: "Hello, world!"
}
		
//create an empty optional
Optional<String> emptyOptional = Optional.empty();
//get a default value if the optional is empty
String value = emptyOptional.orElse("default value");
System.out.println(value);    // Output: "default value"
		
//throw exception
emptyOptional.orElseThrow(() -> new RuntimeException("throw Exception"));

Optional<T>는 null이 올 수 있는 값을 감싸는 Wrapper 클래스로, 참조하더라도 NPE(Null Pointer Exception)가 발생하지 않도록 도와주는 역할을 하는데요.

따라서 예상치 못한 Null Pointer Exception이 발생될만한 상황에서도 예시와 같이 제공되는 메서드를 통해 간단하게 예외 처리를 할 수 있습니다.

 

 

2. Java 11 (was released on September 25, 2018)

  • Oracle JDK와 Open JDK 통합되고 Oracle JDK가 구독형 유료 모델로 전환
  • 람다 지역 변수 사용 방법 변경
  • Third Party JDK로의 이전 필요
  • HTTP 클라이언트 표준화 기능
  • 앱실론 가비지 컬렉터 (Epsilon GC)

 

2-1. 람다 지역 변수 사용 방법 변경

 

(var s1, var s2) -> s1 + s2

var 키워드는 java 10에서 추가되었는데요.

var 키워드를 사용하는 경우 데이터 유형을 지정하지 않고 변수를 선언하고 정의할 수 있으며, 컴파일러는 할당된 데이터 유형에 따라 데이터 유형을 결정하게 됩니다.

 

java 11에서 부터 위와 같은 구문이 지원되면서 람다 인자에 대한 타입 추론의 유연성이 추가되었으며, 람다식에 var 키워드를 사용할 수 있게 되면서 아래와 같은 파라미터 어노테이션도 적용할 수 있게 되었습니다.

(@NonNull var s1, @Nullable var s2) -> s1 + s2

 

 

2-2. HTTP Client

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://test-api.com/posts"))
        .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

11 버전에서 도입된 Java HttpClient API는 최신 HTTP 표준의 클라이언트를 구현하며, 동기 및 비동기 프로그래밍 모델인 HTTP/1.1 및 HTTP/2를 지원합니다.

(java 11 이전에는 기본적인 URLConnection 구현 또는 Apache HttpClient 등의 타사 라이브러리에 의존해야 했습니다.)

 

 

3. Java 17 (was released on September 14, 2021)

  • 봉인 클래스(Seald Class) 정식 추가
  • 패턴 매칭 프리뷰 단계
  • Incubator (Foreign Function & Memory API)
  • 애플 M1 및 이후 프로세서 탑재 제품군에 대한 정식 지원
  • 의사난수 생성기를 통해 예측하기 어려운 난수를 생성하는 API 추가
  • 컨텐츠 기반의 역직렬화 필터링
  • Record Data Class 추가

 

3-1. Seald Class

public sealed class Shape permits Circle, Square {
    // common fields and methods
}

public final class Circle extends Shape {
    // circle-specific fields and methods
}

public final class Square extends Shape {
    // square-specific fields and methods
}

17 버전에서 추가된 Seald Class, Interface는 상속하거나(extends), 구현(implements) 할 클래스를 지정해 두고, 해당 클래스들만 상속 또는 구현을 허용하는 키워드입니다.

개발자는 seald 키워드를 통해 어떤 클래스가 해당 클래스를 상속 또는 구현하는지를 쉽게 알 수 있고, 또 제한할 수 있습니다.

 

 

3-2. Record Data Class

//Lombok 사용 예시
@EqualsAndHashCode
@ToString
@AllArgsConstructor
@Getter
public class Person {
    private final String name;
    private final String address;
}

//record class 예시
public record Person (String name, String address) { }

Record 키워드는 14 버전에서 프리뷰 기능으로 추가되었고, 16 버전에서 공식 기능이 되었는데요.

 

Record 클래스는 불변 데이터를 객체 간에 전달하는 작업을 간단하게 만들어주며, record를 사용함으로써 불필요한 코드(boilerplate code)를 제거할 수 있고, 적은 코드로도 명확한 의도(data carrier)를 표현할 수 있다는 특징이 있습니다.

 

 

3-3. 텍스트 블록(Text Blocks)

String html1 = "<html>\n" +
        "           <body>\n" +
        "               <p>Hello, world</p>\n" +
        "           </body>\n" +
        "       </html>\n";

// Text Blocks
String html2 = """
        <html>
            <body>
                <p>Hello, world</p>
            </body>
        </html>
        """;

텍스트 블록은 java 13, 14 버전에서 프리뷰로 추가되었고 15 버전에서 정식으로 발표되었는데요.

멀티 라인의 문자열을 에스케이프 시퀀스 없이 사용감으로 소스 코드 작성을 편리하게 하고, 코드의 가독성을 높이는데 주된 목적을 가지고 있다고 합니다.

 

 

 

< 참고 자료 >

https://medium.com/javarevisited/java-8-9-11-and-17-what-you-need-to-know-about-the-key-differences-between-these-versions-808dfee652ba

https://techblog.gccompany.co.kr/우리팀이-jdk-17을-도입한-이유-ced2b754cd7