[include(틀:하위 문서, top1=Kotlin/문법)] [include(틀:프로그래밍 언어)] [[파일:external/kotlinlang.org/kotlin_250x250.png|width=25%]] {{{#!syntax java fun main(args: Array<String>) { println("Hello, World!") } }}}[* 코틀린 버전 1.3부터 main 메서드에 매개 변수가 없어도 실행된다. 1.3 이후에선 다음과 같이 작성하여도 똑같이 작동한다. {{{#!syntax java fun main() { println("Hello World!") } }}}] [[http://kotlinlang.org/|공식 사이트]] [목차] == 소개 == [[IntelliJ IDEA]]의 개발사 [[JetBrains]]에서 2011년에 공개한 [[프로그래밍 언어]]. [[Java]]에 비해 상당히 간결한 문법을 가지고 있으며, 세미콜론은 옵션이다. [[Java Virtual Machine|JVM]] 기반의 언어이며, [[Java]]와의 상호 운용이 100% 지원된다. JVM [[바이트코드]]가 기본이지만, Kotlin/Native [[컴파일러]]를 사용하여 기계어로 최종컴파일이 가능하다. [[안드로이드(운영체제)|안드로이드]], [[Spring(프레임워크)|스프링 프레임워크]], [[톰캣]][* JVM 환경에서도 돌아간다.], [[JavaScript]], [[Java|Java EE]], [[HTML5]], [[iOS]], [[라즈베리 파이(컴퓨터)|라즈베리 파이]] 등을 개발할 때 사용할 수 있다. 현재 최신 버전은 1.4.20. 2017년에 [[구글]]이 [[안드로이드(운영체제)|안드로이드]]의 공식 언어로 Kotlin을 [[https://blog.jetbrains.com/kotlin/2017/05/kotlin-on-android-now-official/|추가]]하였다. 이는 [[오라클(기업)|오라클]]과의 Java API 저작권 분쟁의 여파로 보는 시각이 많다. 2018년 [[카카오(기업)|카카오]]가 [[카카오톡]] 메시징 서버에 Kotlin을 사용해 본 결과, 코드량이 비약적으로 감소하고 생산성이 대폭 향상되었다고 한다. [[https://byline.network/2018/09/5-20/|#]] 2019년 1월부터는 구글 내부의 안드로이드 프로젝트에서도 Java 대신 Kotlin을 사용한다. [[https://twitter.com/jmslau/status/1087827632752738304|#]] 안드로이드 공식 문서의 샘플 코드도 Java보다 Kotlin으로 작성된 예제가 먼저 나온다. [[https://developer.android.com/guide/components/activities/activity-lifecycle|예시]] 이름은 JetBrains의 R&D 센터가 위치한 [[상트페테르부르크]] 근처의 코틀린(Ко́тлин) 섬에서 따왔다. [[https://youtu.be/VU_L2_XGQ9s|Andrey Breslav(Андрей Бреслав)의 발표 참고]] [[Java]]가 인도네시아의 섬이라는 것을 생각해보면 다분히 Java를 의식한 듯한 이름. == [[Kotlin/문법|문법]] == [include(틀:상세 내용, 문서명=Kotlin/문법)] == 특징 == * 장황했던 Java와 비교하면 눈물날 정도로 간결한 문법을 제공한다. 간결한 문법을 제공하면서도 런타임 오버헤드가 거의 없다. * 오버헤드 없는 널 안전성을 제공한다. Kotlin의 변수는 Nullable(널 값 사용 가능)과 NotNull(널 값 사용 불가)로 나뉘는데, 변수 선언 시 '?'를 붙여 Nullable로 만들 수 있다. Swift에서도 유사한 기능을 쓰는데 Kotlin 쪽이 제약이 좀 덜해서 사용하기 편하다. * 예외처리를 강제하지 않는다. JSONObject를 만들 때 눈물이 난다... * 모든 함수가 리턴값을 가진다. * Java의 'Integer'나 'Double'처럼 primitive type을 위한 별도의 wrapper class가 존재하지 않는다. 모든 primitive type은 객체 취급을 받는다. 따라서 Int 같은 변수는 객체에 할당된 toString 함수 등을 바로바로 이용할 수 있다. * 확장함수, 연산자 오버로딩을 지원한다. 예를 들어 int형을 확장해 'i = 3 power 4' 같은 식으로 새 연산자를 만들 수 있다.[* 실제로는 새 infix 함수를 생성하는 것으로 작동한다. 사칙연산 또한 infix 함수로 구현되어 'a * 3'으로도, 'a.times(3)'으로도 쓸 수 있다. 연산자와 연산자 오버로딩도 이 infix 함수로 돌아간다.] * API 문서에 Java의 HTML 대신 Markdown을 사용한다. * == 연산자가 생각하는 대로 작동한다. Java에서는 String i와 String j가 같은 문자열을 담고 있어도 가리키는 객체의 메모리 주소는 다를 수 있으므로 i == j는 false가 될 수 있다. 이 경우 쓰는 함수가 equals()인데, Kotlin에서 ==는 equals()와 똑같이, 즉 content equality로 작동한다. 따라서 i == j는 true다. Java처럼 identity equality를 비교하려면 ===를 쓰면 된다. !=를 쓰려면 !==를 쓰자. * static 메서드가 없다. companion object를 사용해 감싸야 한다. Java 코드에서 접근하려면 '클래스명.Companion.메서드_혹은_get변수명()' 또는 @JvmStatic annotation을 쓰면 된다. * Java 6에 호환된다.[* JVM6를 타겟으로 컴파일해야 한다. JVM8 바이트코드로 컴파일할 수도 있다.] * '''Java와의 상호 운용이 100% 지원된다.'''[* Kotlin에서 Java 코드 사용 시에는 그냥 사용할 수 있지만, Java에서 Kotlin 코드 사용 시에는 @Jvm* 계열의 annotation 사용이 필요한 경우도 있다.] === 간결한 문법 === * getter와 setter를 배제했다. 그냥 쓰지 말라고 IntelIiJ의 코드 제너레이트(Alt+Insert)에서 빼버렸다. 물론 쓰려면 당연히 쓸 수 있는데, 구글은 Java에서도 메모리와 속도 면에서 저 둘을 쓰지 말고 그냥 변수를 public으로 하라고 권장해 왔다.[* 변수를 private으로 선언해놓으면 접근할 때 getXX() 또는 setXX() 함수를 호출해야하므로 public으로 선언한다면 함수 호출에 따른 오버헤드와 그에 따른 불필요한 리소스 소모를 줄일 수 있다. 간단한 프로그램에서의 동작은 체감하기 어려울 지 몰라도 방대한 양의 코드에서는 효과가 있다.] * 클래스의 getters, setters, equals(), hashCode(), toString()과 copy()를 '''한 줄로''' 선언할 수 있다! 변수(var) 및 상수(val)로 지정된 생성자 패러미터는 클래스의 멤버 변수/상수로 동작한다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">data <span style="color: #008800; font-weight: bold">class</span> <span style="color: #0066BB; font-weight: bold">Customer</span>(<span style="color: #008800; font-weight: bold">var</span> name: String, <span style="color: #008800; font-weight: bold">var</span> email: String, <span style="color: #008800; font-weight: bold">var</span> company: String) </pre></div> }}} * 람다 식을 지원한다. * 싱글톤 방식의 객체를 object로 만들 수 있다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">object ThisIsASingleton { <span style="color: #008800; font-weight: bold">val</span> companyName: String = <span style="background-color: #fff0f0">"JetBrains"</span> } </pre></div> }}} * in과 Range문이 있다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">if</span> (i <span style="color: #008800; font-weight: bold">in</span> <span style="color: #6600EE; font-weight: bold">1.</span>.<span style="color: #6600EE; font-weight: bold">10</span>) { <span style="color: #888888">// equivalent of 1 <= i && i <= 10</span> println(i) } </pre></div> }}} * for문에도 쓸 수 있다! {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">for</span> (i <span style="color: #008800; font-weight: bold">in</span> <span style="color: #6600EE; font-weight: bold">0.</span>.<span style="color: #6600EE; font-weight: bold">12</span> step <span style="color: #6600EE; font-weight: bold">3</span>) print(<span style="background-color: #fff0f0">"$i "</span>) <span style="color: #888888">// 0 3 6 9 12 출력</span> <span style="color: #008800; font-weight: bold">for</span> (i <span style="color: #008800; font-weight: bold">in</span> <span style="color: #6600EE; font-weight: bold">12</span> downTo <span style="color: #6600EE; font-weight: bold">0</span> step <span style="color: #6600EE; font-weight: bold">2</span>) print(<span style="background-color: #fff0f0">"$i "</span>) <span style="color: #888888">// 12 10 8 6 4 2 0 출력</span> </pre></div> }}} * switch/case가 when ->으로 대체되었다. 위의 in과 Range도 쓸 수 있다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">when</span> (x) { <span style="color: #6600EE; font-weight: bold">0</span>, <span style="color: #6600EE; font-weight: bold">1</span> -> print(<span style="background-color: #fff0f0">"boolean"</span>) <span style="color: #6600EE; font-weight: bold">2</span> -> print(<span style="background-color: #fff0f0">"콩\n콩"</span>) !<span style="color: #008800; font-weight: bold">in</span> <span style="color: #6600EE; font-weight: bold">1.</span>.<span style="color: #6600EE; font-weight: bold">9</span> step <span style="color: #6600EE; font-weight: bold">2</span> -> print(<span style="background-color: #fff0f0">"홀수 아님"</span>) <span style="color: #008800; font-weight: bold">in</span> <span style="color: #6600EE; font-weight: bold">0.</span>.<span style="color: #6600EE; font-weight: bold">9</span> -> print(<span style="background-color: #fff0f0">"한자릿수"</span>) <span style="color: #008800; font-weight: bold">else</span> -> print(<span style="background-color: #fff0f0">"otherwise"</span>) } </pre></div> }}} * is 연산자가 있다. 타입 체크, 자동 형변환 등이 가능하다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">npcContainer.forEach { npc -> <span style="color: #008800; font-weight: bold">if</span> (npc <span style="color: #008800; font-weight: bold">is</span> Visible) npc.drawBody(gc, g) <span style="color: #888888">// npc가 Visible형으로 자동 변환되었다.</span> <span style="color: #008800; font-weight: bold">if</span> (npc <span style="color: #008800; font-weight: bold">is</span> Glowing) npc.drawGlow(gc, g) <span style="color: #888888">// npc가 Glowing형으로 자동 변환되었다.</span> } </pre></div> }}} * when문에도 쓸 수 있다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">when</span> (expr) { <span style="color: #008800; font-weight: bold">is</span> Num -> expr.value <span style="color: #888888">// expr이 Num형으로 자동 변환되었다.</span> <span style="color: #008800; font-weight: bold">is</span> Sum -> eval(expr.left) + eval(expr.right) <span style="color: #888888">// expr이 Sum형으로 자동 변환되었다.</span> <span style="color: #008800; font-weight: bold">else</span> -> <span style="color: #008800; font-weight: bold">throw</span> IllegalArgumentException(<span style="background-color: #fff0f0">"퉤에엣"</span>) } </pre></div> }}} * if문이 표현식으로 동작한다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">val</span> max = <span style="color: #008800; font-weight: bold">if</span> (a > b) { print(<span style="background-color: #fff0f0">"Choose a"</span>) a } <span style="color: #008800; font-weight: bold">else</span> { print(<span style="background-color: #fff0f0">"Choose b"</span>) b } </pre></div> }}} === 안전성 === * Null 객체를 참조하는 경우를 알아서 보호해준다. Java에서 가져온 클래스 등도 가능하다. * 변수명?를 사용하는 경우 변수 안의 메소드나 변수 (ex. length)를 불러올때 변수가 null이면 null을 반환한다. 런타임 NullPointerException의 고통을 덜어주는 고마운 기능이다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">return b?.length <span style="color: #888888">//b가 null이면 null 리턴</span> </pre></div> }}} * 오류 방지로 null-safe 연산자를 쓸 수 있다. (ex. s as String?) * 안전한 형변환 키워드인 as? 가 존재한다. (ex. s as? String) {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #888888">/*</span> <span style="color: #888888">null이거나 null은 아니지만 대상 타입으로 형변환될 수 없는 경우와 같은</span> <span style="color: #888888">형변환이 실패하는 모든 경우에 대해 안전하게 null을 반환해준다.</span> <span style="color: #888888">*/</span> <span style="color: #008800; font-weight: bold">null</span> <span style="color: #008800; font-weight: bold">as</span>? String <span style="color: #888888">// null</span> <span style="background-color: #fff0f0">"string"</span> <span style="color: #008800; font-weight: bold">as</span>? File <span style="color: #888888">// null</span> <span style="color: #888888">/*</span> <span style="color: #888888">반면 as는 경우에 따라 kotlin.TypeCastException이나</span> <span style="color: #888888">java.lang.ClassCastException 예외를 발생시킬 수 있다</span> <span style="color: #888888">*/</span> <span style="color: #008800; font-weight: bold">null</span> <span style="color: #008800; font-weight: bold">as</span> File <span style="color: #888888">// kotlin.TypeCastException 예외 발생</span> <span style="color: #008800; font-weight: bold">null</span> <span style="color: #008800; font-weight: bold">as</span> File? <span style="color: #888888">// null</span> <span style="background-color: #fff0f0">"string"</span> <span style="color: #008800; font-weight: bold">as</span> File <span style="color: #888888">// java.lang.ClassCastException 예외 발생</span> <span style="background-color: #fff0f0">"string"</span> <span style="color: #008800; font-weight: bold">as</span> File? <span style="color: #888888">// java.lang.ClassCastException 예외 발생</span> </pre></div> }}} === 그 외 === * new 키워드가 없다. * 세미콜론이 필요없다.[* 넣어도 오류는 나지 않는다.] * Function parameter가 immutable한 val이다. * System.out.println/printf 등이 println/printf 등으로 줄었다. * String에서 변수의 값을 쉽게 표현할 수 있는 interpolation($)을 지원한다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">val</span> name: String = <span style="background-color: #fff0f0">"Wikineet"</span> <span style="color: #008800; font-weight: bold">val</span> greet_en: String = <span style="background-color: #fff0f0">"Hello, $name!"</span> <span style="color: #008800; font-weight: bold">val</span> greet_ko: String = <span style="background-color: #fff0f0">"${name}님 안녕하세요!"</span> println(greet_en) <span style="color: #888888">// 출력: Hello, Wikineet!</span> println(greet_ko) <span style="color: #888888">// 출력: Wikineet님 안녕하세요!</span> </pre></div> }}} * Nullable이 아닌 변수에서 null 사용시 오류를 뱉어낸다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">var a: String <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"abc"</span> a <span style="color: #333333">=</span> null <span style="color: #333333">//</span> 컴파일 에러 </pre></div> }}} * ?을 사용해 Nullable로 만들어주면 쓸 수 있다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">var</span> b: String? = <span style="background-color: #fff0f0">"abc"</span> b = <span style="color: #008800; font-weight: bold">null</span> <span style="color: #888888">// ok</span></pre></div> }}} * Elvis 연산자(?:)가 존재한다. {{{#!html <!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">val</span> testee_hometown: String? = <span style="color: #008800; font-weight: bold">null</span> <span style="color: #888888">// 여기에 적절한 값을 넣으면 '<피실험자 고향 지명>' 대신 넣은 값이 표시된다.</span> <span style="color: #008800; font-weight: bold">val</span> hometown_display = testee_hometown ?: <span style="background-color: #fff0f0">"<피실험자 고향 지명>"</span> <span style="color: #888888">// testee_hometown이 null인지 검사한다. null이면 연산자의 우변에 있는 값이 대신 대입된다.</span> println(<span style="background-color: #fff0f0">"이 장치는 ${hometown_display}에 사는 모든 사람의 소득 금액을 합친 것보다 더 비쌉니다."</span>) </pre></div> }}} == 통합 개발 환경 == [[JetBrains]]에서 개발하고 [[구글]]이 밀어주는 언어인 만큼 이쪽에 특화된 [[통합 개발 환경]]에서 주로 지원된다. 대표적인 것이 [[IntelliJ IDEA]]와 [[안드로이드 스튜디오]]. [[이클립스(통합 개발 환경)|이클립스]]에서도 Kotlin 플러그인을 설치해 사용할 수 있다. == 기타 == * [[가상머신]]을 이용하지 않는 모바일 환경이나 임베디드, IoT 환경을 위해 개발된 Kotlin/Native 컴파일러로 기계어 최종 컴파일을 할 수 있다. [[LLVM]]에 기반하고 있으며, 참조 횟수 카운팅 방식의 [[쓰레기 수집|가비지 컬렉션]]을 사용한다. [[iOS]]나 [[Raspberry Pi]] 개발도 가능하다. * 최신 언어에서 개발된 언어 디자인 컨셉들을 많이 활용했지만, 이해하기 힘들거나 사용빈도가 떨어지는 기능들을 제거해 언어 자체를 단순하게 만들고 툴링을 강화한 언어라는 평가를 받는다. 예를 들면, 본문에 소개된 Kotlin의 ?(null 안전성)를 제외한 모든 기능은 [[Scala]]에 이미 존재했던 기능들이고, 반대로 Scala에 존재하지만 Kotlin에 존재하지 않는 기능은 정말 많다.[* ~~?는 편리한 기능임과 동시에 타입시스템 상의 논리적인 오류이기 때문에 타입 안정성에 극도로 공을 들이는 Scala 같은 언어에서 도입할 가능성은 없다.~~ Scala 2에서 null에 대처하는 일반적인 방법은 단순한 빌트인 타입 중 하나일 뿐인 Option 타입이고, 언어 자체에 null 안정성과 관련된 기능은 없다. 하지만 Scala 3에서는 `-Yexplicit-nulls` 컴파일러 옵션으로 타입 위계를 완전히 바꾸어서 레퍼런스 타입이라도 기본적으로 nullable하지 않게 할 수 있다. 이 경우, Null이 가능하게 하려면 `String|Null` 로 타입을 지정해야 한다. 타입시스템에 논리적 오류를 도입하지 않으면서도 null 안정성을 얻은 연구 성과이다.] * 스택 오버플로우를 검색해보면 Kotlin 질문들은 거의 없는 것을 볼 수 있는데, Java와 Kotlin은 서로 완벽하게 호환되기 때문에 답이 안 나온다면 Java로 질문된 문제를 참고하면 된다. * Kotlin과 [[IntelliJ IDEA]]를 만든 [[JetBrains]]에서 제작한 코틀린 전용 웹 프레임워크 Ktor가 존재한다. * [[Java]]와 상호 호환되는 언어인만큼 [[JetBrains]]의 Java, Kotlin IDE인 [[IntelliJ IDEA]]에 Java 코드를 Kotlin 코드로 바꿔주는 기능이 존재한다.[* 이 기능은 [[IntelliJ IDEA]]를 기반으로 만들어진 IDE인 [[Android Studio]]에도 존재한다.] == 관련 문서 == * [[Java]] * [[Swift(프로그래밍 언어)|Swift]] * [[Dart(프로그래밍 언어)|Dart]] * [[Go(프로그래밍 언어)]] * [[Flutter(프레임워크)|Flutter]] == 바깥 링크 == * [[https://kotlinlang.org/docs/reference/|레퍼런스 가이드]] * [[https://play.kotlinlang.org/|써보기]] * [[http://try.kotlinlang.org/koans|배워보기]] * [[https://discuss.kotlinlang.org/|코틀린 포럼]] [[분류:객체 지향 언어]][[분류:프로그래밍 언어]]