1장. 코틀린이란 무엇이며, 왜 필요한가?

Posted by yunki kim on January 7, 2024

코틀린은 자바 플랫폼에서 돌아가는 프로그래밍 언어다. 코틀린은 간결하고 실용적이며, 자바 코드와 상호운용성(interopreability)을 중시한다.

1. 코틀린의 주요 특성

1.1 대상 플랫폼: 서버, 안드로이드 등 자바가 실행되는 모든 곳.

코틀린의 주목적은 현재 자바가 사용되고 있는 모든 용도에 적합하면서 더 간결하고 생산적인 안전한 대체 언어를 제공하는 것이다. 코틀린은 개발 과정에서 수행해야 하는 모든 과업에 있어서 폭넓게 생산성을 향상시켜준다. 코틀린은 구체적인 영역의 문제를 해결하거나 특정 프로그래밍 패터다임을 지원하는 여러 라이브러리와 잘 융합된다. 또 한, 코틀린은 자바와 자바스크립트로 컴파일 할 수 있기에 코틀린 코드를 브라우저나 노드에서 실행할 수 있다.

1.2 정적 타입 지정 언어

코틀린은 정적 타입 언어이다. 그러나 자바와 달리 모든 변수 타입을 직접 명시하지 않아도 된다. 코틀린 컴파일러가 문맥으로부터 변수 타입을 자동으로 유추하는 타입 추론(type inference)를 제공하기 때문이다. 정적 타입 지정으로 인한 장점은 다음과 같다.

  • 성능: 실행 시점에 어떤 메서드를 호출할지 알아내는 과정이 필요 없기에 메서드 호출이 더 빠르다.
  • 신뢰성: 컴파일러가 프로그램의 정확성을 검증하기 때문에 실행 시 프로그램이 오류로 중단될 가능성이 더 적어진다
  • 유지 보수성: 코드에서 다루는 객체가 어떤 타입에 속하는지 알 수 있기에 처음 보는 코드를 다룰 때 더 쉽다.
  • 도구 지원: 정적 타입 지정을 활용하면 더 안전하게 리팩토링할 수 있고, 도구는 더 정확한 코드 완성 기능을 제공할 수 있으며, IDE의 다른 지원 기능도 더 잘 만들 수 있다.

자바에 있는 내용을 코틀린에서도 쉽게 적용할 수 있다. 그러나 코틀린만 지원하는 특성 역시 존재한다.

  • 코틀린은 nullable type을 지원한다. 널이 될 수 있는 타입을 지원함에 따라서 컴파일 시점에 null pointer expection이 발생할 수 있는지를 검사할 수 있어서 프로그램의 신뢰성을 높일 수 있다.
  • 함수 타입(function type)을 지원한다.

1.3 함수형 프로그래밍과 객체지향 프로그래밍

함수형 프로그래밍 핵심 개념에 대한 내용은 ‘함수형 프로그래밍’ 포스팅을 참고하자. 함수형 프로그래밍을 사용하면 다음과 같은 이점을 누릴 수 있다.

  • 간결성: 함수형 코드는 그에 상응하는 명령형(imperative) 코드에 비해 더 간결하고 우아하다. 함수를 값처럼 활용할 수 있어서 더 강력한 추상화를 할 수 있기에 코드 중복을 막을 수 있다.
  • 다중 스레드를 사용해도 안전(safe multithreading) 하다. immutable 하기 때문이다.
  • 테스트하기 쉽다: 부수 효과가 있는 함수는 그 함수를 실행할 때 필요한 전체 환경을 구성하는 준비 코드(setup code)가 따로 필요하다. 순수 함수는 그런 준비 코드 없이 독립적으로 테스트할 수 있다.

코틀린은 처음부터 다음과 같은 기능을 이용해 함수형 프로그래밍을 지원해 왔다.

  • 함수 타입을 지원함에 따라 어떤 함수가 다른 함수를 파라미터로 받거나 함수가 새로운 함수를 반환할 수 있다.
  • 람다 식을 지원함에 따라 번거로운 준비 코드를 작성하지 않아도 코드 블록을 쉽게 정의하고 여기저기 전달할 수 있다.
  • 데이터 클래스는 불변적인 값 객체(value object)를 간편하게 만들 수 있는 구문을 제공한다.
  • 코틀린 표준 라이브러리는 객체와 컬렉션을 함수형 스타일로 다룰 수 있는 API를 제공한다.

