will come true

[Kotlin] Kotlin 코드와 Java 코드 본문

Kotlin

[Kotlin] Kotlin 코드와 Java 코드

haehyun 2023. 5. 18. 01:05

코틀린

코틀린은 결국 최종적으로는 자바 언어로 변환되어서 JVM에 의해 실행되지만, 코틀린에는 자바에서 지원하지 않는 기법을 제공한다. 그렇기 때문에 자바보다 간결하고 편하게, 좀 더 직관적으로 코드를 작성할 수 있다.
코틀린은 자바와 전혀 다른 언어가 아니며, 자바 코드를 편하게 쓰기 위한 확장 언어라고 생각하면 된다.

  • 자바로 안드로이드 앱을 개발할 수 있다.
  • 코틀린은 자바의 가상머신인 JVM에 기반을 둔 언어이다. 즉, 코틀린으로 작성한 프로그램은 JVM에서 실행할 수 있다.
  • 개발자는 코틀린으로 코드를 작성해도, 코틀린 컴파일러(kotlinc)가 .kt 파일을 컴파일하면 자바 클래스가 만들어지고 이를 JVM이 실행한다.
  • 코틀린은 안드로이드 앱 개발자가 많이 사용하지만 iOS앱, 서버쪽 애플리케이션도 개발할 수 있다. 대표적으론 스프링 프레임워크를 이용해 백엔드 웹 애플리케이션도 코틀린으로 개발할 수 있다. 코틀린도 단순히 언어일 뿐. 또한 근본은 결국 자바여서 (스프링 프레임워크와 같이)자바가 자주 사용되는 분야를 대체할 수 있다.

 

코틀린 특징

  • 간결한 코드
  • 널 안전성(Null Safety)
    • 객체 지향 프로그래밍에서 객체는 null 상태일 수 있으며, 이때 텅빈 객체를 참조하게 되면 런타임 오류인 NullPointException이 발생할 수 있다. 이 예외의 난감한 점은 런타임 오류기 때문에 실제로 코드를 실행(Run)해봐야 발견할 수 있다는 점이다. 따라서 개발자는 자체적으로 if문 등을 사용해 객체가 null인 상황을 고려해 개발해야 하는데, 코틀린에서는 변수를 널 허용(nullable) / 널 불허용(not null)으로 구분해서 선언할 수 있다.
    • 이로써 널과 관련된 여러 부분을 컴파일러가 해결해줘 코드 실행전에도 오류를 잡아낼 수 있으므로 코드에서 널 안정성(null safety)을 확보할 수 있는 것이다.
      널 참조 문제를 알아서 해결해준다는 건 아니고, 이를 사전에 방지할 수 있도록 좀 더 직관적으로 오류를 확인할 수 있도록 개발자를 도와줌.
  • 상호 운용성(interoperable)
    • interoperable : 상호 정보 교환이 가능한
    • 코틀린은 자바와 100% 호환됨 코틀린에서 자바 클래스와 라이브러리를 자유롭게 활용할 수 있으며 자바에서도 코틀린 클래스를 이용할 수 있다.(코틀린 코드에서 java 패키지를 import할 수 있다) 결국 최종 산출물은 자바 바이트 코드기 때문에 자바, 코틀린을 하나의 코드에 혼용해서 사용할 수도 있다.
    • → IntelliJ에 자바 코드를 붙여넣으면 자동으로 코틀린으로 변환됨.
      → 이미 자바로 개발한 앱을 유지보수할 때 추가 코드만 코틀린으로 작성할 수 있다.
  • 구조화 동시성(structured concurrency) ⭐
    • concurrency : 동시 실행
    • 코틀린 언어가 제공하는 코루틴(coroutine) 기법을 이용해서 비동기 프로그래밍을 간소화할 수 있다. 간소화한다는 건 프로그램을 좀 더 간단하게, 효율적으로 작성할 수 있단 뜻이다.
    • → 네트워크 연동, 데이터베이스 갱신과 같은 작업 구현시 이용

 

코틀린 파일 구성

  • package 구문
    • 이 파일을 컴파일했을 때 만들어지는 클래스 파일의 위치를 나타내며 소스 파일에서 맨 처음 한 줄로 선언한다.
    • package com.test.main : .kt 파일이 com/test/main 폴더에 생성된다.
    • import 문 바로 아래(최상위)에 변수, 함수, 클래스를 선언할 수 있다.
      (자바에서는 최상위에 클래스만 선언할 수 있다.)
    • 변수, 함수는 클래스 안뿐 아니라 클래스 밖(최상위)에도 선언할 수 있다.
      ⇒ 이 경우 자바 파일에선 static 멤버로 변환된다.
    • 같은 package로 선언한 멤버는 import문 없이 바로 참조할 수 있다.
  • 파일명과 클래스명을 다르게 선언해도 OK
    • 코틀린 파일명과 그 파일에 선언한 클래스명은 아무 상관이 없다. 코틀린이 객체지향만 지원하는 언어라면 모든 것이 클래스로 묶여야 하지만, 코틀린은 변수, 함수 등을 클래스로 묶지 않고 최상위(import문 아래)에 선언할 수 있으므로 파일명과 클래스명은 아무런 상관이 없다.
      ⇒ 물론 코틀린 파일이 컴파일러에 의해 자바 파일로 변환되면 최상위에 선언된 멤버들은 전부 ‘public final class 코틀린파일명Kt’ 클래스의 멤버로 포함된다.
    • 코틀린 파일을 컴파일하면 클래스는 각각의 클래스(.class) 파일로 만들어진다.
      User 클래스 선언 → User.class 파일 생성

 

