본문 바로가기

Supplier는 왜 쓰는걸까?

@정소민fan2025. 8. 16. 19:19

자바를 쓰면서 항상 궁금했던 것들... 함수형 인터페이스들은 대체 왜 쓰는걸까??

하나하나 알아가볼건데, Supplier부터 먼저 알아보자.

이 글은 http://youtube.com/watch?v=7e7FCMFrwcg 이 영상을 보고 작성했다. 굉장히 좋은 영상들이 많으니 참고하자.

Supplier<T>는 내부적으로 다음과 같이 생겼다.

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

그냥 이게 정말 끝이다. T 타입을 받아서 get 함수로 돌려주는게 끝이다.

그럼 이것을 왜 쓰는걸까?

코드로 예시 보기

import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
      
        long start = System.currentTimeMillis();
        printIfValidIndex(10, getVeryExpensiveValue());
        printIfValidIndex(-5, getVeryExpensiveValue());
        printIfValidIndex(-10, getVeryExpensiveValue());
        System.out.println("it took " + ((System.currentTimeMillis() - start) / 1000) + " seconds");
    }

    private static String getVeryExpensiveValue() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "Hello World";
    }

    private static void printIfValidIndex(int index, String value) {
        if (index >= 0){
            System.out.println(value);
        }else {
            System.out.println("invalid");
        }
    }
}

getVeryExpensiveValue는 자원을 굉장히 많이 잡아먹는 작업을 추상화했다. 이 함수를 호출하면 3초를 기다리고 문자열을 반환한다.

printIfVaildIndex는 인자로 받은 index가 0 이상일 때만 value를 출력하는데, 지금의 코드는 index가 0 미만일 때도 getVeryExpensiveValue를 호출하여 자원을 잡아먹게 된다.

이 함수를 그대로 실행하게 되면 getVeryExpensiveValue를 총 3번 호출하게 되어 9초의 시간이 걸린다.

 

이 로직을 다시 한번 생각해보면, index가 0미만이라면 엄청난 자원을 잡아먹는 getVeryExpensiveValue를 굳이 호출할 필요도 없을 것이다. 이 비효율적인 로직을 없애기 위해 Supplier를 사용할 수 있다.

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

public class Main {
    public static void main(String[] args) {

        long start = System.currentTimeMillis();
        printIfValidIndex(10, () -> getVeryExpensiveValue());
        printIfValidIndex(-5, () -> getVeryExpensiveValue());
        printIfValidIndex(-10, () -> getVeryExpensiveValue());
        System.out.println("it took " + ((System.currentTimeMillis() - start) / 1000) + " seconds");
    }

    private static String getVeryExpensiveValue() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "Hello World";
    }

    private static void printIfValidIndex(int index, Supplier<String> value) {
        if (index >= 0){
            System.out.println(value.get());
        }else {
            System.out.println("invalid");
        }
    }
}

printIfVaildIndex 에서는 더이상 value는 직접 string으로 받지 않고, Supplier를 통해 받게 된다. 이렇게 사용하게 되면 인자로 람다식을 통해 getVeryExpensiveValue를 받게 되고, Supplier의 get을 호출하기 전까지는 getVeryExpensiveValue가 작동하지 않게 된다 !! 다시 말해서 index가 0 미만일 때도 3초를 기다려야 했던 이전과 달리 필요할 때만 자원을 사용하면 된다는 것이다!!

그러면 결국 getVeryExpensiveValue가 한번만 호출되게 되고 3초만 기다리면 끝이다.

 

Spring을 배우면서 Supplier가 내부적으로 엄청나게 많이 사용되는 것을 보았는데, 지연되어서 사용된다는 것은 알았지만 왜 지연해서 사용해야하는지를 몰랐었다.

JPA의 지연 로딩이나 프록시 패턴 등 성능을 위해 일부러 lazy 기법을 사용하는 기술이 굉장히 많다 !! 이들도 천천히 알아보자.

'Java' 카테고리의 다른 글

JVM 튜?닝?  (1) 2025.11.27
자바 가비지 컬렉터 (GC)  (0) 2025.09.07
JVM  (0) 2025.09.06
SOLID 원칙  (0) 2025.09.05
와일드카드<?>가 무엇인가?  (0) 2025.08.23
정소민fan
@정소민fan :: 코딩은 관성이야

코딩은 관성적으로 해야합니다 즐거운 코딩 되세요

목차