(kotlin) 001. What is kotlin?

What is kotlin?

koltin은 Java Platform을 대상으로 하는 새로운 프로그래밍 언어이다.

java 코드와의 상호 운용이 가능하며, 간결하고 안전하며 또 실용적인 특징을 가지고 있다.

특히 java 코드와의 상호 운용이 가능하므로 java가 주로 사용되는 서버사이드의 개발은 물론 Android 앱을 개발하는 등 거의 모든 곳에서 사용할 수 있다.

kotlin은 모든 java 기반의 라이브러리 및 프레임워크에서 잘 동작하며, 동일한 수준의 성능을 보인다.

kotlin의 특징

kotlin의 특징에 대해서 알아보자.

1. 다양한 플랫폼에서의 동작

kotlin은 현재 java가 사용되는 모든 용도에 적용가능하면서도, 더욱 간결하고 생산적이며 안전한 언어를 제공하는 게 목적인 언어이다.

특히 한국에서는 백엔드 영역에서 java가 많이 쓰이는 만큼 kotlin의 사용처도 넓다고 할 수 있을 것이다.

반대로 클라이언트인 Android의 경우 java를 주언어로 개발하는만큼 완벽하게 kotlin으로 대체가 가능하다.

좀 더 상세한 예시로는 아래와 같은 것들이 있다.

Intell Multi-OS Engine을 통해 iOS에서도 kotlin을 실행시킬 수 있다.

TornadoFX, javaFX를 통해 데스크톱 애플리케이션을 개발할 수 있다.

kotlin 1.1부터는 javascript도 지원하여, 브라우저에서도 실행시킬 수 있다.

이처럼 kotlin이라는 언어는 특정 영역의 문제를 해결하기 위해서라기보단,

개발 언어 자체가 해결할 수 있는 모든 종류의 일에 대해 광범위하게 생산성을 높여주는 역할을 한다.

2. 정적 타입 지정 언어

kotlin은 java를 대체할 수 있는 것처럼, java와 동일한 특징인 정적 타입(statically typed) 지정 언어이기도 하다.

정적 타입 이란 모든 프로그램 구성 요소의 타입을 컴파일 시점에 알 수 있으며, 객체안에서 필드나 메서드를 사용할때마다 컴파일러가 타입을 검증할 수 있음을 뜻한다.

정적 타입의 자세한 특징과 이에 대비되는 용어인 동적 타입은 아래 포스팅을 참고하자.

참고 정적 타입과 동적 타입

컴파일러가 타입을 특정하게 해주기 위해 모든 구성 요소를 명시해야할 것처럼 느껴지지만, kotlin은 매우 높은 추론 능력으로 구성 요소의 타입을 판정해낸다.

예를 들어

1
var x = 1

위의 코드에서 kotlin의 컴파일러는 변수 xInt 타입임을 추론해낸다.

이처럼 컴파일러가 문맥을 읽어 변수 타입을 결정하는 것을 타입 추론(type inference) 라고 부른다.

kotlin의 이 강력한 타입 추론 능력을 바탕으로 개발자가 직접 타입을 지정해야하는 불편함이 많이 해소되었다.

또한 kotlin을 활용하다보면 class, interface, generic 등의 친숙한 개념을 발견할 수 있어서, java와 똑같은가? 하는 생각이 들 수도 있지만, 몇 가지 다른 점이 존재한다.

가장 중요한 특징은 kotlin이 Nullable type 을 지원한다는 것인데, 컴파일러가 Null이 될 수 있는 타입이냐 아니냐에 따라 jvm에서 가장 위험하다고 할 수 있는 NullPointerException에 대한 검사를 수행해준다.

3. 함수형 프로그래밍

kotlin은 Funtion type 에 대해서도 지원하고 있다.

이를 이해하기 위해선 함수형 프로그래밍의 개념에 대해 알고 있어야 한다.

first-class funtion
함수를 그 자체로 value 취급한다.

따라서 변수에 저장하거나, 파라미터로 넘기거나, 반환값으로 사용할 수 있다.

immutability
불변성 취급이므로 생성 후 상태의 변경이 불가능하다는 것이 보장된다.

without side effect
동일한 입력을 통해 동일한 결과를 반환하는 함수만의 순수한 기능을 사용할 수 있다.

이러한 개념을 지닌 함수형 프로그래밍을 사용할 경우 아래와 같은 이점을 얻을 수 있다.

첫 번째, 좀 더 우아하고 간결한 코드를 작성할 수 있으며 좀 더 추상화에 무게를 둠에 따라 코드의 중복을 회피할 수 있다.

아래의 예제를 보자.

1
2
fun searchKotlin() = searchName { it.name == "kotlin" }
fun searchNamhoon() = searchName { it.name == "namhoon" }

비슷한 작업을 수행하는 코드가 있고, 약간의 세부 사항이 다르다고 할 때 람다식을 이용한 anonymous function을 이용해 간결하게 작성할 수 있다.

두 번째, 안전한 멀티스레딩을 구현할 수 있다.

일반적으로 멀티 레드를 사용하는 경우, 데이터에 대한 적절한 동기화를 해주지않는다면 많은 문제점이 발생한다.

함수형 프로그래밍을 이용하여 불변성을 지닌 데이터 구조를 보장한 상태로 pure function을 사용하면 같은 데이터를 여러 스레드가 변경할 수 없으므로 동기화의 적용이 필요 없어진다.

참고 pure function이란, 외부 혹은 다른 바깥 환경과 상호작용하지않는 함수를 의미한다.

세 번째, 테스트 코드 작성이 용이하다.

pure function 기반의 함수형 프로그래밍은 외부의 영향이 없으므로 별도의 setup code없이 독립적으로 테스트를 수행할 수 있다.

