매일 업데이트
2022-11-15 06:44 8 min

자바 17의 새로운 기능은 무엇입니까?

자바 언어와 런타임 플랫폼의 최신 장기 지원(LTS) 버전인 자바 17이 2021년 9월 14일에 세상에 공개되었습니다. 이 새로운 버전이 제공하는 혁신적인 기능들과 기존 자바 환경을 업그레이드해야 하는 이유에 대해 자세히 살펴보겠습니다.

현재 많은 애플리케이션들이 자바의 이전 버전, 특히 자바 11이나 자바 8과 같은 이전 LTS 버전을 기반으로 운영되고 있습니다.

그렇다면 기업들이 최신 자바 버전으로의 전환을 고려해야 하는 이유는 무엇일까요? 자바 17 업그레이드는 주로 JVM 내부에 도입된 최신 기능들을 최대한 활용하기 위한 노력의 일환입니다.

다수의 기업들이 도커와 도커 이미지를 사용하여 최소한의 노력과 시간으로 자바 17로의 전환을 용이하게 하고 있습니다. 개발자들은 지속적 통합/배포(CI/CD) 파이프라인을 설정하고 도커 이미지 내에서 모든 작업을 실행할 수 있습니다. 이전 자바 버전을 사용하는 다른 팀들은 기존의 도커 이미지를 계속 활용할 수 있어, 전체적인 워크플로우에 미치는 영향은 최소화됩니다.

자바 17의 주요 특징

macOS 및 AArch64 아키텍처 지원 강화

이번 버전에서 가장 주목할 만한 JVM 기능 중 하나는 JEP 391을 통해 AArch64 아키텍처에서 macOS 지원을 향상시킨 것입니다. 이는 Apple이 최근에 출시한 M1 프로세서 시리즈를 완벽하게 지원하는 것을 의미합니다.

일부 공급업체들이 이미 해당 아키텍처를 지원하는 JDK 버전을 출시하고 자바 8까지 지원을 확대하고 있지만, 해당 플랫폼 사용자들에게는 여전히 중요한 개선 사항입니다. 특히 Linux/AArch64 플랫폼은 이미 자바 9에서, Windows/AArch64는 자바 16에서 지원이 추가되었습니다.

봉인된 클래스

자바 17에 새롭게 도입된 봉인된 클래스 기능은 시험 단계를 거쳐 공식적인 자바 언어 기능으로 자리매김했습니다. 이 기능은 클래스가 의도하지 않은 방식으로 확장되거나 구현되는 것을 방지하여 코드의 안정성과 보안성을 높여줍니다.

봉인된 클래스를 사용하면 컴파일러가 허용되지 않은 하위 유형으로 변환하려는 시도를 컴파일 시점에 감지하여 오류를 생성할 수 있습니다. 또한 자바 17은 macOS에서 실행되는 AWT/Swing 애플리케이션을 위해 OpenGL 대신 Apple Metal API를 사용하는 새로운 렌더링 파이프라인을 제공하며, 개선된 난수 생성 API와 향상된 기능들을 함께 제공합니다.

자바 17의 변경점, 삭제 및 제한 사항

자바 17은 이전 버전과 비교하여 다양한 변경 사항, 삭제된 기능, 그리고 새로운 제한 사항들을 포함하고 있습니다.

JDK 내부 캡슐화 강화

JDK 내부 캡슐화 프로세스가 완료되었습니다. 이는 자바 9에서 처음 도입되었으며, 사용자들이 리플렉션 등의 기술을 사용하여 내부 API 사용 제한을 우회하려고 할 때 런타임 시에 경고를 표시했습니다. 또한 이 동작을 제어하기 위한 명령줄 인자도 추가되었습니다.

자바 9 이후, 다양한 API가 생성되어 가장 일반적으로 수행되는 작업에 대한 일관된 접근 방식을 제공했습니다. 자바 16에서는 기본 설정이 경고에서 액세스 비활성화로 변경되었으며, 사용자는 명령줄 인자를 통해 이전 동작을 유지할 수 있었습니다.

그러나 자바 17에서는 명령줄 인자가 제거되어 더 이상 이 제한을 해제할 수 없습니다. 이는 허가되지 않은 모든 내부 API 접근이 이제 완전히 차단됨을 의미합니다.

