JavaRush /Java Blog /Random-KO /커피 브레이크 #37. Java의 새로운 미래. 2020년 이후 JVM, Kotlin 및 Java 전망...

커피 브레이크 #37. Java의 새로운 미래. 2020년 이후 JVM, Kotlin 및 Java 전망

Random-KO 그룹에 게시되었습니다
출처: 중간 규모 Java는 주로 두 가지 이유로 비판을 받습니다. 즉, 많은 경우에 명백한 필요 없이 생성되는 상용구 코드의 양과 장황함입니다. 나는 항상 Java를 좋아했지만 이러한 진술이 틀렸다고 말할 수는 없습니다. 정말 사실입니다. Java의 과도한 세부사항은 때때로 매우 짜증스러울 수 있습니다. 그러나 우리는 이상적인 세상에 살고 있지 않으며, 대부분의 경우 두 가지 악 중 더 적은 것을 선택해야 한다는 점을 인정해야 합니다. 커피 브레이크 #37.  Java의 새로운 미래.  2020년 이후 JVM, Kotlin 및 Java 전망 - 1Java는 처음부터 완벽하지 않았습니다. 우리 모두 이것을 알고 있지만 실제 질문은 왜 이러한 문제를 해결하기 위해 이전에 아무 것도 수행되지 않았느냐입니다. 변경 사항이 그렇게 오래 걸린 유일한 이유는 Java 언어에 경쟁이 없었고 상황이 예전과 같았기 때문이라고 생각합니다. Java가 시장을 장악했는데, 이는 아마도 심각한 경쟁자가 부족하고 처음에는 Sun이, 그 다음에는 Oracle이 많은 노력을 기울였기 때문일 것입니다. Java가 제공하는 높은 수준의 유형 안전성과 언어의 우수한 구조로 인해 Java는 대규모 프로젝트에서 매우 인기가 높습니다. 또한 자체 가상 머신에서 실행되는 다중 플랫폼 언어입니다. JIT 컴파일러를 통한 자동 성능 최적화와 결합되어 이 모든 것이 잘못 작성된 코드의 영향을 최소화합니다. 전체적으로 보면 이는 Java를 사용해야 하는 매우 설득력 있는 이유입니다. 하지만 그 다음에 무슨 일이 일어났나요? Java와 동일한 JVM에서 실행될 수 있는 새로운 언어가 시장에 출시되었습니다. Java의 가장 큰 불편함을 일부 제거하고, 경우에 따라 진입 장벽을 낮추어 개발자에게 보다 쾌적한 환경을 제공하는 언어입니다. 계속하기 전에 JVM 언어의 역사를 간략하게 살펴보겠습니다.

JVM 언어의 역사

