๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Kotlin

์ดํŽ™ํ‹ฐ๋ธŒ ์ฝ”ํ‹€๋ฆฐ - 1์žฅ ์•ˆ์ •์„ฑ

by ์ฃผ๋ฐœ2 2025. 6. 3.
๋ฐ˜์‘ํ˜•


์•„์ดํ…œ 1. ๊ฐ€๋ณ€์„ฑ์„ ์ œํ•œํ•˜๋ผ

(๊ฐ€๋Šฅํ•˜๋ฉด) var ๋ณด๋‹ค๋Š” val ์‚ฌ์šฉ
(๊ฐ€๋Šฅํ•˜๋ฉด) mutable ํ”„๋กœํผํ‹ฐ๋ณด๋‹ค๋Š” immutable ํ”„๋กœํผํ‹ฐ ์‚ฌ์šฉ
mutable ๊ฐ์ฒด๋ฅผ ์™ธ๋ถ€์— ๋…ธ์ถœํ•˜์ง€ ๋ง์ž.
class Test {
    fun calculate(): Int {
        println("Cal...")
        return 42
    }

    val fizz = calculate()
    val buzz
        get() = calculate()

}

fun main() {
    println(Test().buzz)
}

//Cal...
//Cal...
//42

์ฝ๊ธฐ ์ „์šฉ ์ปฌ๋ ‰์…˜์„ Mutable ์ปฌ๋ ‰์…˜์œผ๋กœ ๋‹ค์šด์บ์ŠคํŒ… ํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

์ฝ๊ธฐ ์ „์šฉ์—์„œ mutable๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ๋ณต์ œ๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ์šด mutable ์ปฌ๋ ‰์…˜์„ ์ƒ์„ฑํ•˜์ž.

val list = listOf(1, 2, 3)
val mutableList = list.toMutableList()

 

mutable ๊ฐ์ฒด๋Š” ์˜ˆ์ธกํ•˜๊ธฐ ์–ด๋ ค์šฐ๋ฉฐ ์œ„ํ—˜ํ•˜๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๊ณ , immutable ๊ฐ์ฒด๋Š” ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ, immutable ๊ฐ์ฒด๋Š” ์ž์‹ ์˜ ์ผ๋ถ€๋ฅผ ์ˆ˜์ •ํ•œ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.

 

Int๋Š” immutable์ด์ง€๋งŒ ๋‚ด๋ถ€์ ์œผ๋กœ plus(), minus() ๋“ฑ ์ž์‹ ์„ ์ˆ˜์ •ํ•œ ์ƒˆ๋กœ์šด Int๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

public operator fun plus(other: Int): Int

 

์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ๋งŒ๋“œ๋Š” immutable ๊ฐ์ฒด๋„ ์œ„์™€ ๋น„์Šทํ•œ ํ˜•ํƒœ๋กœ ์ž‘๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

data class User(val name: String, val surname: String) {
    fun witName(name: String) = User(name, surname)
}

์•„์ดํ…œ 2. ๋ณ€์ˆ˜์˜ ์Šค์ฝ”ํ”„๋ฅผ ์ตœ์†Œํ™”ํ•˜๋ผ

ํ”„๋กœ๊ทธ๋žจ์„ ์ถ”์ ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•  ๋•Œ ์ดˆ๊ธฐํ™”๋˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
// ๋‚˜์œ ์˜ˆ์‹œ
var user: User
for(i in users.indices){
    user = users[i]
    print("User at $i is $user")
}


// ์กฐ๊ธˆ ์ข‹์€ ์˜ˆ์‹œ
for(i in users.indices){
    var user = users[i]
    print("User at $i is $user")
}


// ์ข‹์€ ์˜ˆ์‹œ
for((i, user) in users.withIndex()){
    print("User at $i is $user")
}

์•„์ดํ…œ 3. ์ตœ๋Œ€ํ•œ ํ”Œ๋žซํผ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ๋ผ

