lazy

์ฝ”ํ‹€๋ฆฐ lazy ํ”„๋กœํผํ‹ฐ: ์ปดํŒŒ์ผ๋œ ์ฝ”๋“œ ๋ถ„์„

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

Drawing

1. lazy ์ปดํŒŒ์ผ ๊ณผ์ •์˜ ํ•ต์‹ฌ

์ฝ”ํ‹€๋ฆฐ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” by lazy { ... } ๊ตฌ๋ฌธ์„ ๋งŒ๋‚˜๋ฉด, lazy ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ์œ„ํ•œ ๋ณด์กฐ ํ•„๋“œ(backing field)๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•„๋“œ๋Š” Lazy<T> ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๋ฉฐ, ์ดˆ๊ธฐํ™” ๋žŒ๋‹ค์‹์€ ์ด ๊ฐ์ฒด ๋‚ด๋ถ€์— ์บก์ฒ˜๋ฉ๋‹ˆ๋‹ค.

// ์›๋ณธ ์ฝ”ํ‹€๋ฆฐ ์ฝ”๋“œ
class MyClass {
    val myLazyValue: String by lazy {
        "Hello, World!"
    }
}

์œ„ ์ฝ”๋“œ๋Š” JVM ๋ฐ”์ดํŠธ์ฝ”๋“œ๋กœ ์ปดํŒŒ์ผ๋  ๋•Œ, ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•œ ์ž๋ฐ” ์ฝ”๋“œ๋กœ ์—ญ์ปดํŒŒ์ผ๋˜์–ด ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์‹ค์ œ ์ƒ์„ฑ๋˜๋Š” ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์˜์‚ฌ ์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•œ ๊ฒƒ์ž„)

// ์ปดํŒŒ์ผ๋œ ์ž๋ฐ” ์˜์‚ฌ ์ฝ”๋“œ
public final class MyClass {
   // myLazyValue$delegate ํ•„๋“œ ์ƒ์„ฑ. Lazy ๊ฐ์ฒด๋ฅผ ์ €์žฅ
   private final Lazy myLazyValue$delegate;

   // myLazyValue ํ”„๋กœํผํ‹ฐ์˜ ๊ฒŒํ„ฐ(getter)
   public final String getMyLazyValue() {
      // ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๊ฐ์ฒด์˜ value ์†์„ฑ์„ ํ†ตํ•ด ์‹ค์ œ ๊ฐ’์— ์ ‘๊ทผ
      return (String)this.myLazyValue$delegate.getValue();
   }

   public MyClass() {
      // lazy ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Lazy ๊ฐ์ฒด ์ดˆ๊ธฐํ™”
      // LazyThreadSafetyMode.SYNCHRONIZED๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ๋จ
      this.myLazyValue$delegate = LazyKt.lazy(null, new MyClass$$special$$inlined$myLazyValue$1());
   }
}

MyClass์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ, myLazyValue ์ž์ฒด๊ฐ€ ๋ฐ”๋กœ ์ดˆ๊ธฐํ™”๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, Lazy ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” lazy ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด Lazy ๊ฐ์ฒด๋Š” ์ดˆ๊ธฐํ™” ๋กœ์ง์„ ๋‹ด๊ณ  ์žˆ๋Š” ๋žŒ๋‹ค(์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ƒ์„ฑํ•œ MyClass$$special$$inlined$myLazyValue$1 ํด๋ž˜์Šค)์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

LazyKt.lazy

LazyKt.lazy๋Š” ์ฝ”ํ‹€๋ฆฐ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์žˆ๋Š” ์ตœ์ƒ์œ„(top-level) ํ•จ์ˆ˜๋กœ, by lazy { ... } ๊ตฌ๋ฌธ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•ต์‹ฌ ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๋Š” by lazy ๊ตฌ๋ฌธ์„ ์ด ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํ˜ธ์ถœ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ง€์—ฐ ์ดˆ๊ธฐํ™” ๋กœ์ง์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.


LazyKt.lazy์˜ ์—ญํ• 