kotlin은 처음부터 위의 세 가지 이점을 활용할 수 있도록 아래와 같이 함수형 프로그래밍을 지원해왔다.

  • 함수가 또 다른 함수를 파라미터 혹은 반환 타입으로 사용할 수 있다.
  • Lambda 표현식을 통해 코드 블럭을 정의하여 넘길 수 있다.
  • data class를 통해 간결한 문법으로 불변 객체를 생성할 수 있다.
  • 표준 라이브러리에서 함수형 스타일의 API를 풍부하게 지원한다.

4. 오픈소스

컴파일러와 라이브러리 등 모든 도구를 포함한 kotlin은 완전히 오픈소스로 제공된다.

오픈소스 라이센스는 Apache2로 어떤 목적으로든 마음대로 사용할 수 있게 개방되어있다.

참고 Kotlin Repository

kotlin의 철학

kotlin은 보통 상호운용성에 중점을 둔 간결하고 안전한 언어로 표현된다.

1. 실용성 - Pragmatic

kotlin은 현실 세계의 문제들을 해결하기 위해 고안된 실용적인 언어로, 다른 프로그래밍 언어들을 통해 검증된 성공적인 기능과 솔루션에 의존하여 디자인되었다.

따라서 언어의 복잡성이 줄어들고, 익숙한 개념들을 통해 쉽게 익힐 수 있다.

또한 kotlin은 특정 프로그래밍 스타일(함수형 프로그래밍과 같은)과 패러다임에 대한 강제성이 없다.

언어로서의 kotlin 뿐만 아니라 kotlin을 개발할 수 있는 환경도 IntelliJ IDEA 플러그인에서의 지원을 통해 실용성을 강조하고 있다.

2. 간결성 - Concise

개발자들은 새로운 코드의 작성보다 기존에 작성된 코드의 읽기에 더 많은 시간을 소모한다고 한다.

당연하게도 코드가 간결하고, 간단할수록 무슨 동작을 의미하는 지 파악하기가 쉽기때문에, kotlin은 작성되는 모든 코드가 의미있는 코드가 되도록 노력한다.

즉, 불필요한 보일러 플레이트는 이미 kotlin의 표준 라이브러리를 통해 포함되어있다.

좀 더 풀어서 설명하자면, kotlin은 개발자들을 위해 field, getter & setter 및 java Bean에서 제시하는 필수 요소들을 내재화하고 있는 것으로 볼 수 있다.

그렇다고 소스코드의 최소화를 목적으로 하지 않으며, 연산자 오버로딩을 지원은 하되 신규 연산자를 정의하진 못하도록 하는 등 최대한 간결성을 보장한다.

참고 Boilerplate

3. 안정성 - Safe

일반적으로 프로그래밍 언어가 안전한다는 것은 프로그램상의 특정 오류를 방지하기 위해 설계되었음을 말한다.

그러나 프로그래밍 언어가 모든 오류를 방지할 수는 없으며, 컴파일러를 통해 개발자에게 적절한 정보를 전달해주어야 한다.

kotlin은 java보다 안전한 언어를 만들기 위해 노력하였으며, 런타임에 실패하는 경우보다 컴파일시 실패하는 경우를 더 깊이 체크하므로서 안정성을 높이고 있다.

즉, 최소한의 비용으로 NPE를 제거하기위해 노력하며, Nullable 데이터들에 대한 지원을 통해서도 NPE를 방지하고 있다.

1
2
val str: String? = null // Null 초기화가 가능한 경우
val str: String = "" // Null 초기화가 불가능한 경우

추가적으로 kotlin은 Nullable 데이터를 처리할 수 있는 여러 방법을 제공하여 NPE를 회피할 수 있게해준다.

kotlin은 ClassCastException 또한 회피한다. 이는 객체 타입을 검증하지 않고 호환되지 않는 타입에 캐스팅할 경우 발생한다.

아래와 같이 타입을 검증하면 별도의 캐스팅 작업 없이 해당 타입의 멤버변수 혹은 멤버함수에 접근이 가능하다.

1
2
if (value is String) // Checks the type
println(value.toUpperCase()) // Uses the method of the type

4. 상호운용성 - Interoperable

kotlin이 java와 완벽하게 호환이 되는 만큼, 기존 라이브러리도 당연히 활용할 수 있다.

kotlin이 java의 코드를 호출하고, java에서 kotlin을 호출하는 것 또한 가능하다.

단순히 호출만 가능한 것이 아니라 클래스를 상속하거나 인터페이스를 구현하는 것도 가능하다.

5. 멀티 패러다임

상술한 함수형 프로그래밍처럼, 프로그래밍에는 다양한 패러다임이 존재한다.

함수형 프로그래밍 외에도, JVM 계열인만큼 객체지향 프로그래밍 도 처리할 수 있고 비동기 프로그래밍 은 물론 절차지향 프로그래밍 도 지원하므로 스크립트처럼 사용할 수도 있다.

6. Full-Stack Language

javac 컴파일러가 java 코드를 바이트코드로 컴파일하여 jvm에서 실행시킬 수 있도록 하는 것처럼, kotlin-jvm은 kotlin 코드를 바이트 코드로 컴파일해준다.

따라서 jvm이 쓰이는 모든 사이드에 적용이 가능한데, client 사이드의 Android Application 개발, back-end 사이드의 Spring fraemwork 개발은 물론

iOS native 개발도 지원한다.

심지어 javascript로의 transpile이 지원되므로 Node.js 와 front-end 사이드에서도 활용이 가능하다.

만약 koltin native를 사용하는 경우 web assembly binary code로도 컴파일할 수 있다.