코틀린 ↔ 자바 코드 호환 예시

1. [User.kt] 파일

import java.text.SimpleDateFormat
import java.util.Date

var data = 10

fun formatData(date: Date):String{
    val sdformat = SimpleDateFormat("yyyy-mm-dd")
    return sdformat.format(date)
}

class User {
    var name = "hello"

    fun sayHello(){
        println("name : $name")
    }
}

 

2. [User.decompiled.java] 파일

  • 자바는 클래스 단위로 작동하기 때문에 모든 코드가 하나의 클래스에 들어가 있다.
  • 코틀린 코드에서 선언된 클래스는 자바에서도 평범한 클래스 구조를 갖춘다.
  • 코틀린 코드에서 최상단(import문 아래)에 선언된 변수, 메서드는 자바에서 전부 static 으로 선언된다.
// import, metadata 등 생략

// User.kt - User 클래스 : 일반적인 클래스의 구조를 갖춤
public final class User {
   @NotNull
   private String name = "hello";

   @NotNull
   public final String getName() {
      return this.name;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   }

   public final void sayHello() {
      String var1 = "name : " + this.name;
      System.out.println(var1);
   }
}

// User.kt - 최상단 코드 : 전부 static 변수, 메서드로 선언됨
public final class UserKt {
   private static int data = 10;

   public static final int getData() {
      return data;
   }

   public static final void setData(int var0) {
      data = var0;
   }

   @NotNull
   public static final String formatData(@NotNull Date date) {
      Intrinsics.checkNotNullParameter(date, "date");
      SimpleDateFormat sdformat = new SimpleDateFormat("yyyy-mm-dd");
      String var10000 = sdformat.format(date);
      Intrinsics.checkNotNullExpressionValue(var10000, "sdformat.format(date)");
      return var10000;
   }
}

 

3. 자바 main 코드에서 코틀린 코드 사용
*굳이 코틀린과 자바를 혼합해서 사용하고 싶은 경우, 코틀린 컴파일 과정에서 생성된 UserKt.class 를 참조해서 사용할 수 있다.

public class TestJava {
	public static void main(String[] args) {
    	UserKt.setData(20);
        UserKt.formatData(new Date());
        User user = new User();
        user.sayHello();    
    }
}

 

코틀린 → 자바 코드 변환

자바 문법을 마스터한 뒤, 코틀린을 학습할 때, IntelliJ의 [Decomplie] 기능으로 자바 코드와 비교해가며 코딩하면 좀 더 수월하게 코틀린 문법을 익힐 수 있다.

1. [Tool] > [Kotlin] > [Show Kotlin Bytecode] 클릭

2. [Decomplie] 클릭
'Kotlin Bytecode' 창에서는 말 그대로 Kotlin을 JVM에서 실행시키기 위한 바이트코드가 표시된다.
Kotlin 코드를 컴파일 시키면 [Kotlin → Java → Bytecode]의 단계로 변환되기 때문에, Bytecode에서 디컴파일을 하면 결국 역순으로 Java 코드가 산출된다.

3. '.java' 확장자의 자바 파일로 변환된다.

 


개인 회고

자바 언어를 한참 쓰다가 코틀린을 경험하니까, 코틀린이 확실히 간결하고 편하다는 게 확 느껴진다.
일단 System.out.println() 이거 안쓰니까 속이 시원하긴 함. public static void main(String args[]) <- 메인 메서드 이렇게 길지도 않고 세미콜론 생략가능한 것도 너무 맘에 듬.

아무래도 자바가 제일 익숙하고 자료도 많아서 알고리즘 풀이시 자바를 사용해왔는데 슬슬 System.out.println 줄줄이 쓰다가 가끔 오타나는게 피곤해서(특히 코딩테스트 전용 에디터는 자동완성 기능이 없으니) 알고리즘 풀이 언어도 코틀린으로 완전히 갈아탈까 고민중이다.
이미 한 번 풀어본 문제들을 다시 자바로 푸는 것 보다는 코틀린으로 새롭게 푸는 게 나을 것 같기도 하고.

⭐ 표시 : 개인적으로 어렵다 느낀 / 다시 한 번 확인해봐야할 중요 개념들

Comments