[Kotlin in Action] 1장. 코틀린이란 무엇이며, 왜 필요한가?






도서 <코틀린 인 액션 2/e>를 읽으며 코틀린에 대해 이해한 내용을 정리한 글이다.

서론: 코틀린이란?

  • 코틀린(Kotlin)은 Jetbrains에서 개발한 간결하고 안전하며 실용적인 현대 프로그래밍 언어이다.
  • Apache License 2.0가 부여된 오픈소스이다.
  • 다음과 같은 것들이 가능하다!

    • 클래스 본문 없이도 프로퍼티가 포함된 데이터 클래스를 정의
    • val 키워드를 사용한 읽기 전용 프로퍼티 선언
    • 타입 시스템을 통한 NullPointerException 방지
    • 클래스 안에 포함될 필요가 없는 최상위 함수 정의
    • 함수나 생성자를 호출할 때 파라미터 이름을 지정한 인자를 사용
    • 마지막 요소 뒤에 쉼표를 붙이는 트레일링 콤마를 사용
    • 엘비스 연산자



1.1 코틀린의 철학

실용성, 간결성, 안전성, 상호운용성

코틀린은 실용적인 언어이다

  • 실제 문제를 해결하기 위해 만들어졌으며, 이미 알고 있는 개념을 통해 사용할 수 있다.
  • 도구를 강조한다. IDE 플러그인과 컴파일러의 개발이 맞물려있는 만큼 IDE의 코틀린 언어 지원을 적극 활용해야 한다.

코틀린은 간결하다

  • 강력한 타입 추론, 보일러플레이트의 암시적 제공 등을 통해 언제나 읽기 좋고 간결한 코드를 만들 수 있다.
  • 람다와 익명 함수를 통해, 라이브러리에 일반적인 기능을 캡슐화한 뒤 필요한 부분만 전달할 수 있다.
  • 간결하다고 해서 소스코드에 필요한 글자 수를 무조건적으로 짧게 하는 것이 아니다. 읽기 좋고 유지보수하기 쉬운 코드를 지향한다는 것이다.

    예를 들어 코틀린은 미리 정해진 연산자 집합(+, -, in, [] 등)에 대해서는 연산자 오버로딩을 제공한다. 그러나 개발자가 새로운 연산자를 정의할 수는 없다. 새롭게 정의한 개발자만의 연산자는 읽고 이해하기 어려운 코드를 만들며, 추후 유지보수성을 낮출 수 있기 때문이다.

코틀린은 안전하다

  • 프로그램 설계가 오류를 원천적으로 방지할 수 있는 구조이다. 즉 컴파일러가 프로그램이 작동하는 방식에 대해 더 많이 알고 있다. 이 말은 곧 프로그램에 더 많은 정보를 덧붙여야 한다는 뜻이기도 하다. (trade off)

  • JVM이 제공하는 안전성을 누린다.

  • 읽기 전용 변수(val)와 불변 클래스(data)로 멀티 스레드 애플리케이션의 안전성을 보장한다.

  • 여러 번 언급했지만 컴파일 시점에 오류를 발견, 특히 NPE를 발견할 수 있다!
    • 널이 될 수 있는 타입은 타입 이름 끝에 ?를 붙인다.
      fun main() {
          var s: String? = null
          var s2: String = ""
    
          println(s.length) // 컴파일 될 수 없다. 컴파일 시점에 오류를 발견할 수 있음.
          println(s2.length)
      }
    
  • 클래스 타입 변환 예외를 방지하기 위해, 어떤 객체를 다른 타입으로 변환하기 전 타입을 미리 검사해야 한다. 코틀린은 타입 검사와 캐스트를 한 연산자로 수행할 수 있다. (스마트 캐스트)

          fun modify(value: Any) {
              if (value is String) { // 타입 검사, 컴파일러는 이 분기에서 value가 String임을 알게 된다.
                  println(value.uppercase()) // 따라서 따로 변환하지 않고 String 타입 메서드를 사용할 수 있다.
              }
          }
    

코틀린은 상호운용성이 좋다 (Kotlin in JVM)

  • 자바의 기존 라이브러리를 그대로 사용할 수 있다. 자바 메서드 호출, 클래스 상속, 인터페이스 구현 모두 가능.
  • 코틀린은 거의 대부분을 자바 표준 라이브러리 클래스에 의존한다.
  • 자바와 코틀린 소스 파일이 임의로 섞여있어도 둘의 의존관계에 상관없이 컴파일할 수 있다.