먼저, 한 가지를 분명히 하고 싶습니다. 기존 JVM 언어 중 일부는 우리 업계에서 널리 사용할 수 있는 후보로 간주될 만큼 충분한 지원을 받지 못했기 때문에 언급하지 않았습니다. 이제 JVM 언어의 역사에 대한 간략한 개요를 시작하겠습니다. 먼저 JVM 세계에서 가장 오래되고 가장 널리 사용되는 언어인 Java를 살펴보겠습니다. Java는 1996년 1월에 공식적으로 출시되었으므로 언어가 나온 지 24년이 되었습니다. 나쁘지 않죠? Java는 원래 객체 지향 프로그래밍 스타일을 따르는 순전히 명령형 언어였습니다. 또한 강력한 형식의 언어이기도 했습니다. Java의 구문은 C++ 및 C 언어와 다소 유사하지만 Java로 코드를 작성하는 것이 C나 C++보다 훨씬 쉽기 때문에 향상된 버전으로 간주됩니다. 반면에, 우리는 그를 비방하는 사람들 사이에서 가장 큰 논쟁을 벌이고 있습니다. 바로 장황함입니다. 두 번째 JVM 언어는 Groovy였습니다. 2003년부터 존재해왔지만 첫 번째 표준화 버전인 1.0은 2007년 1월에야 등장했습니다. Groovy의 장점은 스크립팅 언어로 사용할 수 있다는 것입니다. Groovy는 동적으로 유형이 지정되는 언어이므로 유형 검사는 런타임에 수행됩니다. 이것이 일부 개발자가 Groovy를 좋아하지 않는 이유 중 하나입니다. Groovy로 코드를 작성하면 컴파일 타임에는 올바르게 보이지만 런타임에는 뭔가 잘못되었음을 깨닫게 됩니다. 그런 다음 또 다른 인기 있는 언어가 나타났습니다. 바로 Scala에 대해 이야기하는 것입니다. 2004년에 출시되었습니다. 그는 함수형 프로그래밍과 선언적 접근 방식이라는 새로운 작업 모델을 JVM 세계에 도입했습니다. 기본적으로 Scala는 불변성 개념을 도입한 최초의 언어였으며 이후 Java를 향상시키는 데 사용되었습니다. 반면, 비방하는 사람들은 문법이 복잡하고 가독성이 낮기 때문에 Scala를 좋아하지 않습니다. JVM 세계에서 등장한 다음 언어는 순수 기능 언어인 Clojure였습니다. 2007년에 등장했지만 최근 꽤 인기를 끌고 있습니다. Clojure는 단순성과 간단한 기능을 사용하는 것이 특징인 LISP 기반 언어입니다. 단점 중 하나는 Groovy와 같이 동적으로 유형이 지정되고 구문이 다른 JVM 언어와 완전히 다르기 때문에 학습 곡선이 훨씬 가파르다는 것입니다. 마지막으로 Kotlin이 있습니다. Kotlin은 2016년 2월에 처음 등장한 이후로 인기가 계속 높아지고 있습니다. 가장 유명한 Java 문제를 해결하는 것을 주요 목표로 JetBrains에서 개발했습니다. 설계상 Kotlin은 Java의 모든 장점을 유지하면서도 동시에 많은 문제를 해결했습니다. 이는 가장 중요한 JVM 언어입니다. 내가 말했듯이 우리는 Jython, JRuby, Ceylon, Fantom 등 그다지 인기가 없는 다른 언어를 놓쳤습니다. 원하는 경우 기존 JVM 언어의 전체 목록을 찾을 수 있습니다.위키피디아에서. 아마도 Java가 만들어진 후 처음 8~10년 동안은 경쟁이 별로 없었다는 사실을 깨달았을 것입니다. 그러나 그 이후로 상황이 달라졌습니다. 그렇다면 경쟁은 좋은 것인가, 나쁜 것인가?

경쟁 증가의 이점

Java는 초기에는 크게 변하지 않았습니다. 아마도 그럴 필요가 없었기 때문일 것이다. 이 언어는 완벽하지 않음에도 불구하고 널리 사용되었으며 항상 인기가 높았습니다. 그러나 새로운 기능을 제공하고 오랫동안 Java 개발자를 괴롭혔던 일부 문제를 해결한 보다 현대적인 언어인 경쟁자가 등장했습니다. 예를 들어 Scala 언어를 살펴보겠습니다. 스칼라의 인기는 2009년부터 계속 높아지고 있습니다. 개발자들은 더 큰 유연성과 병렬 코드를 안전하고 쉽게 작성할 수 있는 기능을 제공하는 이 새로운 기능적 스타일을 환영했습니다. Oracle은 이러한 새로운 추세에 어떻게 대응했습니까? 2014년에는 Java Lambda와 Streams가 등장했습니다. 나는 이것이 Java가 Scala를 물리치기 위한 가장 큰 발걸음을 내딛은 때라는 점에 우리 모두 동의할 것이라고 생각합니다. 이제 모든 프로그래머는 Scala가 더 이상 유행하지 않는다는 것을 알고 있습니다. 커피 브레이크 #37.  Java의 새로운 미래.  2020년 이후 JVM, Kotlin 및 Java 전망 - 2JVM 세계에 더 많은 경쟁자가 있으면 또 다른 이점은 JIT 컴파일러와 JVM이 지속적으로 개선된다는 것입니다. 이제 훨씬 더 많은 사람들이 JVM 최적화 및 성능 향상에 관심을 갖고 있습니다. 그러니 경쟁은 누구에게나 좋은 것입니다! Java의 최신 대안은 Kotlin 언어입니다. 새로운 언어는 어떤 의미에서 Oracle이 앞으로 나아갈 길을 보여 주었기 때문에 Java 개발에 있어 그 모습은 매우 중요했습니다. Kotlin 예는 Java의 장점을 유지하면서도 코드 작성 속도가 더 빠른 보다 컴팩트한 언어를 만드는 것이 가능하다는 것을 보여주었습니다. 구글 트렌드 그래프를 보면 2016년부터 2018년까지 Kotlin의 인기가 급격히 높아진 것을 알 수 있습니다. 그러나 지난 2년 동안 그 기대감은 줄어들었습니다. 커피 브레이크 #37.  Java의 새로운 미래.  2020년 이후 JVM, Kotlin 및 Java 전망 - 3Oracle은 Kotlin에 대한 업계의 반응을 면밀히 조사했습니다. JDK 15 릴리스 노트를 보면 새로운 Java 기능 중 일부가 Kotlin에 포함된 기능의 복사본임을 알 수 있습니다. 이는 새로운 Java 항목 , 새로운 텍스트 블록(삼중 따옴표가 있는 여러 줄 문자열) 및 기본적으로 Kotlin switch연산자의 복사본인 new 연산자 입니다. when우리가 이야기한 모든 내용은 제가 "Java의 Kotlinization"이라고 부르는 것입니다. Kotlin은 더욱 강력한 경쟁자가 됨으로써 Java가 따라야 할 길을 보여주었습니다.