엄격한 부동 소수점 연산 의미 체계 적용

또한 '제거'된 기능 중 하나는 항상 엄격한 부동 소수점 의미 체계의 재도입입니다. 자바 1.2에서는 성능 향상을 위해 부동 소수점 연산에서 약간의 정밀도를 포기할 수 있도록 허용했습니다. 엄격한 의미 체계가 필요한 클래스와 메서드에는 strictfp 키워드가 추가되었습니다.

이후 다양한 CPU 명령어 세트가 도입되면서, 불필요한 성능 저하 없이 엄격한 부동 소수점 의미 체계를 사용할 수 있게 되었습니다. 자바 17에서는 이전의 기본 의미 체계를 제거하고 모든 부동 소수점 연산이 엄격하게 실행됩니다. strictfp 키워드는 여전히 존재하지만 더 이상 아무런 효과가 없으며 컴파일 시 경고를 생성합니다.

AOT(Ahead-of-Time) 컴파일

자바 9에서는 Graal 컴파일러를 활용하는 실험적인 기능으로 AOT(ahead-of-time) 컴파일이 도입되었습니다. 자바 10에서는 JVMCI 인터페이스를 통합하여 Graal 컴파일러를 OpenJDK의 JIT 컴파일러로 사용할 수 있게 했습니다. 이후 Graal 컴파일러는 크게 발전하여 현재는 GraalVM이라는 이름으로 JVM 자체를 포함하고 있습니다.

RMI 활성화 기능 제거

RMI 활성화 기능은 JEP 407 에 따라 제거되었습니다. 이 기능은 자바 8에서 이미 사용 중단되었으며, 자바 15에서 최종적으로 제거될 예정이었습니다. RMI 활성화는 RMI를 사용하여 분산 객체의 온디맨드 리소스를 활성화하는 방법을 제공했지만, 사용률이 낮았고 현재 더 나은 대안들이 존재합니다. RMI의 나머지 부분은 활성화 기능 제거의 영향을 받지 않습니다.

애플릿 API 제거

애플릿 API 또한 최종적으로 제거되었습니다. JEP 398 에 따라, 자바 9에서 이미 제거되었어야 했지만, 이 API는 자바 AWT/Swing 컨트롤을 웹 페이지에 통합하는 데 사용되었지만, 현재 대부분의 브라우저에서 지원되지 않으므로 지난 10년 동안 실질적으로 사용되지 않았습니다.

보안 관리자 사용 중단

가장 중요한 변화 중 하나는 보안 관리자의 사용 중단입니다( JEP 411 ). 자바 1.0부터 사용된 보안 관리자는 네트워크, 파일 등 시스템 자원에 대한 접근을 제한하여 Java가 시스템에서 수행할 수 있는 작업을 제어하고, 리플렉션이나 특정 API를 차단하여 신뢰할 수 없는 코드를 샌드박스 처리하는 데 사용되었습니다.

보안 관리자의 사용 중단은 자바 12에서 시작되었으며, 런타임 시에 보안 관리자의 사용을 차단하는 명령줄 인자가 추가되었습니다. 자바 17에서는 명령줄에서 또는 런타임에 동적으로 보안 관리자를 설정하려고 하면 JVM이 런타임 경고를 생성합니다.

인큐베이터 및 미리보기 기능

자바 17이 장기 지원 버전으로 승격되었기 때문에, 많은 사람들이 자바 17에 미리보기 및 인큐베이터 기능이 있는지 궁금해했습니다. 자바 17은 실제로 두 개의 인큐베이터 모듈과 한 개의 미리보기 기능을 제공합니다.

벡터 API

벡터 API( JEP 414 )는 현재 인큐베이터의 두 번째 단계에 있습니다. 이 API를 통해 개발자들은 JIT 컴파일러가 JVM이 실행되는 CPU 아키텍처에서 지원하는 적절한 벡터 명령으로 변환할 수 있는 벡터 연산을 정의할 수 있습니다(예: SSE 또는 AVX 명령 집합 사용).