1.2 코틀린의 주요 특성

다양한 종류의 애플리케이션 개발이 가능하다

  • 더 나은 자바로서 사용

    • 안드로이드 모바일 애플리케이션
    • 서버 프로그래밍
      • 자바와 호환가능하면서도 NullPointerException을 사전에 방지할 수 있다.
      • Spring, Ktor, http4k
  • 다중 플랫폼

    • JVM이 아닌 곳에서도 돌아간다. 자바스크립트, 이진 코드로도 컴파일이 가능하며, WebAssembly 바이너리 형식으로도 컴파일할 수도 있다!
    • 데스크톱, iOS, 안드로이드, 브라우저

    비즈니스 로직을 하나의 언어로 통일하기 위해 코틀린의 크로스 플랫폼을 사용한다고 한다. 로직을 짠 뒤 UI는 스위프트나 코틀린으로 보내는 느낌으로 돌아간다고~

정적 타입 지정 언어이다

동적 타입 지정 언어(파이썬, 자바스크립트 등)는 타입과 관계없이 모든 값을 변수에 넣을 수 있고, 메서드나 필드 접근에 대한 검증이 실행 시점에 일어난다. 그에 따라 코드가 더 짧아지고 데이터 구조를 유연하게 다룰 수 있으나, 런타임에 예기치 못한 에러를 발견할 위험이 커진다.

반면, 정적 타입 지정 언어는 런타임이 아닌 컴파일 시점에서 오류를 잡아낼 수 있다는 큰 장점이 있다.

  • 성능
    • 어떤 메서드를 호출해야 할지 런타임에 살펴볼 필요가 없어, 메서드 호출이 더 빠르다.
  • 신뢰성
    • 컴파일러가 타입을 통해 프로그램의 일관성을 검증한다. 따라서 실행 시점에 프로그램이 실패할 가능성이 줄어든다.
  • 유지보수성
    • 낯선 코드를 다룰 때 더 쉽게 이해하고 다룰 수 있다.
  • 도구 지원
    • 리팩토링의 신뢰도를 높일 수 있다.
    • Code Completion이나 다른 IDE 기능, AI 툴 등을 활용할 때 정확도를 높일 수 있다.

[타입 추론]

코틀린은 컴파일 시점에 모든 식의 타입이 알려져야 한다. 단, 모두 직접 명시할 필요가 없고, 코틀린 컴파일러가 문맥으로부터 타입 추론을 제공한다.

val x: Int = 1 // 명시적인 타입 지정
val y = 1 // 초기화를 통한 타입 추론

[Null 안정성]

  • 널이 될 수 있는 타입을 지원한다.
    • 자바와 달리 null을 가질 수 있는 변수는 이를 명시해야 한다.
  • 따라서 NPE가 발생하는지 여부를 컴파일 시점에 검사할 수 있어 프로그램의 신뢰성을 높인다.

함수형 프로그래밍을 지원한다

코틀린은 객체지향 접근 방식과 함수형 스타일을 엮어 제공한다.

[함수형 프로그래밍의 핵심 개념]

  • 일급 시민(first-class)인 함수

    • 함수를 일반 값처럼 다룰 수 있다. 함수에 변수를 저장할 수 있고, 함수를 인자로 다른 함수에 전달할 수 있으며, 함수에서 새로운 함수를 만들어 반환할 수 있다.
  • 불변성

    • 생성된 후 내부 상태가 절대 바뀌지 않는 불변 객체를 사용한다.
  • 부수 효과 없음

    • 함수형 프로그래밍에서는 입력이 같으면 항상 같은 출력을 반환하고, 다른 객체의 상태를 변경하지 않으며 함수 외부나 다른 바깥 환경과 상호작용하지 않는 순수 함수를 사용한다.

[함수형 프로그래밍의 장점]

  • 간결함

    • 함수형 프로그래밍은 명령형 코드에 비해 간결하다. 분기에 의존하거나 변수의 값을 변경하는 대신 함수를 값처럼 활용할 수 있으므로 더 강력한 추상화가 가능하다.
  • 안전한 동시성

    • 멀티 스레드 프로그램에서는 적절한 동기화 없이 같은 데이터를 여러 행위자가 변경하는 경우 문제가 발생한다. 불변 데이터 구조와 순수 함수는 안전하지 않은 데이터 변경을 방지하므로 복잡한 동기화 방법을 적용하지 않아도 된다.
  • 쉬운 테스트

    • 부수 효과가 없으므로 외부 환경 의존을 준비하지 않고 독립적으로 테스트 가능하다.
    • 외부와 상호작용하지 않으므로, 코드에 대해 쉽게 추론할 수 있다.


