# **코틀린의 특수 기능과 주요 키워드**  

코틀린은 **개발 생산성을 높이는 다양한 특수 기능**을 제공한다.  
이 글에서는 **코틀린의 고급 기능**을 **사용 예시와 함께** 설명하겠다. 🚀  

### ✨ **소개할 내용**  
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 <T> getClassName(): String {
    return T::class.simpleName  // 오류 발생!
}

fun main() {
    println(getClassName<String>())  
}
```
> - 오류 발생! **제너릭 타입은 실행 시점에서 사라지기 때문**.  

### **2.2. `reified` 키워드 사용하여 해결**
```kotlin
inline fun <reified T> getClassName(): String {
    return T::class.simpleName ?: "알 수 없음"
}

fun main() {
    println(getClassName<String>())  // "String"
    println(getClassName<Int>())     // "Int"
}
```
> - **`reified`를 사용하면 실행 시점에서도 제너릭 타입을 알 수 있음**  
> - 주의: **`inline` 함수에서만 `reified` 사용 가능**  

---

## **3. 제너릭(Generic): 타입을 유연하게 만들기**  
제너릭을 사용하면 **코드의 재사용성을 높이고, 타입 안정성을 유지할 수 있음**.  

### **3.1. 기본적인 제너릭 사용**
```kotlin
class Box<T>(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 <T> 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 <reified T> getType() = T::class.simpleName` |
| 제너릭 | 코드의 재사용성과 타입 안정성 유지 | `class Box<T>(val value: T)` |
| Delegation | 클래스 기능을 다른 객체에 위임 | `class PrinterImpl : Printer by ConsolePrinter()` |
| `by lazy` | 지연 초기화 | `val name: String by lazy { "코틀린" }` |
| `object` | 싱글톤 객체 | `object Singleton {}` |

코틀린의 강력한 기능들을 활용하면 **코드를 더 간결하고 효율적으로 작성**할 수 있다.  
이제 **직접 사용해보면서** 익숙해지자! 🚀