Java와 Kotlin 차이

벼리·2023년 3월 15일

Android

목록 보기
1/2

안드로이드 개발자로서 Java와 Kotlin의 차이에 대해 알아보고자 한다.

💡 왜 Kotlin이라는 언어가 생겼을까?

📝Kotlin 등장배경

Kotlin은 어떻게 개발시장에서 자리를 잡았을까?

Kotlin은 JetBrains 젯브레인즈의 오픈소스 그룹에서 개발된 프로그래밍 언어이다.
2011년에 처음 공개되었으며 2017년에는 구글에서 안드로이드 공식 언어로 지정하며 유명해졌다.

🌎 Google에서는 왜 Kotlin을 공식 언어로 지정했을까?

여기에는 두가지 이유가 있다.

  • Java JDK 유료화 정책으로 인한 대체 언어
  • Kotlin은 다른 언어에는 가지고 있지 않은 다양한 장점

✅ Java JDK 유료화 정책

한때 전세계적으로 가장 많이 사용한 언어인 Java는 제임스 고슬링이 개발한 언어이다. 하지만 썬 마이크로시스템즈가 Oracle에 인수되면서 Oracle이 Java 언어를 주도하게 되었다.

그 후 Oracle은 특정 Java JDK에 대해 유료화 정책을 펼치게 되면서 Google은 난처한 입장에 처해지게 되었다. Google은 이미 Java JDK를 통해 안드로이드의 핵심 프레임워크와 여러 서비스를 개발한 상태이며, Oracle은 구글을 상대로 천문학적인 금액을 요청하였다.

Google은 Java 언어로 프로그램을 작성하기 위한 SDK인 Java JDK, JVM 등이 필요했다. 그래서 Google은 Oracle과의 분쟁을 피하고자 Java의 대체 언어인 Kotlin을 공식 언어로 채택하였다.


✅ Kotlin의 장점

그럼 Kotlin의 장점이 무엇이기에 Java에 이어 안드로이드 공식 언어가 되었을까?

  • 코틀린은 자바의 고질적인 문제였던 널(null) 안정성을 해결
  • 안드로이드 프로그래밍을 진행 시 Java 언어와 Kotlin 언어가 100% 호환
  • 함수를 변수에 저장하거나 함수를 매개변수로 전달하는 등 코틀린 언어에서는 함수형, 객체 지향 프로그래밍 모두 가능
  • 코틀린은 프로그램이 컴파일될 시 자료형을 검사하여 확정하는 정적 언어의 특성을 가지고 있어 오류를 초기에 발견할 수 있음

예시 코드를 통해 Kotlin의 장점을 좀 더 정확히 알아보자



📝Kotlin 특징


✅ Null 안정성

Java

Java는 기본적으로 모든 객체 변수를 nullable로 정의한다.
그렇기에, 개발자는 if나 try-catch로 null 검사를 해야한다.

