코틀린이란?
코틀린(Kotlin)은 자바 가상머신(JVM) 플랫폼과 JVM 외의 다른 플랫폼에서 돌아가는 현대 프로그래밍 언어로, 처음에는 '더 나은 자바'로 시작했습니다. 즉, 개발자들이 일반적으로 저지를 수 있는 유형의 오류를 방지하고, 현대적 언어 설계 패러다임을 포용하면서도 자바가 쓰이던 모든 곳에 더 편리하게 쓸 수 있는 언어로 시작했습니다. 최근 10년간 코틀린은 자신이 여러 유형이 개발자, 프로젝트, 플랫폼에 실용적으로 잘 들어맞는 언어임을 증명해왔습니다.
안드로이드는 이제 코틀린 우선 플랫폼입니다. 이는 대부분의 안드로이드 개발자가 코틀린으로 개발을 한다는 뜻입니다. 스프링(spring) 같은 널리 쓰이는 프레임워크들이 코틀린을 네이티브로 지원하고 풍부한 코틀린 문서도 함께 제공하는 반면, 케이토(Ktor) 같은 순수 코틀린 프레임워크도 코틀린 언어의 모든 잠재 능력을 활용할 수 있게 해주기 때문에 서버 개발에서도 코틀린이 자바의 강력한 대안이 되고 있습니다.
코틀린은 잘 작동하는 다른 언어의 아이디어를 포함하면서 비동기 프로그래밍을 위한 코루틴 등 혁신적인 접근 방법도 취합니다. JVM에만 초점을 맞춰 시작했지만, 코틀린은 JVM을 훨씬 더 넘어섰으며 크로스플랫폼 솔루션을 만들 수 있는 기술을 포함해, 실행될 수 있는 더 많은 '타깃'을 제공합니다.
주요 특성
코틀린은 다중 패러다임 언어입니다. 코틀린은 정적 타입 지정(statically typed) 언어인데, 이는 실행 시점이 아니라 컴파일 시점에 많은 오류를 잡아낼 수 있다는 뜻입니다. 코틀린은 객체지향 언어와 함수형 언어의 아이디어를 조합했는데, 이런 조합은 우아한 코드를 작성할 수 있고, 추가로 더 강력한 추상화를 사용할 수 있게 도와줍니다. 또한 코틀린은 수많은 여러 개발 분양에서 중요한 비동기 코드를 작성할 수 있는 강력한 방법을 지원합니다.
원래 코틀린의 주목적은 현재 자바가 사용되고 있는 모든 용도에 적합하면서도 더 간결하고 생선적이며 안전한 대체 언어를 제공하는 것입니다. 이런 용도에는 아주 작은 디바이스에서 실행되는 환경으로부터 큰 데이터 센터에 이르는 다양한 환경이 포함됩니다.
또한 코틀린튼 다른 환경에서도 잘 작동합니다. 코틀린 다중 플랫폼을 사용하면 데스크톱, IOS, 안드로이드, 더 나아가 브라우저에서도 코틀린을 실행할 수 있는 크로스 플랫폼 애플리케이션을 만들 수 있습니다.
정적 타입 지정
정적 타입 지정 언어에는 성능, 신뢰성, 유지 보수성 등의 몇 가지 장점이 있습니다. 정적 타입 지정 언어의 핵심적인 장점은 프로그램의 모든 식의 타입을 컴파일 시점에 알 수 있다는 점입니다. 코틀린 컴파일러는 접근하려는 메서드나 필드가 실제로 존재하는지 검증할 수 있습니다.
이로 인해 필드가 존재하지 않거나 함수의 반환 타입이 예상과 달라짐으로 인해 생기는 모든 종류의 버그를 런타임에 프로그램이 갑자기 중단되면서 발견하는 대신, 컴파일 시에 문제를 발견함으로써 미리 방지할 수 있고, 개발 사이클의 앞쪽에서 더 일찍 문제를 해결할 수 있습니다. 다음은 정적 타입 지정의 몇 가지 장점입니다.
- 어떤 메서드를 호출해야 할 지를 런타임에 살펴볼 필요가 없기 때문에 메서드 호출이 더 빠릅니다.
- 컴파일러가 타입을 사용해 프로그램의 일관성을 검증하며, 그로 인해 프로그램이 실행 시점에 실패할 가능성이 줄어듭니다.
- 코드가 작용하는 타입을 볼 수 있기 때문에 낯선 코드를 다룰 때도 더 쉽게 다룰 수 있습니다.
- 리팩터링의 신뢰도를 높일 수 있고, 코드 완성이나 다른 IDE 기능의 정확도를 높일 수 있습니다.
코틀린에서는 컴파일 시점에 프로그램에 사용된 모든 식의 타입이 알려져 있어야만 하지만, 프로그래머가 직접 모든 변수의 타입을 명시할 필요가 없습니다. 대부분의 경우 코틀린 컴파일러가 문맥으로부터 변수 타입을 자동으로 유추할 수 있기 때문에 프로그래머는 타입 선언을 생략해도 됩니다. 컴파일러가 문맥을 고려해 변수 타입을 결정하는 이런 기능을 타입 추론(type inference)라고 부릅니다.
또한 눈길을 끄는 특성으로 코틀린이 널이 될 수 있는 타입(nullable type)을 지원한다는 점을 들 수 있습니다. 널이 될 수 있는 타입을 지원함에 따라 런타임에 프로그램이 망가지면서 끝나는 대신, 널 포인터 예외(null pointer exception)가 발생하는지 여부를 컴파일 시점에 검사할 수 있어서 좀 더 프로그램의 신뢰성을 높일 수 있습니다.
함수형 프로그래밍과 객체지향 프로그래밍
다중 패러다임 언어인 코틀린은 객체지향 접근 방식과 함수형 스타일 엮어 제공합니다.
그 중 함수형 프로그래밍의 핵심 개념은 다음과 같습니다.
- 일급 시민 함수: 함수를 일반 값처럼 변수에 저장할 수 있고, 함수를 인자로 다른 함숭 전달 할 수 있으며, 함수에서 새로운 함수를 만들어 반환할 수 있습니다.
- 불변성: 일단 만들어지고 나면 내부 상태가 절대로 바뀌지 않는 불변 객체를 사용합니다.
- 부수 효과(side-effect) 없음: 입력이 같으면 항상 같은 출력을 내놓고, 다른 객체의 상태를 변경하지 않으며 함수 외부나 다른 바깥 환경과 상호작용하지 않는 순수 함수(pure function)을 사용합니다.
이런 핵심 개념을 사용하는 함수형 스타일로 프로그램을 작성하면 얻을 수 있는 장점에 대해 알아보겠습니다.
1. 간결성
함수형 코드는 그에 상응하는 명령형 코드에 비해 더 간결하며 우아합니다. 변수의 값을 변경하고 루프나 조건 분기에 의존하는 대신 순수 함수를 값처럼 활용할 수 있으며 더 강력한 추상화가 가능합니다.
또한 함수형 접근 방식을 택하면 코드 중복을 피할 수 있습니다. 비슷한 작업을 구현하는 비슷한 코드 조각이 있는데, 일부 세부 사항에서 차이가 난다면 쉽게 공통 로직을 따로 함수로 뽑아내고 서로 다른 세부 사항을 인자로 전달할 수 있습니다. 이런 인자는 그 자체가 함수로, 코틀린에서는 람다식이라는 간결한 문법으로 표현할 수 있습니다.
2. 동시성
다중 스레드 프로그램에서는 적절한 동기화 없이 같은 데이터를 여러 행위자(스레드)가 변경하는 경우 많은 문제가 생깁니다. 불변 데이터 구조와 순수 함수를 사용한다면 안전하지 않은 데이터 변경이 발생하지 않는다고 확신할 수 있으므로 복잡한 동기화 방법을 적용하지 않아도 됩니다.
3. 테스트
부수 효과(side-effect)가 없는 함수는 그 함수가 의존하는 전체 환경을 구축하기 위한 준비 코드 없이 독립적으로 테스트 가능합니다. 함수가 외부 세계와 상호작용하지 않으므로 코드에 대해 쉽게 추론할 수 있고, 더 큰 복잡한 시스템을 항상 염두에 두지 않고서도 코드의 동작을 검증할 수 있습니다.
코루틴
서버, 데스크톱, 모바일 폰에서 실행되는 애플리케이션을 만들 때 동시성, 즉 코드의 여러 조각을 동시에 실행하는 것을 거의 피할 수 없습니다. 백그라운드에서 오래 계산이 실행되는 동안에도 사용자 인터페이스는 계속 반응성을 유지해야 합니다. 또한 인터넷 서비스와 상호작용할 때 애플리케이션이 한 번에 하나 이상의 요청을 보내야 하는 경우가 자주 있습니다. 이는 한 번에 하나 이상의 작업을 처리해야 한다는 것입니다.
동시성 처리에는 스레드로부터 callback, future, promise, reactive extension 등의 다양한 접근 방법이 있습니다. 코틀린은 동시성과 비동기 프로그래밍의 문제를 코루틴(coroutine)이라 불리는 일시 중단 가능한 계산(suspendable computation)을 사용해 접근합니다. 코루틴에서는 코드가 자신의 실행을 잠시 중단시킬 수 있고, 나중에 중단한 작업을 계속 수행할 수 있습니다.
또한 코루틴은 아주 가벼운 추상화로, 큰 성능 손해를 보지 않고 수백만 개의 동시성 작업을 시작할 수 있습니다. 뒤에서 다룰 how flow나 cold flow 같은 추상화를 통해 코틀린 코루틴은 동시성 애플리케이션을 구출할 때 쓸 수 있는 강력한 도구가 됩니다.
오픈소스
코틀린 언어와 컴파일러, 라이브러리 및 코틀린과 관련한 모든 도구는 모두 오픈소스이며, 어떤 목적에든 무료로 사용할 수 있습니다. 코틀린은 Apache 2 라이센스하에 제공됩니다.
사용 분야
코틀린이 널리 쓰이는 2가지 분야는 서버와 안드로이드 개발입니다.
백엔드: 서버 프로그래밍
서버 프로그래밍은 상당히 광범위한 개념입니다. 브라우저에 HTML 페이지를 돌려주는 웹 애플리케이션에서부터 JOSN API를 제공하는 백엔드 애플리케이션, RPC 프로토콜이나 메세지 버스를 통해 서로 통신하는 마이크로서비스까지 포함합니다.
개발자들은 이런 애플리케이션을 수년간 JVM에서 개발해 오면서 이런 종류의 애플리케이션 개발에 도움을 줄 수 있는 기술과 프레임워크를 엄청나게 만들어왔습니다. 새로운 기술이나 프레임워크는 언제나 기존 프레임워크나 기술을 확장하고 개선하거나 대치하며, 이미 여러 해 동안 쓰여 온 기존 시스템과 새로운 코드를 통합해야만 합니다.
이런 환경에서 자바 코드와 매끄럽게 상호운용할 수 있다는 점이 코틀린의 큰 장점입니다. 코틀린은 새로운 컴포넌트를 작성하거나 기존 서비스 코드를 코틀린으로 이식해야 하는 경우에 모두 잘 들어맞습니다. 자바 클래스를 코틀린으로 확장해도 아무 문제가 없으며, 코틀린 클래스 안의 메서드나 필드에 특정 자바 어노테이션을 붙여야 하는 경우에도 아무 문제가 없습니다.
코틀린을 사용할 때 얻을 수 있는 다른 큰 장점으로는 애플리케이션의 신뢰성이 더 나아진다는 점을 들 수 있습니다. 코틀린 타입 시스템은 null 값을 정확히 추적하기 때문에 NullPointerException(NPE)로 인한 문제의 영향을 덜 받게 됩니다. 자바라면 런타임(실행시점)에 NPE을 발생시켰을 대부분의 코드는 코틀린에서 컴파일에 실패하기 때문에 애플리케이션이 프로덕션 환경에 채택되기 전에 오류를 확실히 수정할 수 있습니다
스프링(spring) 같은 현대적 프레임워크도 처음부터 코틀린을 입급 시민으로 지원합니다. 이런 프레임워크들은 매끄러운 상호운용성을 제공하는 한편, 해당 프레임워크가 처음부터 코틀린을 위해 설계된 것처럼 느껴지게 해주는 확장을 제공하며 코틀린 기술을 활용합니다.
또한 계속 성장 중인 서버 측 프레임워크를 포함하는 코틀린 자체 라이브러리 생태계를 사용할 수도 있습니다. 예를 들어 케이토(Ktor)는 JetBrains에 의해 만들어진 연결형 애플리케이션 프레임워크로, 서버 측 애플리케이션을 구축하거나, 모바일이나 클라이언트에서 네트워크 요청을 보낼 때 사용할 수 있습니다. 케이토는 JetBrains Space나 Toolbox 같은 제품에 쓰이며, Adobe 같은 회사도 케이토를 채택했습니다.
다른 코틀린 서버 프레임워크로 http4k가 있습니다. http4k는 코틀린 코드의 함수적 특정을 강력히 포용하며, 요청과 응답에 대해 단순하고 균일한 추상화를 제공합니다.
모바일: 안드로이드
세계에서 가장 널리 쓰이는 모바일 운영체제인 안드로이드는 2017년부터 코틀린을 앱 빌딩을 위한 언어로 공식 지원하기 시작했습니다. 단 2년만인 2029년부터는 수많은 개발자의 긍정적 피드백으로 인해 안드로이드가 코틀린을 우선시하는, 즉 새로운 코틀린을 디폴트 선택으로 제공하는 정책을 채택했습니다. 그 후 구글의 개발 도구나 Jetpack 라이브러리, 예제, 문서, 훈련은 모두 주로 코틀린에 초점을 맞추고 있습니다.
코틀린은 모바일 앱에 적합합니다. 이런 유형의 앱은 보통 더 다양한 디바이스에 대해 운용 신뢰성을 보장하면서 더 빠르게 개발해 배포할 필요가 있습니다. 코틀린을 사용하면 안드로이드 개발 작업을 훨씬 더 적은 코드로 달성할 수 있습니다. 안드로이드 팀이 만든 안드로이드 KTX 라이브러리는 안드로이드 API에 대한 코틀린 어댑터를 제공하고, 코틀린으로 작성된 구글의 Jetpack Compose Toolkit은 애플리케이션 UI를 구축할 때 더 작고 단순하며 유지 보수하기 쉬운 코드를 작성할 수 있게 해줍니다.
또한 안드로이드에서 코틀린을 사용하는 것은 신뢰성이 높아지고 NullPointerException이나 'Unfortunately, process has stopped'와 같은 메세지가 표시되는 대화상자도 줄어듭니다. 예를 들어 구글도 '구글 홈'앱에서 새로운 기능 개발을 코틀린으로 전환한 후 NPE로 인한 프로그램 중단 횟수를 30% 줄일 수 있었습니다.
추가로 코틀린을 사용하더라도 성능이나 호환성 측면에서 아무 손해가 없습니다. 코틀린은 성능이나 호환성 측면에서 아무 손해가 없습니다. 코틀린은 자바 8 이상과 완전히 호환되며, 코틀린 컴파일러가 생성한 바이트코드도 효율적으로 실행됩니다. 코틀린의 런타임 시스템은 상당히 작기 때문에 컴파일 후 패키징한 애플리케이션의 크기도 그리 많이 늘어나지 않습니다. 또한 대부분의 코틀린 표준 라이브러리 함수는 인자로 받은 람다 함수를 인라이닝(inlining)합니다. 따라서 람다를 사용해도 새로운 객체가 만들어지지 않으므로 객체 증가로 인한 가비지 컬렉션(GC)으로 프로그램이 더 자주 멈추는 것을 겪지 않아도 됩니다.
다중 플랫폼
코틀린은 다중 플랫폼 언어이기 때문에 JVM 외에 다음과 같은 타깃을 지원합니다.
- 자바스크립트로 컴파일하여 브라우저나 노드(Node.js) 같은 런타임에서 실행할 수 있습니다.
- 코틀린/네이티브를 사용하여 이진 코드로 컴파일하면 iOS나 다른 플랫폼에서 스스로 실행되게 할 수 있습니다.
- 코틀린/와즘(Wasm)를 사용하여 웹어셈블리 바이너리 형식으로 컴파일할 수 있습니다.
코틀린은 또 여러 타깃에 대해 소프트웨어 중 어느 부분을 공유하고 어느 부분을 플랫폼마다 구체적인 구현을 제공하게 할지 아주 세밀하게 지정할 수 있습니다. 코틀린에서 expect/actual 이라는 키워드로 사용하는 이 메커니즘을 사용하면 코틀린 코드에서 크로스플랫폼 기능을 활용할 수 있습니다.
철학
코틀린에 대해 말할 때 상호운용성에 초점을 맞춘 실용적이고 간결하며 안전한 언어라고 할 수 있습니다. 각각을 순서대로 자세히 살펴보겠습니다.
실용성
코틀린의 설계는 대규모 시스템을 개발해본 다년간의 IT 업계 경험을 바탕으로 이뤄졌으며, 코틀린의 특성은 수많은 소프트웨어 개발자들의 사용에 잘 들어맞을 수 있도록 주의 깊게 선택되었습니다. 또한 코틀린은 연구를 위한 언어가 아닙니다. 코틀린은 다른 프로그래밍 언어가 채택한 이미 성공적으로 검증된 해법과 기능에 주로 의존합니다. 이로 인해 언어의 복잡도가 줄어들고 이미 알고 있는 기존 개념을 통해 코틀린을 더 쉽게 배울 수 있습니다.
코틀린은 어느 특정 프로그래밍 스타일이나 패러다임을 사용할 것을 강제로 요구하지 않기 때문에 코틀린 언어를 배우는 사람은 자신이 익숙한 프로그래밍 스타일이나 기법을 활용할 수 있습니다. 점차 코틀린의 강력한 특성(확장 함수, 고차 함수 등)을 발견하고 배우고 나면 간결하고 전형적인 코틀린 코드를 작성할 수 있습니다.
실용성에 있어 코틀린의 다른 측면은 도구를 강조한다는 점입니다. 좋은 언어만큼이나 편리한 개발 환경도 생산성 향상에 필수적입니다. 코틀린의 경우 인텔리제이 IDEA 플러그인의 개발과 컴파일러의 개발이 맞물려있습니다. 흔히 쓰이지만 더 간결한 구조로 바꿀 수 있는 대부분의 코드 패턴을 도구가 자동으로 감지해서 수정하라고 제안합니다. 이런 자동 수정 안내에 쓰인 특성을 살펴보면서 코틀린 언어의 특성을 잘 이해하면 자신의 코드에 그런 특성을 적용하는 법을 배울 수 있습니다.
간결성
개발자가 코드를 새로 작성하는 시간보다 기존 코드를 읽는 시간이 더 길다는 사실이 잘 알려져 있습니다. 큰 프로젝트에서 수정할 부분을 찾고 어떻게 고쳐야 할지 알아내려면 엄청난 양의 코드를 읽어야 합니다. 물론 설계가 좋고 각 부분의 역할을 잘 표현해주는 적절한 이름이 붙어있다면 내용을 파악할 때 도움은 되지만, 어떤 언어를 사용해 코드를 작성했고 그 언어가 얼마나 간결한 언어인지도 중요합니다. 어떤 언어가 간결하다는 말은 그 언어로 작성된 코드를 읽을 때 의도를 쉽게 파악할 수 있는 구문 구조를 제공하고, 그 의도를 달성하는 방법을 이해할 때 방해가 될 수 있는 부가적인 준비 코드가 적다는 뜻입니다.
코틀린은 프로그램 언어가 요구하는 구조를 만족시키기 위한 요소를 줄이기 위해 많은 노력을 기울였습니다. getter, setter, 생성자 파라미터를 필드에 대입하기 위한 로직 등 객체지향 언어에 존재하는 여러 가지 번거로운 준비 코드를 코틀린은 암시적으로 제공하기 때문에, 코틀린 소스코드는 그런 준비 코드로 인해 지저분해지는 일이 없습니다. 또한 코틀린의 강력한 타입 추론으로 인해 컴파일러가 문맥으로부터 타입을 추론할 수 있는 경우 타입을 직접 지정할 필요가 없습니다.
코틀린의 기능이 풍부한 표준 라이브러리를 사용하면 반복되거나 길어질 수 있는 코드를 라이브러리 함수 호출로 대치할 수 있습니다. 코틀린은 람다와 익명 함수를 지원하기 때문에 작은 코드 블록을 라이브러리 함수에 쉽게 전달할 수 있습니다. 따라서 일반적인 기능을 라이브러리 안에 캡슐화하고 작업에 따라 달라져야 하는 개별적인 내용을 사용자가 작성한 코드 안에 남겨둘 수 있습니다.
반면 코틀린은 소스코드에 필요한 글자 수를 최대한 짧게 만드려고 노력하지는 않습니다. 예를 들어 코틀린은 연산자 오버로딩(operation overloading)을 미리 정해진 연산자 집합에 대해서만 제공합니다. 이는 +, -, in, [ ] 등의 연산에 대해 커스텀 구현을 정의할 수 있다는 뜻입니다. 하지만 프로그래머가 직접 언어가 제공하지 않는 연산자를 정의할 수는 없습니다. 이로 인해 개발자가 메서드 이름을 암호문처럼 보이는 기호만으로 이뤄진 연산자 식별자로 대치할 수 없습니다. 식별자로 된 이름은 더 읽기 어렵고 설명적인 이름을 사용할 때에 비해 문서 시스템에서 원하는 이름을 검색하기도 어렵습니다.
안전성
일반적으로 프로그래밍 언어가 안전하다는 말은 프로그램에서 발생할 수 있는 오류 중에서 일부 유형의 오류를 프로그램 설계가 원천적으로 방지해준다는 뜻입니다. 물론 이는 절대적이지는 않습니다. 어떤 언어도 발생할 수 있는 모든 오류를 막을 수는 없습니다. 추가로 오류를 방지하는 데는 대가가 따르기 마련입니다. 컴파일러에게 프로그램이 어떻게 작동해야 하는지에 대한 정보를 더 자세히 제공해야만 컴파일러가 프로그램 코드와 프로그램의 작동 의도에 대한 정보가 일치하는지를 검증할 수 있습니다. 따라서 프로그램에 더 많은 정보를 덧붙여야 하기 때문에 감소하는 생산성과 그로 인해 늘어나느 안전성 사이에는 트레이드 오프(trade off) 관계가 성립합니다.
코틀린을 JVM에서 실행한다는 사실은 이미 상당한 안전성을 보장할 수 있다는 뜻입니다. 예를 들어 JVM을 사용하면 메모리 안전성을 보장하고, 버퍼 오버플로(overflow)를 방지하며, 동적으로 할당한 메모리를 잘못 사용함으로 인해 발생할 수 있는 다른 문제를 예방할 수 있습니다. JVM에서 실행되는 정적 타입 지정 언어로서 코틀린은 애플리케이션의 타입 안전성을 보장합니다. 코틀린은 이보다 더 나가서 읽기 전용 변수를 쉽게 정의할 수 있게 해주고, 불변 변수들을 묶어 불변 클래스로 빠르게 만들 수 있게 해줌으로써 다중 스레드 애플리케이션에서 안전성을 더 보장할 수 있습니다.
그 외에도, 코틀린은 실행 시점에 오류를 발생시키는 대신 컴파일 시점 검사를 통해 오류를 더 많이 방지해줍니다. 가장 중요한 내용으로 코틀린의 타입 시스템은 null이 될 수 없는 값을 추적하며 실행 시점에 NullPointerException이 발생할 수 있는 연산을 사용하는 코드를 금지합니다. 이로 인해 추가로 들어가는 비용은 미미합니다. null이 될 수 있는 경우를 보완하기 위해 코틀린은 널이 될 수 있는 값을 다룰 수 있는 편리한 방법을 다양하게 제공하며, 이런 기능은 애플리케이션이 갑자기 중단되는 경우를 많이 줄여줍니다.
코틀린이 방지해주는 다른 예외로는 클래스 캐스트 예외가 있습니다. 어떤 객체를 다른 타입으로 변환하기 전에 타입을 미리 검사하지 않으면 이런 예외가 발생합니다. 코틀린은 타입 검사와 캐스트를 한 연산자로 수행하는데, 이는 어떤 객체의 타입을 검사했다면 그 객체의 멤버를 별도의 캐스트나 재선언, 타입 검사 없이 사용할 수 있다는 뜻입니다.
상호운용성
상호운용성(interpoerability)과 관련해 첫 번째로 걱정하는 것은 "기존 라이브러리를 그대로 사용할 수 있나?"일 것입니다. 코틀린의 경우 그에 대한 답은 "물론 그렇다"입니다. 라이브러리가 어떤 API를 제공하던지 코틀린에서 그 API를 활용할 수 있고, 자바 메서드를 호출하거나 자바 클래스를 상속하거나 인터페이스를 구현하거나 자바 어노테이션을 코틀린 코드에 적용하는 등의 일이 모두 가능합니다.
다른 일부 JVM 언어와 달리 코틀린은 상호운용성 측면에서 훨씬 더 많은 것을 제공합니다. 코틀린의 클래스나 메서드를 일반적인 자바 클래스나 메서드와 똑같이 사용할 수 있습니다. 이에 따라 자바와 코틀린 코드를 프로젝트에서 원하는 대로 섞어 쓸 수 있는 궁극적인 유연성을 발휘할 수 있습니다. 기본 자바 프로젝트에 코틀린을 도입하는 경우 자바를 코틀린으로 변환하는 도구로 코드베이스 안에 있는 자바 클래스에 대해 실행해서 어느 한 자바 클래스를 코틀린 클래스로 변환할 수 있는데, 이 경우에도 프로젝트의 나머지 부분을 전혀 수정하지 않고 컴파일 및 실행이 가능합니다. 이런 성질은 변환한 클래스의 역할과 관계없이 성립합니다.
상호운용성 측면에서 코틀린이 집중하는 다른 방향으로는 기존 자바 라이브러리를 가능하면 최대한 활용한다는 점을 들 수 있습니다. 예를 들어 코틀린은 거의 대부분을 자바 표준 라이브러리 클래스에 의존하며 코틀린에서 컬렉션을 더 쉽게 활용할 수 있게 해주는 함수를 몇 가지 더 확장할 뿐입니다. 이는 코틀린에서 자바 API를 호출할 때나 자바에서 코틀린을 호출할 때 객체를 감싸거나 변환할 필요가 없다는 뜻입니다. 코틀린이 제공하는 풍부한 API는 실행 시점에 아무런 부가 비용을 야기하지 않습니다.
또한 인텔리제이에서도 다중 언어 프로젝트를 완전히 지원합니다. 코틀린과 자바 소스 파일이 임의로 섞여 있어도 각 소프 파일 사이의 의존관계가 어떤 식으로 이뤄지든 관계없이 컴파일 할 수 있습니다.
+) 자바-코틀린 변환기
자바-코틀린 변환기(Java-to-Kotlin converter)는 자동으로 자바를 코틀린으로 변환해주는 변환기입니다. 작성하고 싶은 코드를 자바로 작성해 복사한 후 코틀린 파일에 그코드를 붙여 넣으면 변환기가 자동으로 같은 뜻의 코틀린 코드를 제안합니다. 물론 변환기가 항상 가장 코틀린다운 코드를 제안해주지는 못하지만 잘 작동하는 코틀린 코드를 알려주기 때문에 원하는 바를 코틀린으로 달성할 수 있습니다. 이는 기존 자바 프로젝트에 코틀린을 도입하고 싶을 때 유용하게 사용될 수 있습니다.
인텔리제이 IDEA에서 변환기를 사용하는 방법은 자바 코드 조각을 복사해서 코틀린 파일에 붙여 넣으면 됩니다. 만약 자바 파일 하나를 통째로 코틀린으로 변환하고 싶으면 메뉴에서 'Convert Java File to Kotlin FIle'을 선택하면 됩니다.
컴파일
코틀린은 컴파일 언어입니다. 이는 코틀린에서 코드를 실행하기 위해서는 반드시 코드를 컴파일해야 한다는 뜻입니다. 앞서 설명한 것처럼 코틀린 코드를 다른 여러 타깃으로 컴파일할 수 있습니다.
- JVM에서 실행되는 JVM 바이트코드(.class)
- 안드로이드에서 실행되기 위한 JVM 바이트코드
- 다른 운영체제에서 네이티브로 실행되기 위한 네이티브 타깃
- 브라우저에서 실행되기 위한 자바스크립트 또는 웹어셈블리
컴파일 과정
코틀린 소스코드를 저장할 때는 보통 .kt 라는 확장자를 파일에 붙입니다. 코틀린 컴파일러는 자바 컴파일러가 자바 소스코드를 컴파일할 때와 마찬가지로 코틀린 소스코드를 분석해서 .class 파일을 만들어냅니다. 만들어진 .class 파일은 개발중인 애플리케이션 유형에 맞는 표준 패키징 과정을 거쳐 실행될 수 있습니다.
JVM은 원래 코드가 코틀린이나 자바 중 어느 언어로 작성됐는지는 알지 못해도 코틀린 코드에서 빌드된 .class 파일을 실행할 수 있습니다. 하지만 코틀린 내장 클래스와 API는 의존관계로, 코틀린 런타임 라이브러리(Kotlin runtime library)라는 추가 정보가 필요합니다. 커맨드라인에서 코드를 컴파일할 때 명시적으로 '-include-runtime' 을 호출해서 결과로 생기는 JAR 파일 안에 런타임 라이브러리를 포함시켜야 합니다. 코틀린 런타임 라이브러리에는 Int나 String 같은 코틀린 기본 클래스의 정의가 들어가 있고, 표준 자바 API에 대한 확장도 들어가 있기 때문에 애플리케이션을 배포할 때는 런타임 라이브러리도 함께 배포할 필요가 있습니다.
추가로 코틀린 표준 라이브러리(Kotlin standard library)도 애플리케이션의 의존관계로 필요합니다. 이론적으로는 코틀린 표준 라이브러리 없이도 코드를 작성할 수 있지만 실제로는 결코 그런 식으로 코드를 작성하지 않습니다. 표준 라이브러리에는 List, Map, Sequence 같은 기초 클래스와 이런 클래스에 대해 작동하는 수많은 메서드가 들어있습니다.
실제로 개발을 진행한다면 프로젝트를 컴파일하기 위해 메이브(Maven), 그래들(Gradle) 등의 빌드 시스템을 사용할 것입니다. 이런 빌드 시스템은 모두 코틀린과 자바가 코드베이스에 함께 들어가 있는 혼합 언어 프로젝트를 지원합니다. 메이븐과 그래들은 애플리케이션을 패키징할 때 알아서 코틀린 런타임과 최신 코틀린 표준 라이브러리를 의존관계에 포함시켜주기 때문에 명시적으로 포함시킬 필요가 없습니다.
'Lang > Kotlin' 카테고리의 다른 글
| [Kotlin In Action] (3) - defining and calling functions (0) | 2025.10.16 |
|---|---|
| [Kotlin In Action] (2) - basics (0) | 2025.10.13 |