Android를 위한 Kotlin: 문법 기초와 기능

저자: IT Sectr 게시일: 2026-02-10 읽는 시간: 8 분

Kotlin은 JetBrains의 정적 타입 프로그래밍 언어로, JVM에서 실행되며 2017년부터 Google이 Android 개발을 위해 공식적으로 지원하고 있습니다. Kotlin은 Java와 완전히 호환되며 간결한 문법과 내장된 null 안전성을 갖추고 있습니다. Kotlin Documentation — 언어 및 표준 라이브러리에 대한 완벽한 가이드.

핵심 포인트

  • Kotlin — 간결한 문법과 null 안전성을 갖춘 JetBrains의 정적 타입 JVM 언어
  • Null safety — 컴파일러가 nullable(String?)과 non-null(String) 타입을 구분하여 NullPointerException 제거
  • Data classes — equals, hashCode, toString, copy 및 componentN 자동 생성
  • Extension functions — 상속 없이 정적 호출을 통해 기존 클래스에 메서드 추가
  • Coroutines — 스레드 차단 없이 suspend 함수를 통한 순차적 스타일의 비동기 프로그래밍

Kotlin이란?

Kotlin은 JetBrains(IntelliJ IDEA 개발사)가 만든 정적 타입 프로그래밍 언어로, Apache 2.0 라이선스 하에 2016년에 출시되었습니다. Kotlin은 JVM 바이트코드, JavaScript 및 네이티브 코드(Kotlin/Native를 통해)로 컴파일됩니다. 주요 적용 분야는 Android 개발, 서버 사이드 애플리케이션 및 크로스 플랫폼 프로젝트입니다.

Google은 Google I/O 2017에서 Kotlin을 Android 개발의 공식 언어로 발표했습니다. Google(Android Developer Blog, 2026)에 따르면 Google Play의 신규 프로젝트 중 85% 이상이 Kotlin을 사용합니다. 이 언어는 서버 사이드 개발(Spring Boot, Ktor) 및 멀티플랫폼 프로젝트(Kotlin Multiplatform Mobile)에서도 활발히 사용됩니다.

Kotlin은 Java와 완전히 호환됩니다 — 동일한 프로젝트 내에서 Kotlin에서 Java 코드를, 그 반대로 호출할 수 있습니다. 빌드 도구(Gradle, Maven)는 두 언어를 모두 지원하므로 개발 중단 없이 Java에서 Kotlin으로 점진적으로 마이그레이션할 수 있습니다.

Android에서 Kotlin이 Java보다 인기있는 이유

주요 이유: 간결성 — Kotlin은 동일한 작업에 Java보다 평균 40% 적은 코드 라인이 필요합니다. Null 안전성 — 컴파일러가 확인 없이 nullable 타입 사용을 금지합니다. 함수형 기능 — 고차 함수, 람다, 확장 함수 및 코루틴이 코드를 더 표현력 있고 안전하게 만듭니다.

문법 기초

기본 Kotlin 문법은 간결성과 명확성을 결합합니다. 변수는 val(불변)과 var(가변)로 선언됩니다. 컴파일러는 타입 추론을 사용하지만 명시적 타입 선언도 지원됩니다. 함수는 fun 키워드로 선언됩니다.

kotlin
package com.example.intro

// 상수와 변수
val appName: String = "KotlinApp"  // 불변
var version = 1.0  // 가변, 타입 추론됨

// 표현식 본문을 가진 함수
fun sum(a: Int, b: Int) = a + b

// String templates
fun greet(name: String) = "안녕하세요, $name! 버전 ${appName}_$version"

// Default and named arguments
fun createUser(
    name: String,
    age: Int = 18,
    email: String? = null
)

When 표현식은 Java의 switch를 대체하며 더 유연합니다: 타입 검사, 범위, 조건 및 break 없는 분기를 지원합니다. 컴파일러는 enum 및 sealed 클래스에 대한 완전한 커버리지를 확인합니다. 스마트 캐스트는 is 검사 후 자동으로 타입을 변환하여 명시적 캐스트를 제거합니다.

kotlin
fun analyzeValue(value: Any) = when (value) {
    is String -> "길이가 ${value.length}인 문자열"  // 스마트 캐스트
    is Int -> "정수: $value"
    in 1..10 -> "1-10 범위의 숫자"
    else -> "알 수 없는 타입"
}

Null 안전성과 엘비스 연산자

Null 안전성은 컴파일 타임에 NullPointerException을 제거하는 Kotlin의 핵심 기능입니다. Kotlin에서 타입은 기본적으로 null이 될 수 없습니다. null을 허용하려면 타입에 ?를 추가하세요: String?. 컴파일러는 모든 nullable 값에 대한 명시적 검사를 요구합니다.