ํ”Œ๋žซํผ ํƒ€์ž…: ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ ์ „๋‹ฌ๋˜์–ด nullable์ธ์ง€ ์•„๋‹Œ์ง€ ์•Œ ์ˆ˜ ์—†๋Š” ํƒ€์ž…
  • ์ฝ”ํ‹€๋ฆฐ์˜ ์ฃผ์š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” Null-Safety ์ด๋‹ค.
  • ํ”Œ๋žซํผ ํƒ€์ž…์€ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ ์™ธ ํ™œ์šฉํ•˜๋Š” ๊ณณ๊นŒ์ง€ ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๊ฐ€๊ธ‰์  ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
  • ์ฝ”ํ‹€๋ฆฐ์˜ nullable -> ?, not null -> !!

์•„์ดํ…œ 4. inferred ํƒ€์ž…์œผ๋กœ ๋ฆฌํ„ดํ•˜์ง€ ๋ง๋ผ

  • ์ฝ”ํ‹€๋ฆฐ ํƒ€์ž… ์ถ”๋ก ์‹œ ์žŠ์ง€ ๋ง์•„์•ผ ํ• ์ ์€ inferredType์€ ์ •ํ™•ํžˆ ์šฐ์ธก์— ์žˆ๋Š” ํ”ผ์—ฐ์‚ฐ์ž์— ๋งž๋Š” ํƒ€์ž…์ด ์„ค์ •๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
  • ์ถ”๊ฐ€์ ์œผ๋กœ ์ฝ”ํ‹€๋ฆฐ์—์„œ ํƒ€์ž… ์ถ”๋ก ์€ ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™”์‹œ ๊ทธ ํƒ€์ž…์„ ์ถ”๋ก ํ•œ๋‹ค.
  • ์ž๋ฐ”๋„ ์ž๋ฐ”10๋ถ€ํ„ฐ ํƒ€์ž… ์ถ”๋ก ์„ ๋„์ž…ํ•˜์—ฌ ์ง€์›ํ•œ๋‹ค.
  • ํƒ€์ž…์„ ํ™•์‹คํ•˜๊ฒŒ ์ง€์ •ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ช…์‹œ์ ์œผ๋กœ ํƒ€์ž…์„ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์›์น™์„ ๊ฐ€์ง€์ž. (๊ณต๊ฐœ API, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋“ฑ)

์•„์ดํ…œ 5. ์˜ˆ์™ธ๋ฅผ ํ™œ์šฉํ•ด ์ฝ”๋“œ์— ์ œํ•œ์„ ๊ฑธ์–ด๋ผ

ํ™•์‹คํ•˜๊ฒŒ ์–ด๋–ค ํ˜•ํƒœ๋กœ ๋™์ž‘ํ•ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์˜ˆ์™ธ๋ฅผ ํ™œ์šฉํ•ด ์ œํ•œ์„ ๊ฑธ์–ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” ์ฝ”๋“œ์˜ ๋™์ž‘์— ์ œํ•œ์„ ๊ฑธ ๋•Œ ๋‹ค์Œ ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • require: ์•„๊ทœ๋จผํŠธ ์ œํ•œ
  • check: ์ƒํƒœ์™€ ๊ด€๋ จ๋œ ๋™์ž‘ ์ œํ•œ
  • assert: ์–ด๋–ค ๊ฒƒ์ด true์ธ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ณ , ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์—์„œ๋งŒ ์ž‘๋™
fun decode(encoded: ByteArray): ByteArray {
    require(isBase62Encoding(encoded)) { "Input is not encoded correctly" }

    val prepared = translate(encoded, lookup)

    return convert(prepared, TARGET_BASE, STANDARD_BASE)
}

์œ„์™€ ๊ฐ™์€ ์ œ์•ฝ์‚ฌํ•ญ์— ๋Œ€ํ•œ ์žฅ์ ์€?

  • ๋ฌธ์„œ๋ฅผ ์ฝ์ง€ ์•Š์€ ๊ฐœ๋ฐœ์ž๋„ ์˜ˆ์ƒ๋˜๋Š” ๋ฌธ์ œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ•œ ๋™์ž‘์„ ํ•˜๋Š” ๊ฒƒ์€ ์˜ˆ์™ธ๋ฅผ throwํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์œ„ํ—˜ํ•˜๊ณ , ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ํž˜๋“ค๋‹ค.
  • ์ฝ”๋“œ๊ฐ€ ์–ด๋А์ •๋„ ์ž์ฒด์ ์œผ๋กœ ๊ฒ€์ฆ์ด ๋œ๋‹ค.

