[Kotlin] 코틀린의 철학
코틀린이 자바와의 상호운용성에 초점을 맞춘 실용적이고 간결하며 안전한 언어라고 설명하는 경우가 자주 있다.
여기서 말하는 실용성, 간결성, 안전성, 상호운용성은 각각 어떤 뜻인지 살펴보자.
실용성
코틀린은 실제 문제를 해결하기 위해 만들어진 실용적인 언어다.
코틀린은 대규모 시스템을 개발해본 다년간의 IT업계 경험을 바탕으로 설계했고, 수많은 소프트웨어 개발자들의 사용에 잘 들어맞을 수 있도록 언어 특성을 선택했다. 여기에 Jetbrains 나 코틀린 커뮤니티 내부의 개발자들이 다년간 코틀린 초기 버전을 사용하면서 전달한 피드백이 현재 발표된 최종 코틀린 버전에 반영돼 있다.
이런 이유를 바탕으로 프로젝트에서 문제를 해결할 때 코틀린이 도움이 될 수 있다고 자신 있게 말할 수 있다.
코틀린은 연구를 위한 언어가 아니다.
최신 프로그래밍 언어 설계를 앞서 채택하거나 전산학계에서 연구 중인 혁신적인 아이디어를 코틀린을 통해 탐구하려고 하지 않는다.
코틀린은 다른 프로그래밍 언어가 채택한 이미 성공적으로 검증된 해법과 기능에 의존한다.
-> 이로 인해 언어의 복잡도가 줄어들고 이미 알고 있는 기존 개념을 통해 코틀린을 더 쉽게 배울 수 있다.
코틀린은 어느 특정 프로그래밍 스타일이나 패러다임을 사용할 것을 강제로 요구하지 않는다.
코틀린을 처음 배우는 사람은 자바에서 사용해 온 익숙한 프로그래밍 스타일이나 기법을 활용할 수 있다.
나중에 코틀린의 더 강력한 특성을 발견하고 자신의 코드에 적용하는 방법을 배우고 나면 그 특성을 잘 활용해서 간결하게 코드를 작성할 수 있다.
-> 자신에게 편한 방식으로 프로그래밍하다, 코틀린의 방식을 배워가며 자연스럽게 자신의 코드에 녹일 수 있다.
실용성에 있어 코틀린의 다른 측면은 도구를 강조한다는 점이다.
좋은 언어만큼이나 편리한 개발 환경도 생산성 향상에 필수적이다. 따라서 언어를 먼저 설계한 다음에 IDE지원에 대해 고민해서는 안 된다.
코틀린의 경우 IntelliJ IDEA의 개발과 컴파일러의 개발이 맞물려 이뤄져 왔다. 코틀린 언어의 특성은 항상 도구의 활용을 염두에 두고 설계돼 왔다.
코틀린의 여러 특성을 배울 때도 IDE의 코틀린 언어 지원이 중요한 역할을 한다. 흔히 쓰이지만 더 간결한 구조로 바꿀 수 있는 대부분의 코드 패턴을 도구가 자동으로 감지해서 수정하라고 제안한다. 자동 수정 안내를 살펴보면서 코틀린 언어의 특성을 이해할 수 있고, 잘 이해하면 자신의 코드에 코틀린의 특성을 적용하는 방법을 배울 수 있다.
코틀린의 실용성 정리
- 코틀린은 실제 문제를 해결하기 위한 언어다.(연구를 위한 언어가 아님)
- 다른 프로그래밍 언어가 채택하고, 사용되고 있는 검증된 해법과 기능에 의존한다.
- 코틀린은 어느 특정 프로그래밍 스타일이나 패러다임을 사용할 것을 강제하지 않는다.
- 자신에게 편한 방식으로 프로그래밍하다, 코틀린의 방식을 배워가며 자신의 코드에 녹여볼 수 있다.
- 코틀린은 도구를 강조한다. (코틀린의 개발사는 Jetbrains로 IntelliJ IDEA도 여기서 개발했다.)
- 코틀린 언어의 특성은 항상 도구의 활용을 염두에 두고 설계돼 왔다.
- 코틀린의 여러 특성을 배울 때 도구의 지원을 받으면 자연스럽게 배울 수 있다.
간결성
개발자는 코드를 새로 작성하는 시간보다 기존 코드를 읽는 시간이 더 길다는 사실이 알려져 있다.
소프트웨어의 어느 부분을 수정해야 한다면 엄청난 양의 코드를 읽어야 한다.
(이것은 옆에 있는 동료 또는 내가 작성했을 수 있고, 이미 퇴사한 사람의 코드일 수 있다)
코드는 간단하고 간결할수록 내용을 파악하기가 쉽다.
설계가 좋고 각 부분의 역할을 잘 표현해주는 적절한 이름이 붙어있다면 내용을 파악할 때 큰 도움이 된다.
하지만 어떤 언어를 사용해 코드를 작성했고, 그 언어가 얼마나 간결한 언어인지도 중요하다.
어떤 언어가 간결하다란?
- 그 언어로 작성된 코드를 읽을 때 의도를 쉽게 파악할 수 있는 구문 구조를 제공
- 의도를 달성하는 방법을 이해할 때 방해가 될 수 있는 부가적인 준비 코드가 적다는 뜻
코틀린은 프로그래머가 작성하는 코드에서 의미가 없는 부분을 줄이고, 언어가 요구하는 구조를 만족시키기 위해 별 뜻은 없지만 프로그램에 꼭 넣어야 하는 부수적인 요소를 줄이기 위해 많은 노력을 기울였다.
예를들면 Getter, Setter, 생성자 파라미터를 필드에 초기화하기 위한 로직 등 자바에 존재하는 여러 가지 번거로운 준비 코드를 코틀린은 묵시적으로 제공한다. 즉, 코틀린 소스코드는 준비 코드로 인해 지저분해지는 일이 없다!
코드가 불필요하게 길어지는 또 다른 이유는 컬렉션에서 원소를 찾는 것과 같은 일반적인 작업을 수행하기 위해 명시적으로 작성해야만 하는 코드의 양이 상당하기 때문이다.
코틀린은 기능이 다양한 표준 라이브러리를 제공하기 때문에 반복되거나 길어질 수 있는 코드를 라이브러리 함수 호출로 대치할 수 있다.
코틀린은 람다를 지원하기 때문에 작은 코드 블록을 라이브러리 함수에 쉽게 전달할 수 있다.
따라서 일반적인 기능을 라이브러리 안에 캡슐화하고 작업에 따라 달라져야하는 개별적인 내용을 사용자가 작성한 코드 안에 남겨둘 수 있다.
코드가 더 간결하면 쓰는 데 시간이 덜 걸린다. 더 중요한 것은 읽는 데도 시간이 덜 걸린다는 점이다.
간결성을 생산성을 향상시켜주고 개발을 더 빠르게 진행할 수 있게 해준다.
코틀린의 간결성 요약
- 코드가 간단하고 간결하다.
- Getter, Setter 같은 준비 코드가 필요없다.
- 다양한 표준 라이브러리를 제공한다. (직접 구현할 코드가 줄어든다)
- 작업에 따라 달라져야하는 개별적인 내용을 함수로 넘겨줄 수 있다.
안전성
일반적으로 프로그래밍 언어가 안전하다는 말은 프로그램에서 발생할 수 있는 오류 중에서 일부 유형의 오류를 프로그램 설계가 원천적으로 방지해준다는 뜻이다. 이것은 절대적인 것은 아니다. 어떤 언어도 발생하는 모든 예외를 막을 수는 없다.
오류를 방지하는 데는 대가가 따른다. 컴파일러에게 프로그램이 어떻게 작동해야 하는지 정보를 더 자세히 제공해야 컴파일러가 프로그램 코드와 프로그램의 작동 의도에 대한 정보가 일치하는지를 검증할 수 있다.
더 큰 안전성을 얻기 위해서는 프로그램에 더 많은 정보를 덧붙여야 한다. 생산성이 하락하는 것을 감수해야 하며 안전성과 생산성 사이에는 트레이드 오프 관계가 성립한다.
코틀린은 자바보다 더 높은 수준의 안전성을 달성하되 전체 비용은 더 적게 지불하고 싶었다.
코틀린을 JVM에서 실행한다는 사실은 이미 상당한 안전성을 보장할 수 있다는 뜻이다.
JVM을 사용하여 다음과 같은 이득을 취할 수 있다.
- 메모리 안전성을 보장
- 버퍼 오버플로우를 방지
JVM에서 실행되는 정적 타입 지정 언어로써 코틀린은 애플리케이션의 타입 안전성을 보장한다.
하지만 코틀린은 자바보다 더 적은 비용으로 타입 안전성을 사용할 수 있다.
대부분의 경우 코틀린의 컴파일러가 타입을 자동으로 추론해주기 때문에 직접 타입 정보를 지정할 필요가 없다.
val word = "bird"
코틀린은 여기서 한걸음 더 나아가 실행 시점에 오류를 방생시키는 대신 컴파일 시점 검사를 통해 오류를 더 많이 방지해준다.
코틀린은 NullPointerException을 없애기 위해 노력한다. 코틀린의 타입 시스템은 null이 될 수 없는 값을 추적하며, 실행 시점에 NullPointerException이 발생할 수 있는 연산을 사용하는 코드를 금지한다.
어떤 타입이 널이 될 수 있는지 여부를 표시하기 위해서는 오직 ? 한 글자만 추가하면 된다.
val s: String? = null // 널이 될 수 있음
val s2: String = "" // 널이 될 수 없음
코틀린은 널이 될 수 있는 값을 다룰 수 있는 편리한 방법을 다양하게 제공한다.
이런 기능들로 인해 애플리케이션이 NullPointerException으로 인해 갑자기 중단되는 경우를 많이 줄여준다.
코틀린이 방지해주는 다른 예외로 ClassCastException이 있다. 어떤 객체를 다른 타입으로 캐스트하기 전에 타입을 미리 검사하지 않으면 ClassCastException이 발생할 수도 있다.
코틀린에서는 타입 검사와 캐스트가 한 연산자에 의해 이뤄진다.
어떤 객체의 타입을 검사했고, 그 객체가 그 타입에 속한다면 해당 타입의 메서드나 필드 등의 멤버를 별로의 캐스트 없이 사용할 수 있다.
if (value is String) // 타입을 검사한다.
println(value.toUpperCase()) // 해당 타입의 메서드를 사용한다.
코틀린의 안전성 요약
- 코틀린은 안전한 프로그래밍 언어다.
- JVM에서 실행을 한다. (JVM의 안전성을 취함)
- 정적 타입 언어로써 코틀린은 애플리케이션 타입 안전성을 보장한다.
- 코틀린의 컴파일러가 타입 추론을 해주므로, 직접 타입 정보를 명시할 필요가 없다.
- 컴파일 시점 검사를 강화한다.
- NullPointerException의 발생을 줄이기 위해 노력
상호 운용성
자바 프로그래머들이 코틀린을 사용할 때 하는 첫 번째 질문은 "기존 라이브러리를 그대로 사용할 수 있느냐?"일 것이다.
(나도 최근에 물어봤다..)
코틀린은 기존 라이브러리를 그대로 사용할 수 있다.
라이브러리가 어떤 API를 제공하던 간에 코틀린에서 그 API를 활용할 수 있다.
자바 메서드를 호출하거나 자바 클래스를 상속하거나 인터페이스를 구현하거나 자바 애너테이션을 코틀린 코드에 적용하는 등의 일이 모두 가능하다.
코틀린은 상호운영성 측면에서 많은 것을 제공한다.
즉, 자바 코드에서 코틀린 코드를 호출할 때도 아무런 노력이 필요없다. 어떤 장치도 필요없다.
코틀린의 클래스나 메서드를 일반적인 자바 클래스나 메서드와 똑같이 사용할 수 있다.
이를 통해 자바와 코틀린 코드를 프로젝트에서 원하는 대로 섞어 쓸 수 있는 궁극적인 유연성을 발휘할 수 있다.
코틀린은 기존의 자바 라이브러리를 가능하면 최대한 활용한다.
예를 들어 코틀린은 자체 컬렉션 라이브러리를 제공하지 않는다. 자바 표준 라이브러리 클래스에 의존한다.
코틀린에서는 컬렉션을 더 쉽게 활용할 수 있게 몇 가지 기능을 더할 뿐이다.
코틀린에서 자바 API를 호출할 때 객체를 감싸거나 변환할 필요가 없고, 자바에서 코틀린 API를 호출할 때도 마찬가지로 아무런 변환이 필요 없다는 뜻이다. (코틀린이 제공하는 풍부한 API는 실행 시점에 아무런 부가 비용을 야기하지 않는다.)
코틀린이 제공하는 도구도 다중 언어 프로젝트를 완전히 지원한다. 코틀린은 자바와 코틀린 소스 파일이 임의로 섞여 있어도 제대로 프로그램을 컴파일할 수 있다.
- 자바와 코틀린 소스 파일을 자유롭게 내비게이션 할 수 있다.
- 여러 언어로 이뤄진 프로젝트를 디버깅하고 서로 다른 언어로 작성된 코드를 언어와 관계없이 한 단계씩 실행할 수 있다.
- 자바 메서드를 리팩터링해도 그 메서드와 관련 있는 코틀린 코드까지 제대로 변경된다. 역으로 코틀린 메서드를 리팩터링해도 자바 코드까지 모두 자동으로 변경된다.
코틀린의 상호운영성 요약
- 자바의 기존 라이브러리를 그대로 사용할 수 있다.
- 자바 코드에서 코틀린 코드를 호출할 때도 아무런 노력없이 가능하다.
- 즉, 자바와 코틀린 코드를 프로젝트에서 원하는 대로 섞어 쓸 수 있다.
- 코틀린은 자바 표준 라이브러리 클래스에 의존하며, 편의성을 위해 몇 가지 기능을 더했다.
- 코틀린이 제공하는 도구는 다중 언어 프로젝트를 완전히 지원한다.
참고 문헌
- 코틀린 인 액션