kotlin
// Nullable 및 Non-null 타입
val nonNull: String = "항상 null 아님"
val nullable: String? = null  // 허용됨

// 세이프 콜 — null이 아닌 경우에만 실행
val length: Int? = nullable?.length

// 엘비스 연산자 — 기본값
val text: String = nullable ?: "Default text"

// Let — non-null 값으로 블록 실행
nullable?.let { value ->
    println("값: $value")
}

세이프 콜 연산자(?.)는 연산자 앞의 객체가 null이면 null을 반환하고, 그렇지 않으면 메서드/속성을 호출합니다. 엘비스 연산자(?:)는 왼쪽이 null인 경우 기본값을 제공합니다. Not-null 단언(!!)은 값이 null이면 NullPointerException을 throw합니다 — 값이 100% 존재한다고 확신할 때만 사용하세요.

플랫폼 타입 — 호출된 Java 코드의 타입으로 Kotlin이 nullable 또는 non-null로 표시할 수 없는 것입니다. 타입은 String!(느낌표 포함)으로 표시됩니다. Java 코드 작업 시 null 안전성은 개발자의 책임입니다.

데이터 클래스와 구조 분해

Kotlin의 데이터 클래스는 equals(), hashCode(), toString(), copy() 및 componentN()을 자동 생성합니다. 이는 Java 모델(POJO)의 보일러플레이트를 제거하고 코드를 더 깔끔하게 만듭니다. data class 선언은 Java에서 20-30줄 대신 한 줄이면 됩니다.

kotlin
data class User(
    val id: Long,
    val name: String,
    val email: String,
    val age: Int? = null
)

// 사용법
val user = User(1, "안나", "anna@example.com")
val updatedUser = user.copy(age = 25)

// 구조 분해
val (id, name) = user
println("사용자 #$id: $name")

구조 분해를 사용하면 data class를 한 줄에서 변수로 분해할 수 있습니다. 이는 쌍, 삼중 및 기타 복합 값 작업 시 편리합니다. 구조 분해는 데이터 클래스, 표준 컬렉션(List, Map) 및 operator fun componentN()이 있는 모든 클래스에서 지원됩니다.

확장 함수

확장 함수는 상속 없이 기존 클래스에 새 메서드를 추가하는 Kotlin 메커니즘입니다. 확장은 리시버 매개변수가 있는 정적 메서드로 컴파일되므로 상속이 필요 없으며 가상 디스패치도 지원되지 않습니다.

kotlin
// String에 대한 확장 함수
fun String.isEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

// 확장 속성
val String.isPhoneNumber: Boolean
    get() = this.matches(Regex("^\\+?[\\d-]{10,15}$"))

// 컬렉션에 대한 제네릭 확장
fun List<Int>.sumOfEvens(): Int {
    return this.filter { it % 2 == 0 }.sum()
}

// 사용법
println("test@mail.com".isEmail())  // true

확장은 Android SDK 및 라이브러리에서 널리 사용됩니다. 예를 들어 Android KTX의 Activity 확장은 Activity, Fragment, View 및 기타 클래스에 대한 extension functions입니다. 확장은 파일에서 최상위 함수로 또는 클래스의 멤버 확장으로 선언할 수 있습니다.

비동기 프로그래밍을 위한 코루틴

코루틴은 Kotlin의 비동기 프로그래밍 메커니즘으로, 순차적 스타일로 논블로킹 코드를 작성할 수 있습니다. 코루틴은 스레드를 차단하지 않고 suspend 함수에서 실행을 일시 중단하고 작업 완료 후 다시 시작합니다. 이는 RxJava 콜백 체인 및 AsyncTask의 대안입니다.

kotlin
import kotlinx.coroutines.*

// Suspend 함수 — 일시 중지 가능
suspend fun fetchUserData(userId: Int): User {
    // delay — suspend 함수, 스레드를 차단하지 않음
    delay(500)
    return User(userId, "User $userId", "user@example.com")
}

// 코루틴에서 실행
fun loadData() {
    CoroutineScope(Dispatchers.Main).launch {
        val user = fetchUserData(1)  // 여기서 일시 중지
        updateUI(user)  // 메인 스레드에서 계속
    }
}

Dispatchers는 코루틴의 스레드 풀을 결정합니다: Dispatchers.Main(UI 스레드), Dispatchers.IO(네트워크/디스크 작업), Dispatchers.Default(CPU 집약적 작업). 구조적 동시성은 코루틴이 스코프 완료 후 활성 상태로 남지 않도록 보장하여 메모리 누수를 방지합니다.

