이전 포스팅에서 네티의 이벤트 루프 스레드를 알아보았는데, 작성된 스칼라 코드에서 다음과 같은 f.channel().closeFuture().sync() 표기를 보았을 것이다. 비동기 호출을 위해 이와 같이 퓨처 패턴을 사용했는데, 그렇다면 퓨처 Future 패턴이란 무엇일까?


네티는 비동기 호출을 위한 두 가지 패턴을 제공한다. 첫 번째는 리액터 패턴의 구현체인 이벤트 핸들러이며 두 번째는 퓨처 패턴이다. 이벤트 핸들러는 이전 포스팅에서 살펴보았으니 퓨처 패턴의 구현체와 사용법을 살펴보자.

퓨처 패턴은 미래에 완료될 작업을 등록하고, 처리 결과를 확인하는 객체를 통해서 작업의 완료를 확인하는 패턴 이다. 정의가 조금 모호하니까 간단한 예를 살펴보자. 애인의 생일에 애인에게 특별한 케이크를 선물하려고 빵집으로 간다. 빵집 주인에게 하트가 99개 그려진 특별한 케이크를 만들어달라고 부탁한 뒤 케이크의 값을 치른다. 빵집 주인이 내일 오후에 케이크를 찾으러 오라면서 케이크 주문서 를 주었다. 여러분은 케이크를 빨리 받고 싶은 마음에 케이크 주문서를 가지고 오후 1시에 빵집을 방문했으나 아직 메이크가 완성되지 않았고 1시간 뒤에 완성될 것 같다고 한다. 1시간 뒤에 여러분은 빵집에서 메이크 주문서로 케이크를 교환했다.

퓨처 패턴은 메서드를 호출하는 즉시 퓨처 객체 를 돌려준다. 위의 예에서는 케이크 주문서에 해당한다. 메서드의 처리 결과는 나중에 Future 객체를 통해서 확인한다. 위의 예에서는 케이크 주문서가 이에 해당하며 이것을 간단한 의사코드로 옮기면 아래와 같다.

object SpecialCake {
    def main(args: Array[String]): Unit = {
        val bakery = new Bakery()

        // 케이크를 주문하고 주문서를 받는다.
        val future = bakery.orderCake()

        // 다른 일을 한다.
        ...
        doSomething()
        ...

        if (future.isDone()) {  // 케이크가 완성되었는지 확인
            val cake = future.getCake()
        } else {
            while (future.isDone() != true) { // 케이크가 완성되었는지 확인
                ...
                doSomething()
                ...
            }

            // while 루프를 빠져나왔으므로 완성된 케이크를 가져온다.
            val cake = future.getCake()
        }
    }
}