์•„๊ทœ๋จผํŠธ (require)

  • ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ๋•Œ ํƒ€์ž… ์‹œ์Šคํ…œ์„ ํ™œ์šฉํ•ด์„œ ์•„๊ทœ๋จผํŠธ์— ์ œํ•œ์„ ๊ฑฐ๋Š” ์ฝ”๋“œ
  • IllegalArgumentException์„ throwํ•œ๋‹ค.

 

์ƒํƒœ (check)

๊ตฌ์ฒด์ ์ธ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•  ๋•Œ๋งŒ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์•ผ ํ•  ๋•Œ,

  • ์–ด๋–ค ๊ฐ์ฒด๊ฐ€ ๋ฏธ๋ฆฌ ์ดˆ๊ธฐํ™”๊ฐ€ ๋˜์–ด ์žˆ์–ด์•ผ๋งŒ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ํ•˜๊ณ  ์‹ถ์€ ํ•จ์ˆ˜
  • ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ์„ ํ–ˆ์„๋•Œ๋งŒ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ํ•˜๊ณ  ์‹ถ์€ ํ•จ์ˆ˜
  • ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ์ ์— ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€ ํ•จ์ˆ˜
  • IllegalStateException์„ throwํ•œ๋‹ค.

 

assert

  • ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ
  • ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์˜ ์ฝ”๋“œ์—์„œ๋„ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅ
// ๋‹จ์œ„ ํ…Œ์ŠคํŠธ
assertThat(...)
assertEquals(...)

// ํ”„๋กœ๋•์…˜ ์ฝ”๋“œ
fun pop(index: Int, numbers: MutableList<Int>) {
    val size = numbers.size
    numbers.removeAt(index)

    assert(size == numbers.size)
}


์•„์ดํ…œ 6. ์‚ฌ์šฉ์ž ์ •์˜ ์˜ค๋ฅ˜๋ณด๋‹ค๋Š” ํ‘œ์ค€ ์˜ค๋ฅ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ผ

ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์ ์ด ์žˆ๋‹ค:

  • ๋Œ€๋ถ€๋ถ„์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ด๋ฏธ ์ž˜ ์•Œ๊ณ  ์žˆ๋Š” ์˜ˆ์™ธ๋“ค์ด๋‹ค.
  • API๋ฅผ ๋” ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ปค์Šคํ…€ ์˜ˆ์™ธ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋Š”?

  • ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์˜ˆ์™ธ๋กœ ํ‘œํ˜„ํ•˜๊ธฐ ๊นŒ๋‹ค๋กœ์šด ๊ฒฝ์šฐ
  • ํŠน์ • ๋น„์ฆˆ๋‹ˆ์Šค ๋„๋ฉ”์ธ์— ํŠนํ™”๋œ ์˜ˆ์™ธ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ
  • ๋ณด์ƒ ํŠธ๋žœ์žญ์…˜, ์žฌ์‹œ๋„ ๋“ฑ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ
  • ํด๋ผ์ด์–ธํŠธ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์—๋Ÿฌ ์ฝ”๋“œ ํ™œ์šฉ

์•„์ดํ…œ 7. ๊ฒฐ๊ณผ ๋ถ€์กฑ์ด ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ null๊ณผ Failure๋ฅผ ์‚ฌ์šฉํ•˜๋ผ

๊ฒฐ๊ณผ ๋ถ€์กฑ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•

 

1. null ๋˜๋Š” Failure ๋ฐ˜ํ™˜

  • null: ๊ฒฐ๊ณผ๊ฐ€ ์—†์Œ์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด ๋ฆฌํ„ด
  • Failure: sealed class๋ฅผ ์‚ฌ์šฉํ•ด ์‹คํŒจ ์ƒํƒœ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ (Success, Failure)
  • ์žฅ์ : Failure๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‹คํŒจ ์›์ธ์„ ๋‹ด์„ ์ˆ˜ ์žˆ๊ณ , when์„ ํ†ตํ•ด ์ƒํƒœ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•˜์—ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹จ์ : null์€ ๋ช…์‹œ์ ์ด์ง€ ์•Š๊ณ , NPE(Null Pointer Exception) ๋ฐœ์ƒ์˜ ์œ„ํ—˜์ด ์žˆ๋‹ค.