LazyKt.lazy๋Š” ์ดˆ๊ธฐํ™” ๋กœ์ง์„ ๋‹ด์€ ๋žŒ๋‹ค์‹์„ ์ธ์ž๋กœ ๋ฐ›์•„ Lazy<T> ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ตฌํ˜„์ฒด๋Š” ๋‹ค์Œ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ดˆ๊ธฐํ™” ๋กœ์ง ์บก์ฒ˜: lazy์— ์ „๋‹ฌ๋œ ๋žŒ๋‹ค์‹(์ดˆ๊ธฐํ™” ๋ธ”๋ก)์„ ๊ฐ์ฒด ๋‚ด๋ถ€์— ์บก์ฒ˜ํ•˜์—ฌ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

  2. ์ง€์—ฐ ์ดˆ๊ธฐํ™” ๊ด€๋ฆฌ: ์ด ๊ฐ์ฒด๋Š” getValue() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•  ๋•Œ ๋žŒ๋‹ค์‹์„ ์‹คํ–‰ํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œํ•ฉ๋‹ˆ๋‹ค.


LazyKt.lazy์˜ ์ปดํŒŒ์ผ ๊ณผ์ •

// SynchronizedLazyImpl (๊ธฐ๋ณธ๊ฐ’)
// ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด synchronized ๋ธ”๋ก์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
private class SynchronizedLazyImpl<T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
    private var initializer: (() -> T)? = initializer // ์ดˆ๊ธฐํ™” ๋žŒ๋‹ค
    @Volatile private var _value: Any? = UNINITIALIZED_VALUE // ์‹ค์ œ ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ํ•„๋“œ
    private val lock = lock ?: this

    override val value: T
        get() {
            // ์ด ๋ธ”๋ก์—์„œ๋งŒ ์ดˆ๊ธฐํ™”๊ฐ€ ์ง„ํ–‰๋˜๋„๋ก ๋™๊ธฐํ™”
            val _v1 = _value
            if (_v1 !== UNINITIALIZED_VALUE) {
                return _v1 as T
            }

            return synchronized(lock) {
                val _v2 = _value
                if (_v2 !== UNINITIALIZED_VALUE) {
                    _v2 as T
                } else {
                    val typedValue = initializer!!()
                    _value = typedValue
                    initializer = null // ์ดˆ๊ธฐํ™” ํ›„ ๋žŒ๋‹ค๋ฅผ GC ๋Œ€์ƒ์œผ๋กœ ๋งŒ๋“ฆ
                    typedValue
                }
            }
        }
}

// SafePublicationLazyImpl (PUBLICATION ๋ชจ๋“œ)
// ๋™๊ธฐํ™” ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด ์ž ๊ธˆ ์—†๋Š”(lock-free) ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
private class SafePublicationLazyImpl<T>(initializer: () -> T) : Lazy<T> {
    @Volatile private var initializer: (() -> T)? = initializer
    @Volatile private var _value: Any? = UNINITIALIZED_VALUE

    override val value: T
        get() {
            val value = _value
            if (value !== UNINITIALIZED_VALUE) {
                return value as T
            }

            // ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ด ๋ธ”๋ก์— ์ง„์ž…ํ•  ์ˆ˜ ์žˆ์Œ
            val initializer = this.initializer
            if (initializer != null) {
                val typedValue = initializer()
                // CAS(Compare-and-Swap) ์—ฐ์‚ฐ๊ณผ ์œ ์‚ฌํ•œ ๋กœ์ง์œผ๋กœ
                // _value๊ฐ€ UNINITIALIZED_VALUE์ผ ๋•Œ๋งŒ ๊ฐ’์„ ๋ฎ์–ด์”€
                if (valueUpdater.compareAndSet(this, UNINITIALIZED_VALUE, typedValue)) {
                    this.initializer = null
                    return typedValue
                }
            }
            // ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋จผ์ € ์ดˆ๊ธฐํ™”ํ–ˆ์„ ๊ฒฝ์šฐ
            return _value as T
        }
}

// UnsafeLazyImpl (NONE ๋ชจ๋“œ)
// ๋™๊ธฐํ™” ๋กœ์ง์ด ์ „ํ˜€ ์—†์–ด ๋‹จ์ผ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๊ฐ€์žฅ ๋น ๋ฆ…๋‹ˆ๋‹ค.
private class UnsafeLazyImpl<T>(initializer: () -> T) : Lazy<T>, Serializable {
    private var initializer: (() -> T)? = initializer
    private var _value: Any? = UNINITIALIZED_VALUE

