자바와 100% 호환되면서 세미콜론도 없고, getter/setter도 없고, null 처리까지 언어 차원에서 해주는 언어가 있다면 어떨까요?

코틀린 은 JetBrains가 만든 JVM 기반 언어로, 자바의 장점을 유지하면서 간결한 문법과 타입 안전성 을 추가한 언어입니다.

val과 var — 변수 선언의 기본

코틀린에서 변수를 선언하는 방법은 딱 두 가지입니다.

  • val — 재할당 불가 (자바의 final과 동일)
  • var — 재할당 가능
KOTLIN
val name = "코틀린"    // 재할당 불가
var count = 0          // 재할당 가능

// name = "자바"       // 컴파일 에러!
count = 1              // OK

val ≠ 불변

val은 ** 참조의 재할당을 막을 뿐 **, 객체 내부 상태까지 보장하지 않습니다.

KOTLIN
val list = mutableListOf(1, 2, 3)
list.add(4)           // OK — 리스트 내부 상태 변경
// list = mutableListOf()  // 컴파일 에러 — 재할당 불가

val은 자바의 final 변수와 동일한 개념입니다. 진짜 불변을 원한다면 listOf()처럼 불변 컬렉션을 사용해야 합니다.

타입 추론 — 타입을 안 써도 되는 이유

코틀린 컴파일러는 초기화 값을 보고 타입을 알아서 결정합니다. 이것을 ** 타입 추론(Type Inference)**이라고 합니다.

KOTLIN
val message = "Hello"          // String으로 추론
val number = 42                // Int로 추론
val pi = 3.14                  // Double로 추론

명시적으로 타입을 적어도 됩니다.

KOTLIN
val message: String = "Hello"
val number: Int = 42

타입 추론이 안 되는 경우

초기화 없이 선언만 하면 타입을 반드시 명시해야 합니다.

KOTLIN
val name: String    // 나중에 초기화할 예정
// val name          // 컴파일 에러 — 타입을 알 수 없음

타입을 안 쓴다고 동적 타이핑이 아닙니다. 코틀린은 ** 정적 타이핑** 언어이며, 컴파일 타임에 타입이 확정됩니다.

Nullable 타입 — 물음표 하나의 차이

코틀린에서 모든 타입은 기본적으로 null을 허용하지 않습니다. 타입 뒤에 ?를 붙이면 Nullable 타입이 됩니다.

KOTLIN
var name: String = "코틀린"
// name = null                 // 컴파일 에러!

var nullableName: String? = "코틀린"
nullableName = null            // OK

이 규칙 하나로 NPE(NullPointerException)를 컴파일 타임에 잡아냅니다.

KOTLIN
fun getLength(text: String?): Int {
    // return text.length      // 컴파일 에러 — null일 수 있음
    return text?.length ?: 0   // 안전 호출 + 엘비스 연산자
}

Nullable에 대한 자세한 내용은 별도 글에서 다룹니다.

String Template — 문자열 조합

자바에서 문자열을 조합하려면 + 연산이나 String.format()을 써야 했습니다. 코틀린은 $ 하나로 해결합니다.

KOTLIN
val name = "코틀린"
val version = 2.0

println("언어: $name")                    // 언어: 코틀린
println("버전: ${version + 0.1}")         // 버전: 2.1

여러 줄 문자열도 지원합니다.

KOTLIN
val json = """
    {
        "name": "$name",
        "version": $version
    }
""".trimIndent()

자바와 비교하면 차이가 확연합니다.

JAVA
// 자바
String result = "이름: " + name + ", 버전: " + version;
KOTLIN
// 코틀린
val result = "이름: $name, 버전: $version"

when 표현식 — switch의 상위 호환

코틀린의 when은 자바 switch의 모든 기능을 포함하면서 훨씬 강력합니다.

KOTLIN
val result = when (grade) {
    'A' -> "우수"
    'B' -> "보통"
    'C' -> "미흡"
    else -> "알 수 없음"
}

범위 검사, 타입 검사, 여러 값 매칭, 인자 없는 형태까지 지원합니다.

KOTLIN
// 범위 검사
when (score) {
    in 90..100 -> "A"
    in 80..89 -> "B"
    else -> "F"
}

// 타입 검사 (스마트 캐스트 적용)
when (obj) {
    is String -> println("길이: ${obj.length}")
    is Int -> println("정수: $obj")
    else -> println("기타")
}
특징Java switchKotlin when
Fall-through있음 (break 필요)없음
표현식 사용Java 14부터처음부터
타입 검사Java 17부터처음부터
범위 검사불가in 연산자
인자 없는 형태불가가능

자바와의 100% 호환

코틀린은 같은 JVM 위에서 돌아가므로 자바와 완벽하게 호환됩니다.

KOTLIN
// 코틀린에서 자바 라이브러리를 그대로 사용
import java.time.LocalDateTime
val now = LocalDateTime.now()
KOTLIN
// 코틀린 파일: Utils.kt
fun greet(name: String): String = "안녕, $name!"
JAVA
// 자바에서 호출
String result = UtilsKt.greet("자바");

코틀린 최상위 함수는 파일명Kt 클래스의 정적 메서드로 컴파일됩니다. @JvmStatic, @JvmOverloads 같은 어노테이션으로 자바 호출을 더 자연스럽게 만들 수 있습니다.

점진적 마이그레이션이 가능하다

PLAINTEXT
기존 자바 프로젝트
├── src/main/java/      ← 기존 자바 코드 유지
│   └── UserService.java
├── src/main/kotlin/    ← 새 코드는 코틀린으로
│   └── OrderService.kt

한 번에 전부 바꾸는 게 아니라, 새로운 코드부터 코틀린으로 작성하고 기존 자바 코드와 공존시키는 방식입니다.

주의할 점

자바에서 코틀린으로 넘어올 때 자주 실수하는 부분입니다.

checked exception이 없다

코틀린은 checked exception을 강제하지 않습니다. 자바에서 throws IOException을 선언해야 했던 메서드도, 코틀린에서는 선언 없이 호출할 수 있습니다. 편리하지만, ** 예외 처리를 잊기 쉽다 **는 함정이 있습니다.

KOTLIN
fun readFile(path: String): String {
    return File(path).readText()  // throws 선언 불필요
}

기본 가시성이 다르다

자바는 package-private가 기본이지만, 코틀린은 public이 기본 입니다. 의도치 않게 API가 노출될 수 있으니, internal이나 private을 적극 활용해야 합니다.

val이 불변을 보장하지 않는다

앞에서 다뤘듯이 val은 참조 재할당만 막습니다. val list = mutableListOf()처럼 선언하면 내부 상태가 변합니다. 진짜 불변이 필요하면 불변 컬렉션(listOf)을 사용해야 합니다.

정리

항목설명
val/varval은 재할당 불가(≠ 불변), var는 재할당 가능
타입 추론컴파일 타임에 타입이 결정되는 정적 타이핑
Nullable? 하나로 NPE를 컴파일 타임에 방지
String Template$${}로 문자열 조합
whenfall-through 없는 강력한 패턴 매칭
자바 호환같은 프로젝트에서 자바와 코틀린 공존 가능
기본 가시성코틀린은 public, 자바는 package-private
댓글 로딩 중...