코틀린은 함수형 프로그래밍을 지원하는 것이지 강제하지는 않는다. 따라서 필요하다면 명령형 방식으로 직접 변경 가능한 데이터와 부수 효과를 활용하는 함수를 작성할 수 있다.

1.4 무료 오픈소스

코틀린은 언어, 컴파일러, 라이브러리 등 코틀린과 관련된 모든 도구는 오픈소스이다.

2. 코틀린 서버 프로그래밍

개발자들은 서버 개발을 위해 오랫동안 자바로 개발을 하면서 이에 도움이 되는 기술과 프레임워크를 만들어왔다. 새로운 프레임워크는 기존 프레임워크나 기술을 확장하고 개선하거나 대치하며, 이미 오랫동안 쓰인 기존 시스템과 새로운 코드를 통합해야 한다.

이런 환경에서 코틀린은 기존 자바 코드와 완벽히 호환된다는 장점을 가진다. 코틀린은 새로운 컴포넌트를 작성하거나 기존 서비스 코드를 코틀린으로 이식해야 하는 것을 원활히 지원한다. 자바 클래스를 코틀린으로 확장하는 경우, 코틀린 클래스 안에서 자바 애너테이션을 사용하는 경우에도 문제가 없다. 그러면서도 시스템 코드는 더 간결해지고 더 신뢰성이 높아지며, 유지 보수하기 쉬워진다.

3. 코틀린의 철학

코틀린의 철학은 다음과 같은 4 가지 키워드로 설명할 수 있다.

3. 1실용성

코틀린 설계는 대규모 시스템을 개발해본 IT 업계 경험을 바탕으로 이뤄졌으며, 수많은 개발자들의 사용에 잘 들어맞을 수 있게 주의 깊게 언어 특성을 선택했다. 때문애 실제 프로젝트에서 문제를 해결할 때 많은 도움이 된다.

코틀린은 다른 프로그래밍 언어에서 이미 검증된 해법과 기능에 의존한다. 이로 인해 언어의 복잡도가 줄어들고 이미 알고 있는 기존 개념을 통해 코틀린을 더 쉽게 배울 수 있다. 코틀린은 특정 프로그래밍 스타일, 패러다임의 사용을 강제하지 않는다. 따라서 자바를 알고 있다면 자바 스타일로 코틀린을 작성하면서 나중에 알게 된 코틀린의 특성을 활용해 더 간결한 코드를 작성할 수 있다.

코틀린은 도구를 강조한다. 코틀린 컴파일러 개발은 intelliJ 개발과 맞물려 이뤄져 왔다. 그리고 코틀린 언어의 특성은 항상 도구의 활용을 염두에 두고 있다. 예컨대 IDE가 추천하는 더 간결한 코드를 보면서 코틀린 언어의 특성을 잘 이해하고 적용할 수 있다.

3.2 간결성

개발자는 코드를 작성하는 시간 보다 읽는 데에 더 많은 시간을 사용한다. 때문에 코드가 간결해야 읽는 시간을 줄일 수 있다. 어떤 언어가 간결하다는 것은 작성된 코드의 의도를 쉽게 이해할 수 있는 구문 구조를 제공하고, 의도 파악에 방해가 되는 부가적인 코드가 적다는 의미다.

코틀린은 설계 당시 코드에서 의미가 없는 부분을 줄이기 위해 많은 노력이 들어갔다. getter, setter, 생성자 파라미터를 필드에 대입하기 위한 로직 등 여러 준비 코드를 코트린은 묵시적으로 제공한다. 또 한, 코틀린은 기능이 다양한 표준 라이브러리를 제공해서 반복되거나 길어질 수 있는 코드를 라이브러리 함수 호출로 대치할 수 있다. 때문에 컬렉션에서 원소를 찾는 등의 작업을 위해 코드를 명시적으로 작성하지 않아도 된다.

반면 소스코드를 가능한 짧게 만드는 것은 코틀린 설계 목표가 아니다. 예를 들어 코틀린은 연산자 오버로딩을 지원하지만 언어가 제공하는 않는 연산자를 임의로 정의할 수 없다. 때문에 이상한 기호들로만 이루어진 코드를 작성할 수 없다.

