Destructuring Declarations

Kotlin์—์„œ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค(data class)๋Š” ๋ถˆ๋ณ€์˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•˜๋ฉฐ, toString(), hashCode(), equals()์™€ ๊ฐ™์€ ์œ ์šฉํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฆฌํ”Œ๋ ‰์…˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๋ฐ˜๋ณตํ•ด์•ผ ํ•  ๋•Œ๋Š” ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ๊ตฌ์กฐ ๋ถ„ํ•ด ์„ ์–ธ(Destructuring Declarations) ์‚ฌ์šฉํ•˜๊ธฐ

๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค์˜ componentN() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌํ”Œ๋ ‰์…˜ ์—†์ด ํด๋ž˜์Šค์˜ ๋ชจ๋“  ์†์„ฑ์„ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์˜คํ•ดํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ํ•จ์ˆ˜๋“ค์€ ์†์„ฑ ๊ตฌ์กฐ ๋ถ„ํ•ด๋ฅผ ์œ„ํ•ด์„œ๋งŒ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๊ตฌ์กฐ ๋ถ„ํ•ด ์„ ์–ธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด์˜ ์†์„ฑ์„ ์ถ”์ถœํ•˜์—ฌ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ง„์ •ํ•œ ์˜๋ฏธ์˜ ๋ฐ˜๋ณต์€ ์•„๋‹ˆ์ง€๋งŒ, ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์ถ”์ถœํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ €, name๊ณผ age๋ผ๋Š” ๋‘ ๊ฐœ์˜ ์†์„ฑ์„ ๊ฐ€์ง„ Person ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

data class Person(val name: String, val age: Int)

@Test
fun `iterate fields using destructuring declaration`() {
    val person = Person("Robert", 28)
    val (name, age) = person
        
    assertEquals("Robert", name)
    assertEquals(28, age)
}

์œ„ ์ฝ”๋“œ์—์„œ Person ๊ฐ์ฒด๋ฅผ ๊ตฌ์กฐ ๋ถ„ํ•ดํ•˜์—ฌ ํ•„๋“œ๋ฅผ ์ง์ ‘ ์ถ”์ถœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ ๊ตฌ์กฐ ๋ถ„ํ•ด ์„ ์–ธ ์‹œ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํ•„๋“œ ์ˆ˜๋ฅผ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•˜๋ฏ€๋กœ, ํ•„๋“œ ์ˆ˜๊ฐ€ ๋งŽ์€ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค์—๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

3. KClassUnpacker ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ ์‚ฌ์šฉํ•˜๊ธฐ

๋ฐ์ดํ„ฐ ํด๋ž˜์Šค์˜ ์†์„ฑ์„ ๋ฐ˜๋ณตํ•˜๋Š” ๊ณผ์ •์„ ๋‹จ์ˆœํ™”ํ•˜๊ธฐ ์œ„ํ•ด, ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์‹ฑ ๋นŒ๋“œ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ”„๋กœ์ ํŠธ์— ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. KClassUnpacker ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ด ๊ณผ์ •์„ ์šฉ์ดํ•˜๊ฒŒ ํ•ด์ฃผ์ง€๋งŒ, ์„ค์ •์ด ๋ณต์žกํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ”„๋กœ์ ํŠธ์˜ pom.xml ํŒŒ์ผ์— ํŠน์ • ๊ตฌ์„ฑ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

3.1. ๋นŒ๋“œ ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์ •

๋จผ์ €, Kotlin ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ์ด๋ฏ€๋กœ kotlin-maven-plugin์˜ kapt ๋ชฉํ‘œ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

<execution>
    <id>kapt</id>
    <goals>
        <goal>kapt</goal>
    </goals>
    <configuration>
        <sourceDirs>
            <sourceDir>src/main/kotlin</sourceDir>
            <sourceDir>src/main/java</sourceDir>
        </sourceDirs>
        <annotationProcessorPaths>
            <annotationProcessorPath>
                <groupId>com.github.LunarWatcher</groupId>
                <artifactId>KClassUnpacker</artifactId>
                <version>v1.0.2</version>
            </annotationProcessorPath>
        </annotationProcessorPaths>
    </configuration>
</execution>

3.2. ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๊ตฌ์„ฑ

๋‹ค์Œ์œผ๋กœ, KClassUnpacker๊ฐ€ JitPack Maven ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ํ˜ธ์ŠคํŒ…๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ํ”„๋กœ์ ํŠธ๊ฐ€ JitPack์„ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

<repositories>
    <repository>
        <id>central</id>
        <url>https://repo.maven.apache.org/maven2</url>
    </repository>
    <repository>
        <id>jitpack</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