Java의 "Kotlinization"

앞으로 출시될 Java 기능 중 일부는 가독성 측면에서 크게 개선될 것이며 Java 언어의 가장 큰 약점 중 하나인 장황함을 해결할 것입니다. 발표된 Java 기능 중 상당수가 일부 Kotlin 기능과 의심스러울 정도로 유사하다고 주장할 수도 있습니다. 그러나 대부분은 시험판 버전 이라는 점에 유의하십시오 . 즉, JDK 14 또는 JDK 15(출시 시)를 설치하면 기본적으로 사용할 수 없습니다. Java 기능 미리보기는 릴리스에 도입되었지만 기본적으로 비활성화되어 있는 새로운 기능입니다. 개발자 커뮤니티의 피드백을 수집하기 위한 목적으로만 새 버전에 포함되었으므로 계속 변경될 수 있습니다. 그렇기 때문에 프로덕션 코드에서는 사용하지 않는 것이 좋습니다. 컴파일 타임에 이를 활성화하려면 다음을 수행해야 합니다.
javac --enable-preview --release 14
런타임에 활성화하려면 다음을 실행해야 합니다.
java --enable-preview YourClass
물론 IDE에서도 이를 활성화할 수 있지만 모든 새 프로젝트에서 기본적으로 미리보기를 활성화하지 않도록 주의하세요! 향후 Java 버전의 코딩에 더 큰 영향을 미칠 변경 사항을 살펴보겠습니다.

자바 게시물

Java Records는 우리 중 많은 사람들이 오랫동안 원해왔던 기능입니다. 나는 당신이 모든 기존 필드에 대해 toString , hashCode , equals 및 getter를 구현해야 하는 상황에 처해 있다고 생각합니다 . Kotlin에는 이 문제를 해결하기 위한 데이터 클래스가 있으며 Java는 Scala가 이미 가지고 있는 레코드 클래스를 케이스 클래스 형태로 출시하여 동일한 작업을 수행할 계획입니다 . 이러한 클래스의 주요 목적은 객체에 불변 데이터를 저장하는 것입니다. Java가 얼마나 더 좋아질 수 있는지 예를 들어 보겠습니다. 다음은 클래스를 생성하고 비교하기 위해 작성해야 하는 코드의 양입니다 Employee.
package com.theboreddev.java14;

import java.util.Objects;

public class Employee {
    private final String firstName;
    private final String surname;
    private final int age;
    private final Address address;
    private final double salary;

    public Employee(String firstName, String surname, int age, Address address, double salary) {
        this.firstName = firstName;
        this.surname = surname;
        this.age = age;
        this.address = address;
        this.salary = salary;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getSurname() {
        return surname;
    }

    public int getAge() {
        return age;
    }

    public Address getAddress() {
        return address;
    }

    public double getSalary() {
        return salary;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return age == employee.age &&
                Double.compare(employee.salary, salary) == 0 &&
                Objects.equals(firstName, employee.firstName) &&
                Objects.equals(surname, employee.surname) &&
                Objects.equals(address, employee.address);
    }

    @Override
    public int hashCode() {
        return Objects.hash(firstName, surname, age, address, salary);
    }

    @Override
    public String toString() {
        return "Employee{" +
                "firstName='" + firstName + '\'' +
                ", surname='" + surname + '\'' +
                ", age=" + age +
                ", address=" + address +
                ", salary=" + salary +
                '}';
    }
}
또한 Address여기에 포함된 개체는 다음과 같습니다.
import java.util.Objects;

public class Address {
    private final String firstLine;
    private final String secondLine;
    private final String postCode;