2. ์˜ˆ์™ธ throw

  • ์žฅ์ : ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋ฉด ํ˜ธ์ถœ์ž์—๊ฒŒ ์˜ค๋ฅ˜๊ฐ€ ์ „๋‹ฌ๋˜๋ฉฐ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ•์ œ๋œ๋‹ค.
  • ๋‹จ์ : ์˜ˆ์™ธ๋Š” ํ”„๋กœ๊ทธ๋žจ ํ๋ฆ„์„ ๋ฐฉํ•ดํ•˜๊ณ , ๋ฌด๋ถ„๋ณ„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ๋‹ค.

+ ์ถ”๊ฐ€

Success, Failure ๋ฅผ ์˜๋ฏธํ•˜๋Š” ์ฝ”ํ‹€๋ฆฐ์˜ Result ํด๋ž˜์Šค

try-catch ๋Œ€์‹  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”ํ‹€๋ฆฐ์˜ runCatching


์•„์ดํ…œ 8. ์ ์ ˆํ•˜๊ฒŒ null์„ ์ฒ˜๋ฆฌํ•˜๋ผ.

null์€ ์ตœ๋Œ€ํ•œ ๋ช…ํ™•ํ•œ ์˜๋ฏธ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

String.toIntOrNull() // String์„ Int๋กœ ์ ์ ˆํ•˜๊ฒŒ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์—†์œผ๋ฉด null ๋ฆฌํ„ด
Iterable<T>.firstOrNull(() → Boolean) // ์ฃผ์–ด์ง„ ์กฐ๊ฑด์— ๋งž๋Š” ์š”์†Œ๊ฐ€ ์—†์œผ๋ฉด null ๋ฆฌํ„ด

 

nullable ํƒ€์ž…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•

  • ?.(safe call), ์Šค๋งˆํŠธ ์บ์ŠคํŒ…, Elvis ์—ฐ์‚ฐ์ž ๋“ฑ ํ™œ์šฉ
  • ์˜ค๋ฅ˜ throw
  • ํ•จ์ˆ˜, ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ฆฌํŒฉํ„ฐ๋งํ•ด์„œ nullable ํƒ€์ž…์ด ๋‚˜์˜ค์ง€ ์•Š๊ฒŒ ๋ฐ”๊พผ๋‹ค.