이전에는 개발자들이 스칼라 함수를 사용하거나 플랫폼별 네이티브 라이브러리를 직접 개발해야 했지만, 자바에서 Vector API를 구현함으로써 더욱 간단하게 폴백 메커니즘을 제공할 수 있습니다. Vector API의 표준화는 JDK 내부 클래스에서도 사용할 수 있게 되며, 자바 배열 불일치(mismatch) 메소드를 자바 내에서 실행되도록 변경하여 여러 플랫폼별 구현을 유지 관리해야 하는 번거로움을 줄일 수 있습니다.

외부 함수 및 메모리 API

또 다른 인큐베이터 기능은 외부 함수 및 메모리 API( JEP 412 )입니다. 이는 자바 16의 두 개의 인큐베이터 모듈, 외부 링커 API( JEP 389 ) 및 외부 메모리 API( JEP 393 )를 결합한 것입니다. 이 API는 자바로 작성된 정적 형식 프로그래밍을 사용하여 네이티브 메모리 및 코드에 대한 접근을 제공합니다.

스위치 표현식의 패턴 매칭

자바 17에 포함된 미리보기 언어 기능은 스위치 표현식의 패턴 매칭입니다( JEP 406 ). 이 기능은 패턴 매칭을 통해 사용되는 구문과 유사하게, 유형을 기반으로 스위치 표현식과 구문을 확장합니다. JEP 394에 따라 자바 16에서 표준 기능으로 도입된 패턴 매칭이 그 기반이 되었습니다.

이전에는 객체의 동적 특성에 따라 다른 작업을 수행하기 위해 다음과 같이 `if-else` 체인을 구성해야 했습니다.

String type(Object o) {
  if (o instanceof List) {
    return "리스트입니다.";
  }
  else if (o instanceof Map) {
    return "맵입니다. 키와 값이 있습니다.";
  }
  else if (o instanceof String) {
    return "문자열입니다.";
  }
  else {
    return "다른 어떤 것입니다.";
  }
}

새로운 패턴 매칭 기능을 사용하면 스위치 표현식을 다음과 같이 더 간결하게 작성할 수 있습니다.

String type(Object o) {
  return switch (o) {
    case List l -> "리스트입니다.";
    case Map m -> "맵입니다. 키와 값이 있습니다.";
    case String s -> "문자열입니다.";
    default -> "다른 어떤 것입니다.";
  };
}

보시다시피, 타입 확인 과정에서 변수 선언이 이루어집니다. 패턴의 다른 변수와 마찬가지로 인스턴스 일치는 해당 객체가 타입 검사를 통과했으며, 캐스팅되어 현재 범위의 변수에서 사용될 수 있음을 나타냅니다.

이 미리보기 기능은 패턴 매칭을 향한 또 다른 단계이며, 다음 단계는 배열과 레코드를 분해하는 기능을 포함할 것입니다.

자바 17으로 업그레이드해야 할까요?

네, 최신 버전으로 지속적으로 업그레이드하는 것이 좋지만, 출시 첫날부터 바로 업그레이드를 서두를 필요는 없습니다. 사용 중인 소프트웨어나 라이브러리가 자바 17과의 호환성을 확보하기까지 시간이 걸릴 수 있으므로, 안정화될 때까지 기다리는 것이 현명할 수 있습니다.

자바 8 또는 자바 11과 같은 LTS 버전의 자바를 사용하고 있다면 자바 17로 업그레이드할 만한 충분한 이유가 있습니다. 자바 17은 언어 자체 및 JVM 내부에 다양한 개선사항을 제공하며, 장기 유지 관리 릴리스이기 때문에 프로덕션 환경에서도 결국 자바 17로 업데이트될 가능성이 높습니다.

새로운 프로젝트를 시작하거나 자바 17로의 전환을 준비하고 있다면, 이전 버전과의 호환성 문제나 기술 부채를 줄일 수 있기 때문에 자바 17로의 빠른 전환이 가장 효율적인 선택일 것입니다. 이를 통해 개발자들은 최신 기능과 개선된 성능을 최대한 활용할 수 있습니다.

또한 컨테이너 환경에서의 향상된 지원과 지연 시간이 짧은 새로운 가비지 컬렉터 구현 등, 지난 몇 년간 자바 플랫폼에서 이루어진 다양한 개선사항들을 활용할 수 있습니다.

저자
Korea

기술 트렌드와 실용적인 팁을 전하는 लेखक입니다.