IMCAT.DEV
로그인 가입
Scala 중급 비동기

Scala 비동기 프로그래밍 기초 (Futures)

Scala 비동기 프로그래밍 기초 (Futures) — 중급

비동기 프로그래밍 기초 (Futures)

1. 도입 (왜 배워야 하는가)

비동기 프로그래밍은 현대 소프트웨어 개발에서 필수적인 기술로, 특히 웹 애플리케이션과 같은 I/O 중심의 서비스에서 매우 중요합니다. 비동기 프로그래밍을 사용하면, 서버가 여러 작업을 동시에 처리할 수 있어 사용자에게 더 빠르고 원활한 경험을 제공합니다. 만약 비동기 프로그래밍을 모른다면, 애플리케이션이 사용자 요청을 처리하는 동안 다른 작업이 차단되어 성능 저하를 초래할 수 있습니다. 예를 들어, 사용자가 웹페이지에서 버튼을 클릭했을 때, 서버가 응답을 기다리는 동안 화면이 멈춰버린다면 사용자는 불편을 느끼고 이탈할 수 있습니다.

2. 핵심 개념 설명

비동기 프로그래밍에서 가장 중요하게 다루는 개념은 "Future"입니다. Future는 비동기적으로 실행되는 작업의 결과를 나타내는 객체입니다. 이 객체는 작업이 완료되면 결과를 반환하거나 예외를 던질 수 있습니다.

비유

Future는 마치 친구에게 음식을 주문하고, 음식이 배달될 때까지 기다리지 않고 다른 일을 할 수 있는 상황과 비슷합니다. 음식을 주문하는 것은 비동기 작업이며, 주문의 결과(배달된 음식)는 Future로 표현될 수 있습니다.

관련 용어 정리

용어설명
Future비동기 작업의 결과를 나타내는 객체
PromiseFuture의 결과를 나중에 제공하기 위한 객체
AwaitFuture의 결과가 준비될 때까지 기다림

3. 기본 코드 예제

아래는 Scala에서 Future를 사용하는 기본적인 예제입니다.

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

// 비동기 작업 정의
val futureResult: Future[Int] = Future {
  // 2초 대기 후 10을 반환
  Thread.sleep(2000)
  10
}

// 결과를 출력
futureResult.foreach(result => println(s"결과는: $result"))

실행 결과

(2초 후) 결과는: 10

코드 한 줄씩 동작 설명

  1. import scala.concurrent.Future: Future 클래스를 사용하기 위해 필요한 라이브러리를 가져옵니다.
  2. import scala.concurrent.ExecutionContext.Implicits.global: 비동기 작업을 실행할 스레드 풀을 설정합니다.
  3. val futureResult: Future[Int] = Future {...}: 비동기 작업을 정의하고, 결과를 Future 객체에 저장합니다.
  4. Thread.sleep(2000): 2초 동안 대기합니다. 이 부분은 비동기 작업의 예제입니다.
  5. futureResult.foreach(result => println(s"결과는: $result")): Future의 결과가 준비되면 결과를 콘솔에 출력합니다.
  6. 4. 실전 활용 예제

    예제 1: 쇼핑몰에서 장바구니의 총 가격 계산

    고객이 장바구니에 담은 상품의 총 가격을 비동기로 계산할 수 있습니다.

    import scala.concurrent.Future
    import scala.concurrent.ExecutionContext.Implicits.global
    
    def calculateTotalPrice(cartItems: List[Double]): Future[Double] = Future {
      // 장바구니의 총 가격 계산
      cartItems.sum
    }
    
    val items = List(100.0, 200.0, 300.0)
    calculateTotalPrice(items).foreach(total => println(s"장바구니 총 가격: $total"))

    예제 2: 데이터베이스에서 사용자 정보 조회

    데이터베이스에서 사용자 정보를 비동기로 조회하여 애플리케이션의 응답성을 높일 수 있습니다.

    def fetchUserData(userId: String): Future[String] = Future {
      // 데이터베이스에서 사용자 정보를 조회 (가정)
      Thread.sleep(1000) // 조회 시간 시뮬레이션
      s"User data for ID: $userId"
    }
    
    fetchUserData("12345").foreach(data => println(data))

    5. 흔한 실수와 주의사항

    1. Future의 결과를 직접 사용하려는 실수

    // 잘못된 예
    val result = futureResult.value.get
    • 문제: Future가 완료되기 전에 값을 가져오려 하므로 예외 발생 가능.
    • 올바른 예:
    • futureResult.foreach(result => println(s"결과는: $result"))

      2. Blocking 호출 사용

      // 잘못된 예
      val blockingResult = Await.result(futureResult, 10.seconds)
    • 문제: Blocking 호출을 사용하면 비동기의 장점을 잃게 됨.
    • 올바른 예: Future의 결과를 비동기로 처리.
    • 6. 정리

    • Future는 비동기 작업의 결과를 나타내는 객체입니다.
    • 비동기 프로그래밍은 애플리케이션의 응답성을 높이는 데 필수적입니다.
    • 비동기 작업의 결과를 사용할 때는 foreach를 활용해야 합니다.
    • Blocking 호출은 피하고, 결과를 비동기로 처리하는 것이 좋습니다.

다음에 학습하면 좋은 주제는 Promise, Akka Streams와 같은 더 복잡한 비동기 패턴입니다.