코틀린에서는 함수형 스타일을 충분히 활용하면서도, 필요할 때 가변 데이터를 쓰고 부수 효과가 있는 함수를 작성할 수 있다.

동시성 처리를 위해 코루틴을 사용할 수 있다

기존에는 동시성 처리를 위해 스레드, 콜백, future, promise, reactive extension 등의 접근법을 사용했다.

코루틴은 일시 중단 가능한 계산(suspendable computation)을 통해 코드가 자신의 실행을 잠시 중단할 수 있고, 나중에 이어서 수행할 수 있다.


    suspend fun processUser(credentials: Credentials) {
        val user = authenticate(credentials)
        val data = loadUserData(user)
        val profilePicture = loadImage(data.imageID)
    }
    
    suspend fun authenticate(c: Credentials): User { /* .. */ }
    suspend fun loadUserData(u: User): Data { /* .. */ }
    suspend fun loadImage(id: Int): Image { /* .. */ }

이 코드를 살펴보자. authenticate, loadUserDate, loadImage는 각각 네트워크 호출을 하는 함수이다. 또한 호출에 이전 호출의 결과 데이터를 사용하기 때문에 순차적으로 실행되어야 한다.

위와 같은 동작을 일반적인 명령형 스타일로 작성한다면 블로킹을 사용하지 않고서는 코드를 한 번에 하나씩 순차적으로 실행할 수 없다. 그래서 이전에는 콜백이나 reactive extention으로 복잡한 코드를 작성하곤 했다. 그러나, 코루틴은 단순한 연속적인 로직만으로 블로킹 없는 순차적인 코드 실행을 가능하게 해준다!


    suspend fun loadAndOverlay(first: String, second: String): Image = 
        coroutineScope {
            val firstDeferred = async { loadImage(first) }
            val secondDeferred = async { loadImage(second) }
            combineImages(firstDeferred.await(), secondDeferred.await())
        }

데이터 의존성이 없는 경우, 작업은 동시에 진행하는 것이 효율적이다. (Task 수준에서의 병렬성!) async 키워드를 이용해 작업들을 비동기적으로 실행하고, await 키워드를 통해 각각의 작업이 끝나기를 기다린 후에 다음 작업을 수행한다. coroutineScope는 구조화된 동시성을 통해 코루틴 생명주기를 관리한다. 이 예제에서는 두 가지 프로세스가 구조화된 방식으로 시작했기 때문에, 한쪽이 실패하면 두 번째 프로세스도 자동으로 취소된다.


이러한 코루틴은 아주 가벼운 추상화로, 큰 성능 손해 없이 수백만 개의 동시성 작업을 시작할 수 있다. 추후 뜨거운 플로우나 차가운 플로우와 같은 추상화를 배울 것.



1.3 코틀린/JVM에서의 컴파일 과정

  • 컴파일러는 코틀린 소스코드 파일 *.kt을 분석해서 *.class 파일(JVM 바이트 코드)을 만들어낸다.
kotlinc <소스파일 또는 디렉터리> -include-runtime -d <jar 이름>
java -jar <jar 이름>
  • 자바 가상머신은 소스코드가 코틀린인지 자바인지 몰라도 바이트 코드를 실행할 수 있다. 그러나 코틀린 내장 클래스와 API는 의존성으로 코틀린 런타임 라이브러리라는 추가 정보가 필요하다. 커맨드라인에서 코드를 컴파일 할 때는 명시적으로 -include-runtime을 호출해서 결과로 생기는 JAR 파일 안에 런타임 라이브러리를 포함시켜야 한다.

    • 여기에는 코틀린 기본 클래스의 정의, 표준 자바 API에 대한 확장 등이 들어있다.
  • 코틀린 표준 라이브러리도 필요하다!

메이븐그레이들을 빌드 시스템으로 사용한다면, 애플리케이션 패키징 시 알아서 이 둘을 의존성에 포함시켜준다.


© 2025 do. Some rights reserved. Powered by Hydejack.