kotlin
// async/await를 통한 병렬 실행
suspend fun loadDashboard(): Dashboard = coroutineScope {
    val user = async { fetchUserData(1) }
    val orders = async { fetchOrders(1) }
    val stats = async { fetchStats() }
    
    Dashboard(user.await(), orders.await(), stats.await())
}

Kotlin vs Java: 비교

새 Android 프로젝트를 위한 Kotlin과 Java 선택은 근본적인 아키텍처 결정입니다. Kotlin은 더 현대적인 문법과 내장된 안전 메커니즘을 제공하는 반면, Java는 더 넓은 개발자 풀과 성숙한 라이브러리를 보유하고 있습니다.

특성KotlinJava
Null 안전성내장(nullable/non-null)내장 아님(@Nullable 애노테이션)
코드 양Java 대비 −40%보일러플레이트(getters/setters)
데이터 클래스data class (한 줄)Lombok 사용 또는 수동 POJO
비동기코루틴(suspend/await)CompletableFuture, RxJava
확장 함수내장유틸리티 클래스를 통해서만
스마트 캐스트is 검사 후명시적 캐스트 (Type) obj
하위 호환성Java와 100%

성능은 Kotlin과 Java가 비슷합니다 — 둘 다 JVM 바이트코드로 컴파일됩니다. Kotlin은 코루틴과 인라이닝에 약간의 마이크로 오버헤드가 있을 수 있지만 모바일 애플리케이션에서는 무시할 수 있습니다. Google과 JetBrains는 Kotlin에 적극적으로 투자하고 있습니다: Kotlin Multiplatform, Kotlin/Wasm 및 K2 컴파일러 성능 개선.

자주 묻는 질문

Kotlin은 Java와 어떻게 다릅니까?

Kotlin은 Java보다 40% 더 짧습니다 — 보일러플레이트가 적습니다. Kotlin은 null 안전성, 데이터 클래스, 확장 함수, 코루틴, 스마트 캐스트, when 표현식을 추가합니다. Java와 완전한 호환성: 두 언어 모두 JVM에서 실행되며 충돌 없이 동일한 프로젝트에서 사용할 수 있습니다.

Kotlin에서 null 안전성은 어떻게 작동합니까?

타입은 기본적으로 non-null입니다. nullable의 경우 ?: String?을 사용하세요. 컴파일러는 nullable 값에 대한 직접 접근을 금지합니다. 세이프 콜(?.)은 null 리시버에서 null을 반환합니다. 엘비스 연산자(?:)는 기본값을 설정합니다. !! — 예외 가능성이 있는 강제 추출.

Kotlin에서 코루틴이란?

코루틴은 경량 스레드로, 비동기 코드를 순차적으로 작성할 수 있습니다. suspend 함수는 스레드를 차단하지 않고 일시 중지됩니다. launch와 async는 CoroutineScope에서 코루틴을 시작합니다. 네트워크 요청에는 Dispatchers.IO, UI 업데이트에는 Dispatchers.Main.

Kotlin에서 데이터 클래스란?

data class는 자동으로 equals(), hashCode(), toString(), copy() 및 componentN()을 생성합니다. 예: data class User(val name: String, val age: Int). val (name, age) = user를 통한 구조 분해. Java 14+의 record와 유사하지만 추가 copy() 메서드가 있습니다.

확장 함수(extension functions)는 어떻게 작동합니까?

확장 함수는 기존 클래스에 메서드를 추가합니다: fun String.isEmail(): Boolean. 컴파일러는 이를 리시버 매개변수가 있는 정적 호출로 대체합니다. 상속이 필요 없습니다. 확장은 Android KTX에서 널리 사용됩니다: view.showToast(), activity.viewModels().

요약

  • Kotlin — JetBrains의 정적 타입 JVM 언어, 2017년부터 Android의 공식 언어
  • Null 안전성 — nullable/non-null 타입, 세이프 콜(?.), 엘비스(??), nullable 안전 작업을 위한 let 블록
  • 데이터 클래스 — equals, hashCode, toString, copy 자동 생성 및 구조 분해
  • 확장 함수 — 상속 없이 모든 클래스에 메서드 추가, 정적 호출로 컴파일
  • 코루틴 — suspend 함수, launch/async 및 Dispatchers를 사용한 순차적 스타일의 비동기 코드
  • Java와 비교 — −40% 코드, null 안전성, 스마트 캐스트, when 표현식 및 100% Java 호환성
  • Kotlin Multiplatform — Kotlin은 Android뿐만 아니라 iOS(KMM) 및 서버(Ktor, Spring)에서도 사용

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기