    override val value: T
        get() {
            val initializer = initializer
            if (initializer != null) {
                val typedValue = initializer()
                _value = typedValue
                this.initializer = null
                return typedValue
            }
            return _value as T
        }
}

LazyKt.lazy์˜ ์„ธ๋ถ€ ๋™์ž‘

LazyKt.lazy ํ•จ์ˆ˜๋Š” LazyThreadSafetyMode์— ๋”ฐ๋ผ ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹ค๋ฅธ Lazy ๊ตฌํ˜„์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  • LazyThreadSafetyMode.SYNCHRONIZED (๊ธฐ๋ณธ๊ฐ’): lazy() ํ•จ์ˆ˜๋Š” SynchronizedLazyImpl ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” synchronized ๋ธ”๋ก์„ ์‚ฌ์šฉํ•˜์—ฌ ์ดˆ๊ธฐํ™” ๋กœ์ง์ด ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผํ•˜๋ฉด getValue()๋Š” ์ž ๊ธˆ(lock)์„ ์–ป์€ ์ฒซ ๋ฒˆ์งธ ์Šค๋ ˆ๋“œ๋งŒ ์ดˆ๊ธฐํ™”๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • LazyThreadSafetyMode.PUBLICATION: lazy(LazyThreadSafetyMode.PUBLICATION, ...) ํ˜ธ์ถœ ์‹œ SafePublicationLazyImpl ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ž ๊ธˆ ์—†์ด(lock-free) ์ดˆ๊ธฐํ™” ๋กœ์ง์„ ์‹คํ–‰ํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ดˆ๊ธฐํ™”๋ฅผ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋จผ์ € ์™„๋ฃŒ๋œ ์Šค๋ ˆ๋“œ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์ตœ์ข… ๊ฐ’์œผ๋กœ ์ฑ„ํƒ๋˜๊ณ , ๋‚˜๋จธ์ง€๋Š” ํ๊ธฐ๋ฉ๋‹ˆ๋‹ค.

  • LazyThreadSafetyMode.NONE: lazy(LazyThreadSafetyMode.NONE, ...) ํ˜ธ์ถœ ์‹œ UnsafeLazyImpl ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ์ „ํ˜€ ๊ณ ๋ คํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋‹จ์ผ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๊ฐ€์žฅ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.


2. LazyThreadSafetyMode์— ๋”ฐ๋ฅธ ์‹ค์ œ ๋™์ž‘ ์ฐจ์ด