    public Address(String firstLine, String secondLine, String postCode) {
        this.firstLine = firstLine;
        this.secondLine = secondLine;
        this.postCode = postCode;
    }

    public String getFirstLine() {
        return firstLine;
    }

    public String getSecondLine() {
        return secondLine;
    }

    public String getPostCode() {
        return postCode;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Address address = (Address) o;
        return Objects.equals(firstLine, address.firstLine) &&
                Objects.equals(secondLine, address.secondLine) &&
                Objects.equals(postCode, address.postCode);
    }

    @Override
    public int hashCode() {
        return Objects.hash(firstLine, secondLine, postCode);
    }

    @Override
    public String toString() {
        return "Address{" +
                "firstLine='" + firstLine + '\'' +
                ", secondLine='" + secondLine + '\'' +
                ", postCode='" + postCode + '\'' +
                '}';
    }
}
이렇게 간단한 작업에는 코드가 너무 많을 것입니다. 그렇죠? 이제 이것이 새로운 Java 항목에서 어떻게 보이는지 살펴보겠습니다.
public record EmployeeRecord(String firstName, String surname, int age, AddressRecord address, double salary) {
}
그리고 Address 클래스도 잊지 마세요.
public record AddressRecord(String firstLine, String secondLine, String postCode) {
}
이것은 우리가 이전에 너무 많은 코드로 작성한 것과 동일합니다. 동의하세요: 정말 놀랍습니다. 그리고 우리가 절약할 코드의 양과 작성의 용이성! 이제 new 연산자와의 차이점을 살펴보겠습니다 switch.

향상된 연산자switch

Java의 새로운 연산자는 switch일부 버그 및 코드 중복을 포함하여 일부 기존 문제를 해결합니다. 새로운 연산자를 사용하면 switch이 문제가 해결될 것입니다. DayOfTheWeek이를 예를 들어 설명하기 위해 Java에서 열거형을 생성하겠습니다 .
public enum DayOfTheWeek {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}
그 후, 우리 switch는 해당 주의 어느 위치가 해당 날짜에 해당하는지 알려줄 것입니다. 먼저 현재 Java 11을 사용하여 이 작업을 수행할 수 있는 방법을 살펴보겠습니다.
final DayOfTheWeek dayOfTheWeek = DayOfTheWeek.THURSDAY;

        int position = 0;

        switch (dayOfTheWeek) {
            case MONDAY:
                position = 1;
                break;
            case TUESDAY:
                position = 2;
                break;
            case WEDNESDAY:
                position = 3;
                break;
            case THURSDAY:
                position = 4;
                break;
            case FRIDAY:
                position = 5;
                break;
            case SATURDAY:
                position = 6;
                break;
            case SUNDAY:
                position = 7;
                break;
        }

        System.out.println("Day " + dayOfTheWeek + " is in position " + position + " of the week");
현재 명령문에서는 switch변수를 사용해야 하며, 요일 중 하나를 놓치면 코드가 정상적으로 컴파일됩니다. 이것은 연산자의 문제 중 하나입니다 switch. 오류가 발생하기 쉽습니다. 그렇다면 Java 14는 어떻게 상황을 개선할까요? 살펴보자:
final DayOfTheWeek dayOfTheWeek = DayOfTheWeek.THURSDAY;

        int position = switch (dayOfTheWeek) {
            case MONDAY -> 1;
            case TUESDAY -> 2;
            case WEDNESDAY -> 3;
            case THURSDAY -> 4;
            case FRIDAY -> 5;
            case SATURDAY -> 6;
            case SUNDAY -> 7;
        };

