Lazy

์ฝ”ํ‹€๋ฆฐ์˜ lazy๋Š” ์ง€์—ฐ ์ดˆ๊ธฐํ™”๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ค‘์š”ํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋กœ, ์„ ์–ธ๋œ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์‹ค์ œ๋กœ ์‚ฌ์šฉ๋  ๋•Œ ์ดˆ๊ธฐํ™”๋˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ณธ ๊ธ€์—์„œ๋Š” lazy๊ฐ€ ์ปดํŒŒ์ผ ์‹œ์ ์— ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋ฉฐ, ์ปดํŒŒ์ผ ํ›„ ์–ด๋–ค ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜๋˜๋Š”์ง€๋ฅผ ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


1. lazy์˜ ๋™์ž‘ ๊ฐœ์š”

lazy๋Š” ์ฝ”ํ‹€๋ฆฐ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜๋กœ, Lazy<T> ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” getValue() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ดˆ๊ธฐํ™”๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๋žŒ๋‹ค๋ฅผ ์‹คํ–‰ํ•ด ๊ฐ’์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

val lazyValue: String by lazy {
    println("Initializing")
    "Hello, Kotlin!"
}

์œ„ ์ฝ”๋“œ๋Š” ์‹ค์ œ๋กœ ์‚ฌ์šฉ๋  ๋•Œ ์ดˆ๊ธฐํ™”๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉฐ, ์ดํ›„์—๋Š” ์บ์‹œ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.


2. ์ปดํŒŒ์ผ ์ „ ์ฝ”ํ‹€๋ฆฐ ์ฝ”๋“œ

์ปดํŒŒ์ผ ์ „์˜ lazy ์ฝ”๋“œ๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

val lazyValue: String by lazy {
    println("Initializing")
    "Hello, Kotlin!"
}

fun main() {
    println(lazyValue)  // ์ฒซ ํ˜ธ์ถœ: ์ดˆ๊ธฐํ™” ๋ฐœ์ƒ
    println(lazyValue)  // ๋‘ ๋ฒˆ์งธ ํ˜ธ์ถœ: ์บ์‹œ๋œ ๊ฐ’ ๋ฐ˜ํ™˜
}

3. ์ปดํŒŒ์ผ ํ›„ ๋””์ปดํŒŒ์ผ๋œ Java ์ฝ”๋“œ

์œ„ ์ฝ”๋“œ๋ฅผ ์ปดํŒŒ์ผํ•œ ํ›„ ๋””์ปดํŒŒ์ผํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ Java ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.

public final class MainKt {
    private static final Lazy<String> lazyValue = LazyKt.lazy(() -> {
        System.out.println("Initializing");
        return "Hello, Kotlin!";
    });

    public static final void main() {
        System.out.println(lazyValue.getValue()); // ์ฒซ ํ˜ธ์ถœ
        System.out.println(lazyValue.getValue()); // ๋‘ ๋ฒˆ์งธ ํ˜ธ์ถœ
    }
}

๋ถ„์„

  1. lazy ํ”„๋กœํผํ‹ฐ๋Š” Lazy<T> ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.

  2. ์ดˆ๊ธฐํ™” ๋ธ”๋ก์€ ๋žŒ๋‹ค๋กœ ๊ฐ์‹ธ์ ธ Lazy ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž์— ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

  3. getValue() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ๋žŒ๋‹ค๊ฐ€ ์‹คํ–‰๋˜์–ด ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•˜๊ฑฐ๋‚˜, ์ด๋ฏธ ์ดˆ๊ธฐํ™”๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.


4. Lazy ๊ตฌํ˜„์ฒด

์ฝ”ํ‹€๋ฆฐ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์„ธ ๊ฐ€์ง€ Lazy ๊ตฌํ˜„์ฒด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

4.1 ๊ธฐ๋ณธ ๊ตฌํ˜„์ฒด: synchronizedLazyImpl

lazy๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™๊ธฐํ™”๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ๋™์ž‘ํ•˜๊ธฐ ์œ„ํ•ด synchronizedLazyImpl์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

public final class SynchronizedLazyImpl<T> implements Lazy<T> {
    private volatile Object _value = UNINITIALIZED_VALUE;
    private final Function0<T> initializer;

    public SynchronizedLazyImpl(Function0<T> initializer) {
        this.initializer = initializer;
    }

    public T getValue() {
        Object result = _value;
        if (result == UNINITIALIZED_VALUE) {
            synchronized (this) {
                result = _value;
                if (result == UNINITIALIZED_VALUE) {
                    result = initializer.invoke();
                    _value = result;
                }
            }
        }
        return (T) result;
    }
}

4.2 ๋‹ค๋ฅธ ๊ตฌํ˜„์ฒด: UnsafeLazyImpl, SafePublicationLazyImpl

  • UnsafeLazyImpl: ๋™๊ธฐํ™”๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„ ์„ฑ๋Šฅ์ด ์ข‹์ง€๋งŒ, ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋Š” ์•ˆ์ „ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • SafePublicationLazyImpl: ์ดˆ๊ธฐํ™”๊ฐ€ ํ•œ ๋ฒˆ ์ด์ƒ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, ์ตœ์ข…์ ์œผ๋กœ ์ดˆ๊ธฐํ™”๋œ ๊ฐ’์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

LazyThreadSafetyMode๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„์ฒด๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

val unsafeLazyValue: String by lazy(LazyThreadSafetyMode.NONE) {
    println("Initializing")
    "Hello, Unsafe!"
}

5. lazy ํ”„๋กœํผํ‹ฐ์˜ ์ „์ฒด ๋™์ž‘ ํ๋ฆ„

  1. ์ปดํŒŒ์ผ ์‹œ์ 

    • by lazy๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ Lazy ๊ตฌํ˜„์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ดˆ๊ธฐํ™” ๋žŒ๋‹ค๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

    • ํ”„๋กœํผํ‹ฐ ์ ‘๊ทผ์€ getValue() ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ๋กœ ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค.

  2. ์‹คํ–‰ ์‹œ์ 

    • ์ฒซ ๋ฒˆ์งธ ํ˜ธ์ถœ ์‹œ getValue()๊ฐ€ ์‹คํ–‰๋˜์–ด ๋žŒ๋‹ค๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

    • ์ดˆ๊ธฐํ™”๋œ ๊ฐ’์ด _value์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

    • ์ดํ›„ ํ˜ธ์ถœ์€ _value์— ์ €์žฅ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

Last updated

Was this helpful?