Lazy<T> ๊ตฌํ˜„์ฒด๋Š” LazyThreadSafetyMode์— ๋”ฐ๋ผ ๋‚ด๋ถ€ ๋กœ์ง์ด ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

  • SYNCHRONIZED (๊ธฐ๋ณธ๊ฐ’):

    getValue()๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ, synchronized ๋ธ”๋ก์ด๋‚˜ ReentrantLock ๊ฐ™์€ **์ž ๊ธˆ(lock)**์„ ์‚ฌ์šฉํ•˜์—ฌ ๋žŒ๋‹ค์‹์ด ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— getValue()๋ฅผ ํ˜ธ์ถœํ•ด๋„, ์ฒซ ๋ฒˆ์งธ ์Šค๋ ˆ๋“œ๋งŒ ๋žŒ๋‹ค์‹์„ ์‹คํ–‰ํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ๋Œ€๊ธฐํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐํ™”๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด _value ํ•„๋“œ์— ๊ฒฐ๊ณผ๊ฐ€ ์ €์žฅ๋˜๊ณ , ์ดํ›„์—๋Š” ๋žŒ๋‹ค์‹ ์‹คํ–‰ ์—†์ด ์ฆ‰์‹œ _value๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  • PUBLICATION:

    getValue()๋Š” ์ž ๊ธˆ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผํ•˜๋ฉด ๋ชจ๋‘ ๋žŒ๋‹ค์‹์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋žŒ๋‹ค์‹์˜ ๊ฒฐ๊ณผ๊ฐ€ _value ํ•„๋“œ์— ์“ฐ์—ฌ์ง€๋Š” ์‹œ์ ์— ์›์ž์ ์ธ compare-and-swap (CAS) ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ์—ฐ์‚ฐ์€ _value๊ฐ€ ์•„์ง ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์„ ๋•Œ๋งŒ ๊ฐ’์„ ๋ฎ์–ด์”๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ดˆ๊ธฐํ™”ํ•˜๋”๋ผ๋„, ์ตœ์ข…์ ์œผ๋กœ๋Š” ํ•˜๋‚˜์˜ ๊ฐ’๋งŒ _value์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์Šค๋ ˆ๋“œ ๊ฐ„ ๋™๊ธฐํ™” ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ค„์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

  • NONE:

    getValue()๋Š” ์•„๋ฌด๋Ÿฐ ๋™๊ธฐํ™” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ˆœ์ˆ˜ํ•œ ๋‹จ์ผ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์„ ๊ฐ€์ •ํ•˜๋ฉฐ, _value ํ•„๋“œ๊ฐ€ null์ธ์ง€ ํ™•์ธํ•˜๊ณ  null์ด๋ฉด ๋žŒ๋‹ค์‹์„ ์‹คํ–‰ํ•˜์—ฌ ๊ฐ’์„ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋“œ๋Š” ๊ฐ€์žฅ ๋น ๋ฅด์ง€๋งŒ, ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์ด ๋ณด์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.


3. ์™œ lazy๋Š” val์—๋งŒ ์‚ฌ์šฉ๋ ๊นŒ?

lazy๋Š” val (์ฝ๊ธฐ ์ „์šฉ) ํ”„๋กœํผํ‹ฐ์—๋งŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” lazy์˜ ๋ณธ์งˆ์ด ๋‹จ ํ•œ ๋ฒˆ์˜ ์ดˆ๊ธฐํ™”๋ฅผ ๋ณด์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. lazy๋Š” ๊ฐ’์„ ์บ์‹œํ•˜๊ณ , ์ดํ›„์˜ ๋ชจ๋“  ์ ‘๊ทผ์— ๋Œ€ํ•ด ๋™์ผํ•œ ์บ์‹œ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ var์— lazy๊ฐ€ ํ—ˆ์šฉ๋œ๋‹ค๋ฉด, myLazyValue = "newValue"์™€ ๊ฐ™์ด ๊ฐ’์„ ์žฌํ• ๋‹นํ•˜๋Š” ๊ฒƒ์€ ์ด "ํ•œ ๋ฒˆ์˜ ์ดˆ๊ธฐํ™”"๋ผ๋Š” lazy์˜ ํ•ต์‹ฌ ๊ฐœ๋…๊ณผ ์ถฉ๋Œํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. val์— ๋Œ€ํ•œ lazy๋Š” ๊ฒŒ์œผ๋ฅธ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ํ”„๋กœํผํ‹ฐ ๋ฒ„์ „๊ณผ ์œ ์‚ฌํ•˜๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

lazy๋Š” ๋‹จ์ˆœํ•œ ๋ฌธ๋ฒ•์  ํŽธ์˜๋ฅผ ๋„˜์–ด, ๋Ÿฐํƒ€์ž„์— ์ง€์—ฐ ์ดˆ๊ธฐํ™” ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ณต์žกํ•œ ๊ฐ์ฒด์™€ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ํŠนํžˆ LazyThreadSafetyMode๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ์ตœ์ ์˜ ์„ฑ๋Šฅ ์ „๋žต์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. lazy๋Š” ๋‹จ์ˆœํžˆ ์ฝ”๋“œ๋ฅผ ์ค„์ด๋Š” ๋„๊ตฌ๊ฐ€ ์•„๋‹ˆ๋ผ, ์„ฑ๋Šฅ๊ณผ ์•ˆ์ „์„ฑ์„ ๋™์‹œ์— ๊ณ ๋ คํ•˜๋Š” ์‹œ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž์˜ ํ•„์ˆ˜์ ์ธ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

Last updated