최근 바뀜
통계
임의의 문서로
도움말
문서
토론
원본 보기
역사 보기
로그인
코틀린 문서 원본 보기
내위키
←
코틀린
이동:
둘러보기
,
검색
문서 편집 권한이 없습니다. 다음 이유를 확인해주세요:
요청한 명령은 다음 권한을 가진 사용자에게 제한됩니다:
사용자
.
문서의 원본을 보거나 복사할 수 있습니다.
Kotlin. [https://kotlinlang.org/ 공식 웹사이트]. 통합 개발환경인 인텔리J로 유명한 [[제트브레인]]에서 내놓은 프로그래밍 언어. [[자바]] 가상머신 위에서 동작하며 [[자바]]와 100% 호환된다는 것이 제트브레인 측의 설명이다. 즉 [[자바]]가 돌아가는 환경이라면 코틀린도 돌아간다. 그 대표적인 예가 안드로이드로, [[안드로이드 스튜디오]] 2.x 대에서도 코틀린을 사용해서 [[안드로이드]] 프로그래밍을 하는 것이 가능하며<ref>[[안드로이드 스튜디오]]에서 코틀린 플러그인을 설치해서 쓸 수 있다.</ref> [[안드로이드 스튜디오]] 3.0부터는 아예 [[자바]]와 함께 코틀린도 기본으로 지원한다. 2019년부터는 아예 [[안드로이드]] 관련 공식문서에 코틀린을 우선 사용하기 시작했다. 물론 [[자바]] 라이브러리도 제약 없이 갖다 쓸 수 있다. [[자바]] 때문에 오라클과 계속해서 분쟁을 겪고 있는 [[구글]]로서는 코틀린이 하나의 대안으로 부상하고 있는데, 한때 [[스위프트]]로 돌아선다는 얘기도 있었지만 그럴 가능성은 거의 사라졌고, 일단 [[자바]]와 100% 호환되는 코틀린을 지원함으로써 개발자들을 이쪽으로 유도한 후 자바 가상머신을 대체해서 [[LLVM]]과 같은 방식으로 코틀린을 네이티브 지원하고 [[자바]]는 자연스럽게 놓지 않겠느냐는 전망이 대두되었고, 실제로 [[LLVM]] 기반으로 JVM을 필요로 하지 않는 코틀린 네이티브(Kotlin Native) 프로젝트가 진행되고 있다. [[안드로이드]]만이 아니라 [[iOS]], [[윈도우]], [[macOS]], [[리눅스]]도 지원한다. 아파치 톰캣과 같은 자바 서블릿 기반 웹 서버 환경에서도 쓸 수 있으며 자바 서버 환경에서 널리 널리 쓰이는 Spring Framework도 Spring Boot를 통해 코틀린을 잘 지원한다. ==특징== ===간결함=== [[자바]]에 비해서 훨씬 간결하게 코드를 짤 수 있으며, 현대 프로그래밍의 여러 개념들을 적극 수용했다. 실제로 똑같은 일을 하는 프로그램을 [[자바]]와 코틀린으로 짜 보면 코틀린의 코드 양이 훨씬 적다. 예를 들면 아래의 코드는 단 한 줄로 name, email, company 세 개의 필드를 가지고 이에 대한 getters와 setters는 물론 equals(), hashCode(), toString() 그리고 copy()까지 모두 지원하는 POJO 클래스를 정의한다. <syntaxhighlight lang="kotlin"> data class Customer(val name: String, val email: String, val company: String) </syntaxhighlight> 이걸 [[자바]]로 짜려면 몇 줄이나 나올까? 말도 하지 말자. 그런데 자세히 보면 변수 혹은 매개변수를 정의하는 방법이 [[자바]]와 많이 다르다. val이라는 키워드가 먼저 나오고, 변수 이름이 나온 다음 콜론을 찍고 변수의 타입을 쓴다. 변수 타입 → 이름 순서인 [[자바]]<ref>[[자바]]만이 아니라 대부분 프로그래밍 언어, 그 중에서도 C를 계승한 언어들이 그렇다. 반면 [[Go]]는 코틀린처럼 변수의 타입을 나중에 쓴다. 이쪽을 지지하는 주장은 보통 사람은 '변수 name은 String 유형'와 같은 순서로 생각하는 게 자유롭다는 것.</ref>와는 반대다. <ref>코틀린의 변수 선언과 가장 비슷한 언어는 놀랍게도 지금 별로 쓰이지 않고 있는 파스칼이다! 코틀린의 변수 선언 방식은 <syntaxhighlight lang="kotlin" inline>val a: Int = 10000</syntaxhighlight>인데 파스칼도 <syntaxhighlight lang="pascal" inline>var a: integer = 10000;</syntaxhighlight>.</ref> 다만 약간 헷갈릴 수 있는 부분이 있는데, 매개변수의 이름에 val이나 var를 사용하면 이를 프로퍼티로 간주하여 클래스 안에 변수는 물론 getter와 setter도 만들어주는 반면, val이나 var가 없으면 그냥 생성자(constructor)에 쓸 매개변수로 취급한다. 또한 과도하게 엄격한 예외 처리를 강요하는 [[자바]]와는 달리 모든 예외 처리를 강제하지 않는다. [[자바]]에서는 이른바 checked error라고 해서 모든 예외를 다 프로그래밍으로 처리함으로써 오류 문제에 단단한 코드를 만들려고 했지만 프로그래머들은 지나친 엄격함에 시달리다 못해 그냥 안 받아도 되는 RuntimeException 같은 걸로 다 때워버리든가 해버려서 오히려 프로그램을 부실하게 만들었다. 코틀린은 이런 문제점을 해소한 셈이다. [[자바]]와는 달리 줄 끝에 세미콜론을 쓰지 않는 것도 차이. 요즘 인기 있는 언어들인 [[파이썬]], [[Go]]<del>(응?)</del><ref>Go는 정확히 말하면 세미콜론을 없앤 것은 아니고 [[컴파일]]할 때 줄 끝에 자동으로 세미콜론을 붙여 준다. 그때문에 주의할 부분들이 있다. 예를 들어 함수를 정의할 때 여는 중괄호를 함수 형식 정의와 같은 줄에 쓰지 않으면 [[컴파일]] 오류를 일으킨다.</ref>, [[스위프트]]도 역시 줄끝에 세미콜론을 쓰지 않는다. 또한 [[자바]]는 달랑 Hello World! 하나 출력하려고 해도 무조건 클래스를 만들고 그 안의 메서드에 코드를 넣어야 하지만 코틀린은 클래스에 속하지 않는 함수를 허용한다. 따라서 [[C]] 수준으로 간단해진다. <syntaxhighlight lang="kotlin"> fun main() { println("Hello, world!") } </syntaxhighlight> 이걸로 땡이다. [[자바]]는? <syntaxhighlight lang="java"> public class HelloWorld { public static void main(String args[]) { System.out.println("Hello World!"); } } </syntaxhighlight> ===안전함=== 코틀린이 강조하는 또 하나의 특징은 안전함이다. 코틀린은 null 값이 들어가도 되는 변수(nullable)와 그렇지 않은 변수를 구분한다. 기본은 nullable이 아니며 nullable로 지정하려면 변수의 타입 뒤에 ? 기호를 붙여 줘야 한다. 이로 인해 null 값을 잘못 사용해서 생길 수 있는 [[널 참조]] 문제<ref>이른바 The Billion Dollar Mistake라고 부른다. 토니 호어가 알골 언어를 설계하는 과정에서 좀 쉽게 가자는 마음에 널 참조를 허용했는데 이 때문에 수십 년 동안 일어난 문제가 'billion dollar' 수준으로 손해가 될 만큼 엄청나다는 것을 뜻하는 말.</ref>를 컴파일 단계에서 더 많이 잡아준다. <syntaxhighlight lang="kotlin"> var output: String output = null // Compilation error val name: String? = null // Nullable type println(name.length()) // Compilation error </syntaxhighlight> 또한 null이 아닐 때에만 어떤 코드를 실행할 수 있도른 간편한 방법을 제공한다. <syntaxhighlight lang="kotlin"> something?.let { println("Not-null") } ?: run { println("Null") } </syntaxhighlight> 변수 something이 null이면 {{InlineCode|lang="kotlin"|println("Null")}}이, null이 이나면 {{InlineCode|lang="kotlin"|println("Not-null")}}이 실행된다. ===현대적=== 최근에 유행하는 [[고차함수]]나 [[클로저]], [[람다식]] 같은 개념들을 지원한다. [[자바]]도 버전 8부터는 [[클로저]]나 [[람다식]]을 지원하지만 사용하려면 좀 복잡한데, 코틀린으로 하면 훨씬 간단하다. <syntaxhighlight lang="kotlin"> fun <T> lock(lock: Lock, body: () -> T): T { lock.lock() try { return body() } finally { lock.unlock() } } </syntaxhighlight> [[고차함수]]의 예. lock 함수의 두 번째 매개변수는 <code>body: () -> T</code>로 되어 있는데, 이는 매개변수가 없고 T 유형의 반환값을 가지는 함수를 매개변수로 받는다는 뜻이며, 함수 안에서는 이를 <code>body</code>로 참조해서 실행시킬 수 있다. ==기본 문법== 일단 기본적인 문법은 다음과 같다. ===변수 선언=== 변수를 선언하려면 {{InlineCode|lang="kotlin"|var}}(variable), 또는 {{InlineCode|lang="kotlin"|val}}(value) 키워드를 사용한다. val은 한번 선언하고 초기값을 부여하면 변경할 수 없는, 즉 읽기만 가능한 변수로 [[자바]]의 {{InlineCode|lang="java"|final}}과 같은 기능을 한다. 반면 {{InlineCode|lang="kotlin"|var}}는 값을 변경할 수 있는 변수다. 가장 기본이 되는 형식은 다음과 같다. <syntaxhighlight lang="kotlin"> // val [변수 이름]:[변수 유형] = [대입할 값] // var [변수 이름]:[변수 유형] = [대입할 값] var num: Int = 1 val num: Int = 2 num = 3 // Error! </syntaxhighlight> [[C]]나 [[자바]]와는 달리 변수 이름을 먼저 쓰고 : 기호 다음에 변수의 유형을 쓴다. [[Go]]가 이와 비슷한 방식을 사용하고 있다. 또한 자바는 기본 유형은 int, float처럼 모두 소문자지만 코틀린은 Int, Float와 같이 모두 대문자로 시작한다. [[자바]]는 기본 유형인 int와 클래스인 Integer 사이, float와 Float 사이에 박싱 및 언박싱이 일어나지만 코틀린은 그런 거 없다. 코틀린은 var든 val이든 선언할 때 초기화를 해 주는 게 원칙이다. 다만 기본 형식이 아닌 클래스 var이라면 lateinit 키워드를 줘서 다른 곳에서 초기화를 하되 그 전에는 쓰지 않을 것이라고 알려준다. 만약 이렇게 해 놓고 초기화 하기 전에 사용하면 [[컴파일]] 오류를 일으킨다. 또한 val은 초기화하고 나면 값을 변경할 수 없지만 객체를 대입했다면 객체의 필드에 다른 값을 넣을 수는 있다. 물론 변경할 수 있는 필드 한정이다. 리스트나 맵 같은 유형도 클래스이기 때문에 객체를 val로 써도 역시 내용을 바꿀 수 있지만 기본적으로 List, Map과 같은 클래스들은 immutable이기 때문에 내용을 바꿀 수 없다. 내용을 바꾸고 싶다면 MutableList, MutableMap과 갈이 앞에 Mutable이 붙는 클래스를 써야 한다. 초기화 대입값에 따라서 추측하는 기능이 있어서 변수 선언 때 타입을 안 쓸 수도 있다. <syntaxhighlight lang="kotlin"> var name = "John Doe" // name은 자동으로 String 타입이 된다. name = 1 // Error! var unknown // Error! </syntaxhighlight> 주의할 것은, 일단 초기화를 하고 나면 [[파이썬]]처럼 name에 다른 타입의 값을 집어넣을 수 없다. 코틀린은 [[자바]]와 마찬가지로 정적 타이핑 언어다. 선언 시점에서 초기 대입값에 따라 변수 타입이 결정되므로 다른 타입의 값을 넣으려고 하면 컴파일 단계에서 오류가 난다. 또한 변수를 선언만 하고 초기 대입값이 없으면 타입을 추정할 수 없으므로 이 역시 에러가 난다. 변수를 선언할 때 값을 대입하지 않을 거라면 타입을 반드시 지정해 줘야 한다. 기본적으로 코틀린의 변수에는 [[null]]을 대입할 수 없다. 어떤 변수에 [[null]]을 대입할 수 있게 하려면, 즉 [[nullable]]로 선언하려면 반드시 타입 뒤에 ? 표시를 붙여줘야 한다. <syntaxhighlight lang="kotlin"> var he: String = "John Doe" // non-nullable var she: String? = "Jane Doe" // nullable he = null // Error! she = null // Okay. </syntaxhighlight> 물론 기본값이 [[nullable]]이 아니라는 것은 될 수 있으면 [[nullable]]을 쓰지 말라는 것이다. [[자바]]와 호환성 때문에 안 쓸 수 없다든가 하는 어쩔 수 없는 때에만 쓰도록 하자. ===함수 선언=== 함수를 선언하려면 {{InlineCode|lang="kotlin"|fun}} 키워드를 사용한다. <del>함수는 즐겁다.</del> 변수 선언 때처럼 반환값 타입을 함수 매개변수 정의 뒤 : 다음에 써야 한다. <syntaxhighlight lang="kotlin"> fun sum(a: Int, b: Int): Int { return a + b } // 위 함수를 다음과 같이 축약할 수도 있다. fun sum(a: Int, b: Int) = a + b </syntaxhighlight> 코틀린은 함수 선언에서만이 아니라 여기 저기서 중괄호 쓸 일이 많이 줄어든다. 변수와 마찬가지로 함수도 [[null]] 값을 반환값으로 쓰려면 함수 정의의 반환값 타입 뒤에 {{InlineCode|lang="kotlin"|?}}를 붙여줘야 한다. ===조건문 및 반복문=== 자바처럼 if-else, when 같은 조건문과 while, for 같은 반복문을 제공한다. 그러나 두드러진 차이가 있다. <syntaxhighlight lang="kotlin"> val i: Int = 1 val test: String = if (i == 0) "ok" else "not ok" println(test) </syntaxhighlight> 이렇게 if-else 문을 대입문에 사용할 수 있다. C나 자바는 Elvis (?:) 연산자로 비슷한 일을 할 수 있는데, 코틀린은 ? 연산자를 null-safe 기능을 위해 쓰기 때문에 이 연산자를 쓸 수 없다. 대신 if-else 문을 쓰면 된다. 코틀린은 [[C]]나 [[자바]]의 {{InlineCode|lang="java"|switch}}를 대체하는 {{InlineCode|lang="kotlin"|when}}을 제공한다. 기본 기능은 {{InlineCode|lang="java"|switch}}와 비슷하지만 조건을 테스트하는 유연성이 훨씬 좋다. 다만 break 문이 없으므로 어떤 조건에 해당하는 명령들을 실행하고 나면 무조건 {{InlineCode|lang="kotlin"|when}} 바깥으로 빠져나간다. <syntaxhighlight lang="kotlin"> val i: Int = 101; when(i) { 1 -> println("one") 2 -> println("two") in 3 .. 10 -> println("three to ten") !in 0 .. 100 -> println("more than 100") else -> println("I don't know") } </syntaxhighlight> {{InlineCode|lang="kotlin"|when}} 안에서는 {{InlineCode|lang="kotlin"|case}} 대신 그냥 평가값만 써 주면 되고 범위를 지정할 수도 있다. 함수도 쓸 수 있고 객체의 필드 또는 메서드를 사용할 수도 있고, 평가식도 사용할 수 있다. <syntaxhighlight lang="kotlin"> val i: List<Int> = listOf(1, 2, 3, 4) when { (i.size % 2 == 1) -> println("The size is odd.") (i.size % 2 == 0) -> println("The size of even.") } </syntaxhighlight> ===클래스와 객체=== ====클래스 정의하기==== 클래스 정의는 [[자바]]와 비슷하다. <syntaxhighlight lang="kotlin"> class Sample { } </syntaxhighlight> 그런데 상속 관련 문법은 extends를 안 쓰고 : 기호를 쓰기 때문에 오히려 [[C++]]나 [[C샵|C#]]와 비슷해 보인다. <syntaxhighlight lang="kotlin"> open class Base(num: Int) class Derived(num: Int) : Base() { } </syntaxhighlight> 코틀린에서 모든 클래스는 기본값이 [[자바]]의 {{InlineCode|lang=java|final}}이다. 즉 상속 불가다. 상속을 허용하려면 {{InlineCode|lang=kotlin|open}} 키워드를 써 줘야한다. 즉, [[자바]]는 {{InlineCode|lang=java|final}}로 지정하지 않으면 어떤 클래스든 상속 가능이지만 코틀린은 반대로 {{InlineCode|lang=kotlin|open}}으로 지정하지 않으면 어떤 클래스든 상속 불가다. 이는 클래스 안의 메서드에도 마찬가지다 메서드에 {{InlineCode|lang=kotlin|open}}을 붙이지 않으면 오버로딩이 안 된다. 이렇게 상속을 기본으로 막아놓고 지정한 것만 허용하는 정책은 C++또는 [[C샵|C#]]과 같은 개념이다.<ref>코틀린을 잘 보다 보면 은근히 [[C샵|C#]]을 닮은 구석이 많다. 사실 [[C샵|C#]]이 사용성으로는 최강이라는 평가도 많으니 참고할 만도 하다.</ref> ====클래스 생성자==== 보통 클래스 생성자가 있을 때에는 매개변수를 받아서 필드를 설정하는데, 코틀린은 이를 간편하게 할 수 있다. <syntaxhighlight lang="kotlin"> open class Person(private val name: String, private val age: Int) { } val john = Person("Jonn Doe", 42) </syntaxhighlight> 위와 같이 하면 {{InlineCode|lang="kotlin"|Person}} 클래스 안에 {{InlineCode|lang="kotlin"|name}}과 {{InlineCode|lang="kotlin"|age}} 두 가지 필드가 생기고, 객체를 만들 때 생성자를 사용해서 이들 필드를 설정할 수 있다. ====object==== [[자바]]와 구별되는 것으로는 클래스가 아니라 객체를 정의해 버리는 것도 가능하다. 이게 무슨 뜻이냐 하면, 싱글톤 클래스, 다시 말해서 어떤 클래스의 정의를 이용한 객체(인스턴스)가 딱 하나만 존재하는 클래스를 정의할 수 있는 것. {{InlineCode|lang="kotlin"|class}} 대신 {{InlineCode|lang="kotlin"|object}} 키워드를 사용한다. [[자바]]는 일단 클래스를 정의한 다음에 생성자를 private로 규정해서 외부에서 객체를 못 만들게 한 다음에 static 팩토리 메서드로 인스턴스가 하나만 존재하도록 하고 어쩌고... 이렇게 복잡하게 구현해야 하는데 코틀린은 {{InlineCode|lang="kotlin"|object}} 키워드로 아주 간단하게 해결할 수 있다. <syntaxhighlight lang="kotlin"> object Singleton { var count = 0; fun addCount(delta: Int = 1) { count += delta; } } </syntaxhighlight> 객체의 이름이 꼭 Singleton일 필요는 없다. 이렇게 정의한 싱글톤 객체는 바로 이름과 함께 쓰면 된다. <syntaxhighlight lang="kotlin"> Singleton.addCount() println("count is ${Singleton.count}") </syntaxhighlight> 단, {{InlineCode|lang="kotlin"|object}}는 컨스트럭터를 가질 수 없다는 점에 유의하자. =====companion object===== 코틀린에는 {{InlineCode|lang="java"|static}} 키워드가 없다. 즉 같은 클래스의 인스턴스들끼리 공유하는 변수나 함수를 만들 수 없다. 대신 {{InlineCode|lang="kotlin"|companion object}}로 같은 일을 할 수 있다. <syntaxhighlight lang="kotlin"> class Example { companion object { val name = "Example class" } } println("The class name is: ${Example.name}") </syntaxhighlight> 이런 방식은 다른 프로그래밍 언어들과 비교하면 상당히 낯설지만 그럴 만한 이유가 있다. [[자바]]에서는 {{InlineCode|lang="java"|static}}과 그렇지 않은 멤버들이 뒤엉켜 있기 쉬운데, 코틀린은 {{InlineCode|lang="java"|static}}에 해당되는 멤버들이 모두 {{InlineCode|lang="kotlin"|companion object}} 블록 안에 들어가야 하므로 엄격히 구분된다는 장점이 있다. ====확장==== 기존 클래스에 새로운 메서드를 넣고 싶다면 [[자바]]에서는 클래스를 상속 받아서 추가해야 했다. 코틀린은 그럴 필요 없이 그냥 기존 클래스를 확장해서 새로운 메서드를 추가할 수 있는 방법을 제공한다. 또한 변수나 함수가 꼭 클래스 안에 있지 않아도 된다. <syntaxhighlight lang="kotlin"> package com.example val NAME = "John Doe" fun printName() : String { println("$NAME") } </syntaxhighlight> 이렇게 해 놓고, <syntaxhighlight lang="kotlin"> com.example.printName() </syntaxhighlight> 다른 패키지에서 쓰려면 이렇게 패키지 이름을 붙여서 참조하면 된다. {{각주}} [[Category:프로그래밍 언어]]
이 문서에서 사용한 틀:
틀:InlineCode
(
원본 보기
)
틀:각주
(
원본 보기
)
코틀린
문서로 돌아갑니다.
도구
여기를 가리키는 문서
가리키는 글의 최근 바뀜
특수 문서 목록
문서 정보