본문 바로가기

카테고리 없음

언어 정리 - 코틀린(Kotlin), 코루틴(Coroutine)과 NullSafety,Multiplatform 그리고 동시성

1.  배경 - 근래에 Memory Manged Language인 c++를 공부하면서 각 언어마다의 특징에 대해서 찾아보는 게 재밌어져서  메타(전신 페이스북)의 내부소스 대량 코틀린 전환 Article을[각주:1][각주:2]읽고 코틀린으로까지 시선이 옮아져갔다. 

 

2. 개요 - 코틀린[각주:3]특징은 크게 간결하면서도 오버헤드없는 문법, 그리고 널안정성(Null Safety)이다.   

그리고 1.3v에 비동기를 위해 추가된 기능인 코루틴(Coroutine)이다.  그 이전에도 Go의 특징으로 자주 접한 용어이다. 

 

3. 특징

3.1. Null Safety 

컴파일 시점에 nullable and not-nullable types을 구별한다. 이것은 널값으로 인한 런타임 에러를 사전에 방지한다. 

nullable인경우 ?를 뒤에 붙여 표기한다.

fun main(args: Array<String>) {
    sayHello(null, 3) //>>Hello strager
    sayHello("apple", 3) //>>Hello apple
}

fun sayHello(maybe: String?, neverNull: Int) {
    // use of elvis operator
    val name: String = maybe ?: "stranger"
    println("Hello $name")
}

이렇게 언어 차원에서 지원하기에 자바로 하면 복잡해질 표현을 간결하게 표현할 수 있다. (또는 추가적인 라이브러리 의존을 덜어준다.)

가장 많은 빈도를 보이는 에러인 NPE를 이렇게 간단한 문법으로 막는다는 이점. 이것이 코틀린의 매력 중 하나일 것이다. 

이것과 동일 바이트코드를 만들려면 자바에서는 다음과 같이 소스를 작성해야 한다. (클래스파일을 역컴파일했다.) 

import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

@Metadata(mv = {1, 5, 1}, k = 2, xi = 48, d1 = {"\000\032\n\000\n\002\020\002\n\000\n\002\020\021\n\002\020\016\n\002\b\004\n\002\020\b\n\000\032\031\020\000\032\0020\0012\f\020\002\032\b\022\004\022\0020\0040\003\006\002\020\005\032\030\020\006\032\0020\0012\b\020\007\032\004\030\0010\0042\006\020\b\032\0020\t\006\n"}, d2 = {"main", "", "args", "", "", "([Ljava/lang/String;)V", "sayHello", "maybe", "neverNull", "", "kotlin_project_initial_todelete"})
public final class Test {
  public static final void main(@NotNull String[] args) {
    Intrinsics.checkNotNullParameter(args, "args");
    sayHello(null, 3);
  }
  
  public static final void sayHello(@Nullable String maybe, int neverNull) {
    String str1 = maybe, name = (str1 == null) ? "stranger" : str1;
    str1 = Intrinsics.stringPlus("Hello ", name);
    boolean bool = false;
    System.out.println(str1);
  }
}

 

public static String stringPlus(String self, Object other) {
  return self + other;
} //import kotlin.jvm.internal.Intrinsics;
public static void checkNotNullParameter(Object value, String paramName) {
     if (value == null) {
         throwParameterIsNullNPE(paramName);
     }
}

3.2. 코루틴 (since v1.3, v1.1부터 별도라이브러리를 통해 구현은 가능)과 동시성

Coroutines are computer program components that generalize subroutines for non-preemptive multitasking, by allowing execution to be suspended and resumed.[각주:4]

 

프로그래밍 레벨
Channel, Coroutine, Futures and promises
OS레벨
멀티태스킹,프로세스,스레드

 

 

1960년대부터 어셈블리어에서 쓰인던 방법인데, 현재는 많은 고급언어에서 기본으로 지원하기도 하고 (Kollin,c#2.0, c++20, go, haskell, ECMAScript 6의 yield, ECMAScript 7의 await, php5.5, Python2.5,  Ruby , Rust1.39 등) , 별도 라이브러리(Java)를 통해 구현가능한 일반적인 방법이 되었다. 

 

코루틴을 쉽게 이해하면 경량스레드라고 볼 수 있다. 

 

쓰레드의 생성비용은 수반되는 작업들이 있기에 비싸다. (Green Thread언급됨)

1. A large block of memory has to be allocated and initialized for the thread stack.
2. System calls need to be made to create / register the native thread with the host OS.
3. Descriptors need to be created, initialized and added to JVM-internal data structures.
Green Thread란?
자바에서 시작되었다. Java는 1.1부터 Green Thread(user-level 쓰레드로 OS가 아닌 가상머신이나 런타임 라이브러리에 의해 만들어진 쓰레드. cpu 코어 한개만 이용할 수 있어서 네이티브 쓰레드는 단 한개만 만들어짐. 따라서 멀티코어에서는 비적합)를 만들었지만,  Java3부터 멀티쓰레딩은 네이티브 쓰레드를 생성하는 쪽으로 바뀌었다. 
여전히 다른 많은 언어에서 지원하고 있다. 

 

 

 

함수는 진입점과 출구점(return)이 한개씩이지만 코루틴이라는 개념은 진입점을 여러개로 만들 수 있는 역할을 한다. 

 

3.2.1 비선점 멀티태스킹(non-preemptive multitasking, also know as Cooperative multitasking )

운영체제가 절대로 프로세스에서 프로세스간으로 Context Switching을 하지 않는 컴퓨터 멀티태스킹 스타일이다.

대신에 processes voluntarily yield control periodically or when idle or logically blockedThis type of multitasking is called cooperative because all programs must cooperate for the scheduling scheme to work.

In this scheme, the process scheduler of an operating system is known as a cooperative scheduler whose role is limited to starting the processes and letting them return control back to it voluntarily.[1][2]

 

 

3.2.2 Context Switching과 Thread

3.2.3. 멀티쓰레딩과 동기화,교착 문제  

 

3.3 . 크로스플랫폼

코틀린은 JVM위에서만 돌아갈 것이라 생각하기 쉬운데, JVM은 타겟 중 하나일 뿐이며 ,이미 여러 플랫폼 위에서 돌아간다. (1.7기준)

  • JVM (Java Virtual Machine)
  • JS (JavaScript)
  • Native (native binaries for various architectures)

3.4.  gradual and flow typing

타입스크립트에서 적용된 것과 유사하다.

gradual typing - 코틀린은 자바처럼 기본적으로 정적타입(at compile)이지만 동적타입(at runtime)의 요소를 많이 가져와서 다른언어들과의 상호운영성을 증대시켰다.

flow typing - 제어흐름에 따라 타입이 결정되는 Type

 

3.5 . 객체지향+함수형의 요소 

객체지향 -  generic(mixed-site variance를 사용해서 구현)을 지원하는 nominal subtyping(자바와 c언어처럼  이름이 다를 경우 다른 타입으로 연산한다.)

함수형 - 고차함수와 람다리터럴(lambda literals)를 위해  일급객체(first-class)를 지원한다. 

 

4. 자바와의 비교

 

  Original purpose Imperative Object-oriented Functional Procedural Generic Reflective Event-driven Other paradigms Standardized?
Java Application, business, client-side, general, mobile development, server-side, web Yes Yes Yes Yes Yes Yes Yes Concurrent De facto standard via Java Language Specification

Kotli
n
Application, mobile development, server-side, client-side, web Yes Yes Yes Yes Yes Yes[29] Yes x De facto standard via Kotlin Language Specification[각주:5]