        System.out.println("Day " + dayOfTheWeek + " is in position " + position + " of the week");
보시다시피, 새 연산자는 switch명령문뿐만 아니라 표현식으로도 사용할 수 있습니다. 결과는 더욱 간결하고 표현력이 풍부해졌습니다. switch이것은 우리 중 많은 사람들이 이를 사용하도록 설득하기 에 충분하지만 주요 개선 사항 중 하나는 이제 switch. 예를 들어 다음과 같은 오류가 표시됩니다.
Error:(9, 24) java: the switch expression does not cover all possible input values
이제부터는 연산자에서 대소문자를 건너뛰는 것이 불가능합니다 switch. 이는 문서when 에서 읽을 수 있는 Kotlin의 연산자와 매우 유사합니다 . 새로운 텍스트 블록도 살펴보겠습니다.

텍스트 블록

Java에서 JSON blob을 변수에 할당하는 것이 얼마나 어렵다고 불평한 적이 있습니까? Java에는 삼중따옴표로 묶어 설명할 수 있는 여러 줄 시퀀스가 ​​있습니다. 이 기능이 공식적으로 출시되면 여러 줄에 걸쳐 긴 시퀀스를 설명하는 것이 훨씬 쉬워질 것입니다. 두 모드의 차이점을 살펴보겠습니다. 변수에 형식화된 JSON을 사용하려는 경우 결과가 좋지 않습니다.
final String text = "{\"widget\": {\n" +
                "    \"debug\": \"on\",\n" +
                "    \"window\": {\n" +
                "        \"title\": \"Sample Konfabulator Widget\",\n" +
                "        \"name\": \"main_window\",\n" +
                "        \"width\": 500,\n" +
                "        \"height\": 500\n" +
                "    },\n" +
                "    \"image\": { \n" +
                "        \"src\": \"Images/Sun.png\",\n" +
                "        \"name\": \"sun1\",\n" +
                "        \"hOffset\": 250,\n" +
                "        \"vOffset\": 250,\n" +
                "        \"alignment\": \"center\"\n" +
                "    },\n" +
                "    \"text\": {\n" +
                "        \"data\": \"Click Here\",\n" +
                "        \"size\": 36,\n" +
                "        \"style\": \"bold\",\n" +
                "        \"name\": \"text1\",\n" +
                "        \"hOffset\": 250,\n" +
                "        \"vOffset\": 100,\n" +
                "        \"alignment\": \"center\",\n" +
                "        \"onMouseUp\": \"sun1.opacity = (sun1.opacity / 100) * 90;\"\n" +
                "    }\n" +
                "}} ";
반면에 새 텍스트 블록이 출시되면 모든 것이 훨씬 더 단순해집니다.
final String multiLineText = """
                {"widget": {
                    "debug": "on",
                    "window": {
                        "title": "Sample Konfabulator Widget",
                        "name": "main_window",
                        "width": 500,
                        "height": 500
                    },
                    "image": {\s
                        "src": "Images/Sun.png",
                        "name": "sun1",
                        "hOffset": 250,
                        "vOffset": 250,
                        "alignment": "center"
                    },
                    "text": {
                        "data": "Click Here",
                        "size": 36,
                        "style": "bold",
                        "name": "text1",
                        "hOffset": 250,
                        "vOffset": 100,
                        "alignment": "center",
                        "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
                    }
                }}
                """;
확실히 이게 더 좋아 보이네요. 유형 정의 에서 볼 수 있듯이 이 모든 것은 이미 Kotlin에서 지원됩니다 . 따라서 우리는 Java가 경쟁사 중 하나인 Kotlin으로부터 자체 문제에 대한 많은 솔루션을 "상속"한다는 것을 확인했습니다. Oracle이 Kotlin의 부상에 맞서기 위해 적시에 대응했는지, 아니면 너무 늦게 대응했는지는 알 수 없습니다. 개인적으로 저는 이러한 변화가 경쟁사에 의해 시작되어 약간의 지연이 있을 수 있다고 하더라도 Java가 올바른 진전을 이루고 있다고 믿습니다.

결론

나는 경쟁이 Java 언어에 일어난 최고의 일이라고 생각합니다. 내 생각에는 그렇지 않으면 Java가 그 명예에 안주할 것입니다. 또한 Java의 경쟁업체들은 다른 프로그래밍 방식이 가능하다는 사실을 보여주면서, 구식이고 비효율적인 코드 작성 방식을 피하고 발전하는 방법을 보여주었습니다. 미래의 변화는 Java를 그 어느 때보다 강력하게 만들고, 현대 시대에 적합한 언어, 진화를 원하는 언어로 만들 것입니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION