reified

์ฝ”ํ‹€๋ฆฐ์—์„œ ํ‚ค์›Œ๋“œ๋Š” ํƒ€์ž… ์†Œ๊ฑฐ(Type Erasure) ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ JVM์€ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ •๋ณด๋ฅผ ์ง€์›Œ๋ฒ„๋ฆฝ๋‹ˆ๋‹ค. ์ด ๋•Œ๋ฌธ์— ๋Ÿฐํƒ€์ž„์— T๊ฐ€ ์–ด๋–ค ํƒ€์ž…์ธ์ง€ ์•Œ ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. reified๋Š” ์ด ํƒ€์ž… ์ •๋ณด๋ฅผ ๋Ÿฐํƒ€์ž„์—๋„ ์œ ์ง€์‹œ์ผœ ์ค๋‹ˆ๋‹ค.


ํƒ€์ž… ์†Œ๊ฑฐ(Type Erasure)์˜ ํ•œ๊ณ„

์ž๋ฐ”์™€ ์ฝ”ํ‹€๋ฆฐ์—์„œ ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๋Š” ์ฃผ๋œ ์ด์œ ๋Š” ์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ํ™•๋ณดํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ JVM์€ ํด๋ž˜์Šค ํŒŒ์ผ์„ ๋กœ๋“œํ•  ๋•Œ ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ •๋ณด๋ฅผ ์ง€์›Œ๋ฒ„๋ฆฌ๋ฏ€๋กœ, ๋Ÿฐํƒ€์ž„์—๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ๋ช…ํ™•ํžˆ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

fun <T> isInstanceOf(item: Any): Boolean {
    // ๋Ÿฐํƒ€์ž„์— T์˜ ํƒ€์ž… ์ •๋ณด๊ฐ€ ์†Œ๊ฑฐ๋˜์–ด is T๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ
    return item is T // โš ๏ธ ์ปดํŒŒ์ผ ์—๋Ÿฌ!
}

์œ„ ์ฝ”๋“œ๋Š” T๊ฐ€ String์ธ์ง€ Int์ธ์ง€ ๋Ÿฐํƒ€์ž„์— ์•Œ ์ˆ˜ ์—†์–ด ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.


reified์˜ ์—ญํ• ๊ณผ ์‚ฌ์šฉ๋ฒ•

reified๋Š” **์ธ๋ผ์ธ ํ•จ์ˆ˜(inline function)**์˜ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ์—๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. reified ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ œ๋„ค๋ฆญ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ T๋ฅผ ํ•ด๋‹น ํƒ€์ž…์œผ๋กœ **"์‹ค์ฒดํ™”(reify)"**ํ•ด์ค๋‹ˆ๋‹ค. ์ฆ‰, ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ํƒ€์ž… T๊ฐ€ **์‹ค์ œ ํƒ€์ž…(e.g., String, Int)**์œผ๋กœ ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค.

reified๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์œ„ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

// reified ํ‚ค์›Œ๋“œ๋กœ T์˜ ํƒ€์ž… ์ •๋ณด๋ฅผ ์œ ์ง€
inline fun <reified T> isInstanceOf(item: Any): Boolean {
    return item is T
}

fun main() {
    val myString = "Hello"
    val myNumber = 123

    // ๋Ÿฐํƒ€์ž„์—๋„ ํƒ€์ž… T๊ฐ€ String, Int๋กœ ์œ ์ง€๋จ
    println(isInstanceOf<String>(myString)) // ์ถœ๋ ฅ: true
    println(isInstanceOf<Int>(myNumber))     // ์ถœ๋ ฅ: true
    println(isInstanceOf<String>(myNumber)) // ์ถœ๋ ฅ: false
}

์ด์ฒ˜๋Ÿผ reified๋Š” ๋Ÿฐํƒ€์ž„์—๋„ ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ํ™œ์šฉํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์—์„œ ๋งค์šฐ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.


reified์˜ ํ™œ์šฉ ์‚ฌ๋ก€

reified๋Š” ํŠน์ • ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ํ•„ํ„ฐ๋งํ•˜๊ฑฐ๋‚˜, ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•  ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์“ฐ์ž…๋‹ˆ๋‹ค.

1. ํƒ€์ž…๋ณ„ ๋ฆฌ์ŠคํŠธ ํ•„ํ„ฐ๋ง

ํŠน์ • ํƒ€์ž…์˜ ์š”์†Œ๋งŒ ๊ฑธ๋Ÿฌ๋‚ด๊ณ  ์‹ถ์„ ๋•Œ reified๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•ด์ง‘๋‹ˆ๋‹ค.

inline fun <reified T> List<Any>.filterIsInstance(): List<T> {
    val result = mutableListOf<T>()
    for (item in this) {
        if (item is T) {
            result.add(item)
        }
    }
    return result
}

fun main() {
    val items = listOf("apple", 1, "banana", 2.5, "cherry")

    val strings = items.filterIsInstance<String>()
    println(strings) // ์ถœ๋ ฅ: [apple, banana, cherry]

    val doubles = items.filterIsInstance<Double>()
    println(doubles) // ์ถœ๋ ฅ: [2.5]
}

2. ์•กํ‹ฐ๋น„ํ‹ฐ ์‹œ์ž‘

์•ˆ๋“œ๋กœ์ด๋“œ ๊ฐœ๋ฐœ์—์„œ startActivity๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ reified๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํด๋ž˜์Šค๋ฅผ ์ง์ ‘ ๋„˜๊ธฐ์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

// Context ํ™•์žฅ ํ•จ์ˆ˜
inline fun <reified T : Activity> Context.startActivity() {
    val intent = Intent(this, T::class.java)
    startActivity(intent)
}

// ์‚ฌ์šฉ ์˜ˆ์‹œ
// context.startActivity<MainActivity>()

reified๋Š” ์ฝ”ํ‹€๋ฆฐ์˜ ํƒ€์ž… ์†Œ๊ฑฐ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๋Š” ํ‚ค์›Œ๋“œ๋กœ, ํŠนํžˆ ์ธ๋ผ์ธ ํ•จ์ˆ˜์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜์–ด ๋Ÿฐํƒ€์ž„์—๋„ ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ •๋ณด๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋” ์•ˆ์ „ํ•˜๊ณ  ์œ ์—ฐํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํŠนํžˆ ๋ฆฌํ”Œ๋ ‰์…˜๊ณผ ๊ฐ™์ด ๋Ÿฐํƒ€์ž„ ํƒ€์ž… ์ •๋ณด๊ฐ€ ํ•„์ˆ˜์ ์ธ ์ƒํ™ฉ์—์„œ ๋งค์šฐ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค. reified๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๋” ๊ฐ„๊ฒฐํ•ด์ง€๊ณ  ๊ฐ€๋…์„ฑ์ด ๋†’์•„์ง€๋Š” ์žฅ์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

Last updated