public void execute() {
  User user = getUser("id");
  
  if (user.getName().equals("Zerobell") { // Can throw NullPointerException
    System.out.println("Yes, I'm Zerobell");
    return;
  }
}

다음 위의 자바 코드를 보자
user 혹은 user.getName()이 null을 return할 수 있기에 컴파일시 문제가 발생할 수 있다.


Kotliln

그렇다면 kotlin은 어떨까?
kotlin은 java와 달리 기본적으로 모든 객체 변수를 not null로 정의한다.그렇기에 불필요한 null 값들이 여기저기에 들어갈 여지를 어느 정도 차단해준다.

class User(
  val id: String,
  val name: String,
  val email: String? // nullable
)

fun execute() {
  val user = getUser("id")
  
  if (user.name == "Zerobell") {
    println("Yes, I'm Zerobell")
  }
  
  val domain = user.email?.split("@")[1] ? : ""
  if (domain == "gmail.com") {
    println("I'm using Gmail!"
  }
}

위의 코드를 보자
id와 name은 not nullable 이고 email은 String? 으로 정의되어 있어 nullable 라는 의미이다. Java에서는 반강제적으로 모든 property에서 해줘야 했던 검증을, Kotlin에서는 오로지 nullable로 선언된 property에만 적용해도 된다.

검증해야하는 양도 줄어들고, 어떤 것을 검증해야할지 ? 를 통해 알 수 있으니 Java 보다는 훨씬 통제하기 쉽다.

또한, elvis(:?) 연산자로, null 값에 대한 기본값(default value)을 지정해줄 수 있다. user의 email이 null이 나올 경우, ""로 치환된다.


✅ type 추론

fun getValue(): String {
    return "Hello!"
}

fun execute() {
    val value = getValue()
    println(value.replace("!", "?"))
}

execute() // print "Hello?"

Java와는 달리, var과 val 키워드를 사용해 알아서 타입을 추론하여 변수의 타입을 정할 수 있다. 위 코드에서 value는 String임을 명시하지 않았음에도, getValue의 return type이 String이기에 자동으로 String 변수로 인식되었다.

✅ Getter/Setter 생성

class User(
    val id: String, //getter only
    var name: String, //getter/setter
    var info: UserInfo
)

data class UserInfo( // generates equals(), hashCode() automatically
    val height: Double,
    val weight: Double
)

fun execute() {
    val user = getUser("id")
    println("user id is ${user.id}")
    user.id = "id2" // Blocked by compiler
    user.name = "zerobell" // equals user.setName("zerobell")
    
    val goodInfo = UserInfo(185.0, 65.0)
    if (goodInfo == user.userInfo) { // 
        println("He is 185 cm tall and weighs 65kg. Good!")
    }
}

자바에서는 Lombok을 이용해 getter/setter을 작성하는 경우가 많다.
그러나 kotlin에서는 객체 프로퍼티에 대하여 val이 선언되어 있을 경우 getter를, var가 선언되어 있다면 getter/setter를 자동 생성해준다. 즉, 위 코드에서 16번째 줄인 user.name = "zerobell"은 Java 코드에선 user.setName("zerobell")로 변환된다.

여기에 더해 Data Class를 활용한다면, getter/setter 외에 equals와 hashCode까지 자동으로 생성해준다. 19번째 줄은 Data Class끼리 동등성(equality) 비교를 하고 있다.(자바와 달리 코틀린에선 == 연산자는 곧 equals() 호출과 같다) 그렇기에 height와 weight 모두가 동일한 값이라면, 저 비교문은 true가 된다.

즉, 코틀린에서는 롬복을 쓸 이유가 전혀 없다. @Getter @Setter @Data 등의 어노테이션이 이미 코틀린 언어 자체에 내장되어 있으니!!!

✅ 비동기 처리 용이

자바의 고질병 중 하나는 "비동기 처리가 아쉽다"는 점이었습니다. Future를 거쳐 CompletableFuture를 제공해줬으나, 자바를 통해 서비스를 개발하는 개발자들 대부분은 CompletableFuture를 직접 활용하기 보단 RxJava 같은 Reactive Streaming 프레임워크를 사용해왔습니다. 그러나 리액티브 프로그래밍은 러닝 커브가 높다는 단점이 있었습니다.

코틀린은 이에 대한 대안으로 코루틴(coroutine)을 제시합니다. 코루틴은 기존의 코드들과 동일하게 절차적으로 코드를 작성하면서도 비동기 처리를 할 수 있도록 하는 또 하나의 패러다임입니다. 코루틴은 기존의 Reactive Streaming과의 호환성도 고려하여 만들어졌으므로 RxJava/Reactor와도 함께 사용할 수 있으며, 특히나 이를 채택하고 있는 Spring Webflux와의 상성도 꽤나 좋습니다.




참고자료

https://juyeop.tistory.com/3
https://seolin.tistory.com/146

profile
코딩일기

0개의 댓글