์ด ์„ค์ •์€ ํ”„๋กœ์ ํŠธ๊ฐ€ mavenCentral()์„ ๊ธฐ๋ณธ ์†Œ์Šค๋กœ ์‚ฌ์šฉํ•˜๊ณ , Maven Central์— ์—†๋Š” ์ข…์†์„ฑ์€ JitPack์—์„œ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

3.3. KClassUnpacker ์ข…์†์„ฑ ์ถ”๊ฐ€

๋งˆ์ง€๋ง‰์œผ๋กœ, ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๋กœ์„œ์˜ ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•˜๊ธฐ ์œ„ํ•ด KClassUnpacker ์ข…์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

<dependency>
    <groupId>com.github.LunarWatcher</groupId>
    <artifactId>KClassUnpacker</artifactId>
    <version>v1.0.2</version>
</dependency>

์ด ์„น์…˜์—์„œ๋Š” GitHub์˜ KClassUnpacker ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(๋ฒ„์ „ 1.0.2)๋ฅผ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์ด ์„ค์ •์€ ์ปดํŒŒ์ผ ์‹œ์ ์— ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํ•ด๋‹น ๊ธฐ๋Šฅ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ฉฐ, ๋Ÿฐํƒ€์ž„ ์ข…์†์„ฑ์—์„œ๋Š” ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค.

4. KClassUnpacker ์‚ฌ์šฉ๋ฒ•

์ด์ œ KClassUnpacker๋ฅผ ์„ค์ •ํ–ˆ์œผ๋ฏ€๋กœ, ๋ฆฌํ”Œ๋ ‰์…˜ ์—†์ด ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€์ƒ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค์— @AutoUnpack ์• ๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@AutoUnpack
data class Person(val name: String, val age: Int)

์ด์ œ Person ํด๋ž˜์Šค์˜ ํ•„๋“œ๋ฅผ ๋ฐ˜๋ณตํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

fun getFields(person: Person): List<String> {
    val list = mutableListOf<String>()
    val cls = person
    for (field in cls) {
        list.add(field.toString())
    }

    return list
}

@Test
fun `iterate fields using KClassUnpacker plugin`() {
    val person = Person("Robert", 28)
    val list = getFields(person)

    assertEquals("Robert", list[0])
    assertEquals("28", list[1])
}

์œ„ ์˜ˆ์ œ๋Š” @AutoUnpack ์• ๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด Person ํด๋ž˜์Šค์˜ ํ•„๋“œ๋ฅผ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด getFields ๋ฉ”์„œ๋“œ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

4.1. ์žฅ๋‹จ์ 

์ด ์ ‘๊ทผ ๋ฐฉ์‹์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์žฅ์ ๊ณผ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์žฅ์ :

  • ์ปดํŒŒ์ผ ํƒ€์ž„ ์ฒดํฌ ๋ฐ ์ฝ”๋“œ ์ƒ์„ฑ: ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์‹ฑ์„ ํ†ตํ•ด ์ฝ”๋“œ์˜ ์ •ํ™•์„ฑ์„ ๋†’์ด๊ณ  ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜ ๊ฐ€๋Šฅ์„ฑ์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ฆฌํ”Œ๋ ‰์…˜ ํšŒํ”ผ: ๋ฆฌํ”Œ๋ ‰์…˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ค„์ด๊ณ  ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ž๋™ ์ฝ”๋“œ ์ƒ์„ฑ: ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์–ธํŒฉํ‚น ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ์–ด ์ˆ˜์ž‘์—…์œผ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ๋ฅผ ์ค„์—ฌ์ค๋‹ˆ๋‹ค.

๋‹จ์ :

  • ๋ณต์žกํ•œ ์„ค์ •: ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ๋นŒ๋“œ ํ”„๋กœ์„ธ์Šค์— ํ†ตํ•ฉํ•˜๋Š” ๊ฒƒ์ด ๋ณต์žกํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐœ๋ฐœ์ž์—๊ฒŒ๋Š” ํ•™์Šต ๊ณก์„ ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์™ธ๋ถ€ ์˜์กด์„ฑ: ์™ธ๋ถ€ ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ์— ์˜์กดํ•˜๊ฒŒ ๋˜์–ด ์ถ”๊ฐ€์ ์ธ ์ข…์†์„ฑ๊ณผ ํ˜ธํ™˜์„ฑ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋””๋ฒ„๊น… ์–ด๋ ค์›€: ์ƒ์„ฑ๋œ ์ฝ”๋“œ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ƒ์„ฑ๋œ ์ฝ”๋“œ๊ฐ€ ์›๋ณธ ์†Œ์Šค ์ฝ”๋“œ์™€ ์–ด๋–ป๊ฒŒ ๋Œ€์‘๋˜๋Š”์ง€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Last updated