3.3 안전성

프로그래밍 언어가 안전하다는 것은 프로그램에서 발생할 수 있는 오류 중에서 일부 오류를 프로그램 설계가 원천적으로 방지해 준다는 뜻이다.

코틀린은 JVM 환경에서 동작하기에 버퍼 오버플로, 동적 할당한 메모리 오 사용으로 인해 발생하는 문제를 방지하고 메모리 안전성을 보장한다. 또 한, 자바보다 더 적은 비용으로 타입 안전성을 보장한다(타입 추론을 지원하기 때문에).

여기서 더 나아가 컴파일 시점 검사를 통해 더 많은 오류를 방지해 준다. 대표적으로 null pointer exception을 없애기 위해 노력했다. 코틀린의 타입 시스템은 null이 될 수 없는 값을 추적하고, 실행 시점에 null pointer exception이 발생할 수 있는 연산을 사용하는 코드를 금지한다. 이를 위해선 다음과 같은 약간의 코드만 추가하면 된다.

1
2
val s: String? = null // null이 될 수 있다
val s2: String = "" // null이 될 수 없다

또 한, 널이 될 수 있는 값을 다루는 편리한 방법을 제공해 애플리케이션이 null pointer exception으로 인해 중단되는 경우를 많이 줄여준다.

코틀린은 ClassCastException도 방지해 준다. 어떤 객체를 다른 타입으로 캐스트 할 때 검사하지 않는다면 ClassCastException이 발생할 수도 있다. 코틀린은 타입 겸사와 캐스트가 한 연산자로 이뤄진다. 어떤 객체의 타입을 검사했고 그 객체가 그 타입에 속한다면 해당 타입의 메서드나 필드 등의 멤버를 별도의 캐스트 없이 사용할 수 있다.

1
2
3
if (value is String) {
	println(value.toUpperCase())
}

3.4 상호운용성(interoperability)

코틀린은 라이브러리가 어떤 API를 제공하든 간에 그 API를 활용할 수 있다. 코틀린은 기존 자바 라이브러리를 가능하면 최대한 활용한다. 예컨대, 코틀린은 컬렉션에 있어서 자바 표준 라이브러리 클래스에 의존한다. 다만 컬렉션을 더 쉽게 사용할 수 있게 몇 가지 기능만 추가로 제공한다.

코틀린이 제공하는 도구도 다중 언어 프로젝트를 완전히 지원한다. 따라서 다음과 같은 동작이 가능하다.

  • 자바와 코틀린 소스 파일을 자유롭게 내비게이션 할 수 있다.
  • 여러 언어로 이뤄진 프로젝트를 디버깅하고 서로 다른 언어로 작성된 코드를 언어와 관련 없이 한 단계씩 실행할 수 있다.
  • 자바 메서드를 리팩토링해도 그 메서드와 관련 있는 코틀린 코드까지 제대로 변경된다. 역으로 코틀린 메서드를 리팩토링해도 자바 코드까지 모두 자동으로 변경된다.

4. 코틀린 코드 컴파일

코틀린 소스코드는 보통 .kt 라는 확장자를 가지는 파일에 작성한다. 코틀린 컴파일러는 자바 컴파일러처럼 소스코드를 분석해서 .class 파일을 만들어낸다. 만들어진 .class 파일은 개발 중인 애플리케이션 유형에 맞는 표준 패키징 과정을 거쳐 실행될 수 있다. 커맨드 라인으로 코틀린 코드를 컴파일하고 실행하는 방법은 다음과 같다.

1
2
kotlinc <source file or directory> -include-runtime -d <jar name>
java -jar <jar name>

코틀린 빌드 과정은 대략 다음과 같다. kotlin build process 코틀린 컴파일러로 컴파일한 코드는 코틀린 런타임 라이브러리에 의존한다. 런타임 라이브러리에는 코틀린 자체 표준 라이브러리 클래스와 코틀린에서 자바 API의 기능을 확장한 내용이 들어있다. 코틀린으로 컴파일한 애플리케이션을 배포할 때는 런타임 라이브러리도 함께 배포해야 한다.

출처 - 코틀린 인 액션