# **코틀린의 특수 기능과 주요 키워드** 코틀린은 **개발 생산성을 높이는 다양한 특수 기능**을 제공한다. 이 글에서는 **코틀린의 고급 기능**을 **사용 예시와 함께** 설명하겠다. 🚀 ### ✨ **소개할 내용** 1. **`inline` 함수** 2. **`reified` 키워드** 3. **제너릭(Generic)** 4. **위임(Delegation) 패턴과 `by` 키워드** --- ## **1. `inline` 함수: 함수 호출 비용 줄이기** 코틀린의 `inline` 함수는 **함수 호출 오버헤드를 줄이기 위해 사용**된다. ### **1.1. 기본적인 `inline` 함수 예제** ```kotlin inline fun execute(block: () -> Unit) { println("실행 시작") block() println("실행 종료") } fun main() { execute { println("실제 로직 실행") } } ``` **출력 결과:** ``` 실행 시작 실제 로직 실행 실행 종료 ``` > - **함수 호출이 사라지고 코드가 그대로 복사됨 (인라이닝)** > - **람다를 인자로 받을 때 유용** > - 단점: **코드 크기가 증가할 수 있음 (작은 함수에만 사용)** --- ## **2. `reified` 키워드: 실행 시점에서 타입 유지** 코틀린에서는 **제너릭 타입 정보가 실행 시점에 사라지는 문제(type erasure)가 있음**. 하지만 `reified` 키워드를 사용하면 **실행 시점에서도 타입을 유지할 수 있음**. ### **2.1. `reified` 없이 제너릭 타입 확인 불가** ```kotlin fun getClassName(): String { return T::class.simpleName // 오류 발생! } fun main() { println(getClassName()) } ``` > - 오류 발생! **제너릭 타입은 실행 시점에서 사라지기 때문**. ### **2.2. `reified` 키워드 사용하여 해결** ```kotlin inline fun getClassName(): String { return T::class.simpleName ?: "알 수 없음" } fun main() { println(getClassName()) // "String" println(getClassName()) // "Int" } ``` > - **`reified`를 사용하면 실행 시점에서도 제너릭 타입을 알 수 있음** > - 주의: **`inline` 함수에서만 `reified` 사용 가능** --- ## **3. 제너릭(Generic): 타입을 유연하게 만들기** 제너릭을 사용하면 **코드의 재사용성을 높이고, 타입 안정성을 유지할 수 있음**. ### **3.1. 기본적인 제너릭 사용** ```kotlin class Box(val value: T) { fun get(): T = value } fun main() { val intBox = Box(123) val strBox = Box("Hello") println(intBox.get()) // 123 println(strBox.get()) // Hello } ``` > - `T`를 사용하여 **어떤 타입이든 저장할 수 있는 클래스**를 정의 ### **3.2. 제너릭 함수 사용** ```kotlin fun printItem(item: T) { println("아이템: $item") } fun main() { printItem(42) // 아이템: 42 printItem("코틀린") // 아이템: 코틀린 } ``` > - **함수에도 제너릭 적용 가능** --- ## **4. 위임(Delegation) 패턴과 `by` 키워드** 코틀린의 `by` 키워드는 **객체의 기능을 다른 객체에 위임할 때 사용**된다. 이를 통해 **불필요한 코드 중복을 방지**할 수 있다. ### **4.1. 인터페이스를 이용한 기본 위임 패턴** ```kotlin interface Printer { fun printMessage() } class ConsolePrinter : Printer { override fun printMessage() { println("콘솔에 출력") } } class SmartPrinter(private val printer: Printer) : Printer { override fun printMessage() { println("스마트 프린터 작동 중...") printer.printMessage() } } fun main() { val printer = SmartPrinter(ConsolePrinter()) printer.printMessage() } ``` **출력 결과:** ``` 스마트 프린터 작동 중... 콘솔에 출력 ``` > - `SmartPrinter`가 `ConsolePrinter`의 기능을 **위임(Delegation)** ### **4.2. `by` 키워드를 사용한 간결한 위임 패턴** ```kotlin class SmartPrinter2(private val printer: Printer) : Printer by printer fun main() { val printer = SmartPrinter2(ConsolePrinter()) printer.printMessage() // "콘솔에 출력" } ``` > - `by printer` 를 사용하면 **위임을 자동으로 처리** > - 코드가 훨씬 간결해짐 --- ## **5. `by lazy`를 활용한 지연 초기화** `by lazy`를 사용하면 **객체를 필요할 때만 초기화**할 수 있다. ```kotlin class Example { val lazyValue: String by lazy { println("초기화 중...") "Hello, Kotlin!" } } fun main() { val example = Example() println("객체 생성 완료") println(example.lazyValue) // 여기서 초기화 발생 println(example.lazyValue) // 이미 초기화됨, 출력만 함 } ``` **출력 결과:** ``` 객체 생성 완료 초기화 중... Hello, Kotlin! Hello, Kotlin! ``` > - `by lazy`는 **최초 접근 시점에만 실행됨** > - 이후에는 **이미 생성된 값을 사용** --- ## **6. `object` 키워드: 싱글톤 객체** 코틀린에서 싱글톤 객체를 만들 때 **`object` 키워드**를 사용한다. ```kotlin object Singleton { fun showMessage() { println("싱글톤 객체 실행!") } } fun main() { Singleton.showMessage() } ``` **출력 결과:** ``` 싱글톤 객체 실행! ``` > - **별도의 인스턴스 생성 없이** `Singleton.showMessage()` 사용 가능 > - **앱 설정, 네트워크 요청 관리 등에 유용** --- ## **🔹 정리: 코틀린의 특수 기능 요약** | 기능 | 설명 | 사용 예시 | |------|------|------| | `inline` 함수 | 함수 호출을 줄이고 성능 향상 | `inline fun execute(block: () -> Unit) {}` | | `reified` | 실행 시점에서도 제너릭 타입 유지 | `inline fun getType() = T::class.simpleName` | | 제너릭 | 코드의 재사용성과 타입 안정성 유지 | `class Box(val value: T)` | | Delegation | 클래스 기능을 다른 객체에 위임 | `class PrinterImpl : Printer by ConsolePrinter()` | | `by lazy` | 지연 초기화 | `val name: String by lazy { "코틀린" }` | | `object` | 싱글톤 객체 | `object Singleton {}` | 코틀린의 강력한 기능들을 활용하면 **코드를 더 간결하고 효율적으로 작성**할 수 있다. 이제 **직접 사용해보면서** 익숙해지자! 🚀