not-null assertion (!!

  • !! ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ž๋ฐ”์—์„œ nullable์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” NPE ๋ฌธ์ œ๊ฐ€ ๋™์ผํ•˜๊ฒŒ ๋ฐœ์ƒํ•œ๋‹ค.
  • ํ™•์‹คํ•œ ์ƒํ™ฉ์ด ์•„๋‹ˆ๋ผ๋ฉด ์‚ฌ์šฉ์„ ์ง€์–‘ํ•˜์ž.

์˜๋ฏธ ์—†๋Š” nullability ํ”ผํ•˜๊ธฐ

nullability๋Š” ์–ด๋–ป๊ฒŒ๋“  ์ ์ ˆํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ถ”๊ฐ€ ๋น„์šฉ์ด ๋ฐœ์ƒํ•˜๊ธฐ์— ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

  • ํด๋ž˜์Šค์—์Šค nullability์— ๋”ฐ๋ผ ์—ฌ๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค. (List<T> ์˜ get, getOrNull)
  • ์–ด๋–ค ๊ฐ’์ด ํด๋ž˜์Šค ์ƒ์„ฑ ์ดํ›„ ๊ฐ’์ด ์„ค์ •๋œ๋‹ค๋Š” ๋ณด์žฅ์ด ์žˆ๋‹ค๋ฉด, lateinit ํ”„๋กœํผํ‹ฐ์™€ notNull ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ.
  • ์ปฌ๋ ‰์…˜์—์„œ๋Š” null์ด ์•„๋‹Œ ๋นˆ ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•˜๋ผ.

 

lateinit ํ”„๋กœํผํ‹ฐ

  • ๋‚˜์ค‘์— ์†์„ฑ์„ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ๋Š”, lateinit ํ•œ์ •์ž → ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ดํ›„ ์„ค์ •๋  ๊ฒƒ์ž„์„ ๋ช…์‹œํ•˜๋Š” ํ•œ์ •์ž
  • ์ฆ‰, ์ฒ˜์Œ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ๋ฐ˜๋“œ์‹œ ์ดˆ๊ธฐํ™”๊ฐ€ ๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉ
  • ์˜๋„์น˜ ์•Š๊ฒŒ ์‚ฌ์šฉ๋˜์–ด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ๊ทธ ์‚ฌ์‹ค์„ ์•Œ์•„์•ผ ํ•˜๋ฏ€๋กœ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์€ ์˜คํžˆ๋ ค ์ข‹์€ ์ผ

์•„์ดํ…œ 9. use๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌ์†Œ์Šค๋ฅผ ๋‹ซ์•„๋ผ

์ฝ”ํ‹€๋ฆฐ/JVM์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ž๋ฐ” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๋•Œ close ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ข…๋ฃŒ๋ฅผ ํ•ด์•ผํ•˜๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ ์žˆ๋‹ค.

  • InputStream, OutputStream
  • java.sql.Connection
  • Java.io.Reader 

์œ„์˜ ๋ฆฌ์†Œ์Šค๋Š” ์ตœ์ข…์ ์œผ๋กœ ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ์—†์–ด์งˆ ๋•Œ GC๊ฐ€ ์ฒ˜๋ฆฌํ•˜์ง€๋งŒ, ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๊ณ  ๋А๋ฆฌ๋ฉฐ Resource Leak๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๋„ ๋ฐœ์ƒํ•  ์—ฌ์ง€๊ฐ€ ์žˆ๋‹ค.

// ๊ฐ€๋…์„ฑ
fun countCharactersInFile(path: String): Int {
    val reader = BufferedReader(FileReader(path))
    try {
        return reader.lineSequence().sumOf { it.length }
    } finally {
        reader.close() // ์˜ˆ์™ธ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ
    }
}

 

try-finally ๋Œ€์‹  use() ์‚ฌ์šฉํ•˜๋ผ๋Š” ๊ฒฝ๊ณ 

 

fun countCharactersInFile(path: String): Int {
    val bufferedReader = BufferedReader(FileReader(path))
    bufferedReader.use { reader ->
        return reader.lineSequence().sumOf { it.length }
    }
}

// ๊ฐœ์„  1.
fun countCharactersInFile(path: String): Int {
    BufferedReader(FileReader(path)).use { reader ->
        return reader.lineSequence().sumOf { it.length }
    }
}

// ๊ฐœ์„  2.
fun countCharactersInFile(path: String): Int {
    File(path).useLines { lines ->
        return lines.sumOf { it.length }
    }
}


์•„์ดํ…œ 10. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ผ

๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ์ •๋ณด

  • ์ผ๋ฐ˜์ ์ธ ์œ ์Šค ์ผ€์ด์Šค(happy path)
  • ์ผ๋ฐ˜์ ์ธ ์˜ค๋ฅ˜ ์ผ€์ด์Šค์™€ ์ž ์žฌ์ ์ธ ๋ฌธ์ œ (fail)
  • ์˜ˆ์™ธ ์ผ€์ด์Šค์™€ ์ž˜๋ชป๋œ ์•„๊ทœ๋จผํŠธ (range, nullable, ...)
@Test
fun `์œ ํšจํ•˜์ง€ ์•Š์€ ์ธ๋ฑ์Šค์— ์ ‘๊ทผํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•œ๋‹ค`() {
    val numbers = listOf(1, 2, 3, 4, 5)

    // ์œ ํšจํ•˜์ง€ ์•Š์€ ์ธ๋ฑ์Šค(์˜ˆ: ์ธ๋ฑ์Šค 10)๋Š” ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ์•ผ ํ•œ๋‹ค.
    assertThrows(IndexOutOfBoundsException::class.java) {
        get(numbers, 6)  // ๋ฒ”์œ„ ๋ฐ–์˜ ์ธ๋ฑ์Šค
    }
}

 

 

 

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€