0Pricing
Scala for Backend Engineering & Functional Programming · 강의

클로저

상태를 캡처합니다

클로저은(는) CoddyKit의 무료 Scala for Backend Engineering & Functional Programming 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Scala for Backend Engineering & Functional Programming 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Scala for Backend Engineering & Functional Programming 강의에는 총 4개의 강의가 포함되어 있습니다.

클로저란 무엇입니까?

클로저는 자신이 정의된 주변 범위의 변수를 포착하는 함수입니다. 이러한 변수를 '감싸서', 해당 범위가 반환된 후에도 변수에 접근할 수 있도록 유지합니다.

object Main {
  def main(args: Array[String]): Unit = {
    val factor = 3
    val multiply = (x: Int) => x * factor
    println(multiply(5))
  }
}

자유 변수 포착하기

x => x * factor에서 x는 매개변수지만 factor는 바깥 범위에서 가져온 자유 변수입니다. 함수는 이 변수에 대한 참조를 지닙니다.

object Main {
  def main(args: Array[String]): Unit = {
    val greeting = "Hello"
    val greet = (name: String) => s"$greeting, $name!"
    println(greet("Ann"))
    println(greet("Bob"))
  }
}

클로저는 범위보다 오래 유지됩니다

함수가 클로저를 반환하면, 해당 클로저가 존재하는 동안 포착된 변수도 계속 유지됩니다. 함수를 정의한 함수가 이미 실행을 마친 뒤에도 마찬가지입니다.

object Main {
  def makeAdder(n: Int): Int => Int = x => x + n
  def main(args: Array[String]): Unit = {
    val add10 = makeAdder(10)
    val add100 = makeAdder(100)
    println(add10(5))
    println(add100(5))
  }
}

각 클로저는 고유한 포착 상태를 가집니다

함수 팩토리를 두 번 호출하면 서로 독립적인 클로저 두 개가 생성되며, 각 클로저는 자신이 포착한 값을 기억합니다.

object Main {
  def prefixer(p: String): String => String = s => p + s
  def main(args: Array[String]): Unit = {
    val withDr = prefixer("Dr. ")
    val withMr = prefixer("Mr. ")
    println(withDr("Smith"))
    println(withMr("Jones"))
  }
}

변경 가능한 상태 포착하기

클로저는 var를 포착해 읽고 수정할 수 있습니다. 이를 통해 클로저가 호출 사이에서 상태를 유지하도록 만들 수 있으며, 카운터가 그 예입니다.

object Main {
  def main(args: Array[String]): Unit = {
    var count = 0
    val increment = () => { count += 1; count }
    println(increment())
    println(increment())
    println(increment())
  }
}

카운터 팩토리

지금까지의 개념을 결합해 보십시오. 자신만의 비공개 var를 포착하는 클로저를 반환하는 함수로 캡슐화된 독립적인 카운터를 만들 수 있습니다.

object Main {
  def counter(): () => Int = {
    var n = 0
    () => { n += 1; n }
  }
  def main(args: Array[String]): Unit = {
    val c1 = counter()
    val c2 = counter()
    println(c1())
    println(c1())
    println(c2())
  }
}

클로저는 복사본이 아니라 참조를 포착합니다

클로저는 스냅샷이 아니라 변수 자체를 포착합니다. 클로저가 생성된 후 포착된 var가 변경되면 클로저는 새로운 값을 확인합니다.

object Main {
  def main(args: Array[String]): Unit = {
    var msg = "first"
    val show = () => println(msg)
    show()
    msg = "second"
    show()
  }
}

val 포착을 우선하기

변경할 수 없는 val을 포착하면 예상치 못한 동작을 피할 수 있습니다. 포착된 값이 변하지 않으므로 클로저가 예측 가능하게 동작합니다. 함수형 코드에서는 val 포착을 우선하십시오.

object Main {
  def main(args: Array[String]): Unit = {
    val taxRate = 0.2
    val withTax = (price: Double) => price * (1 + taxRate)
    println(withTax(100))
  }
}

컬렉션 메서드와 클로저

map, filter 등에 전달하는 람다는 외부 변수를 참조할 때마다 클로저입니다. 이는 일상적인 Scala 코드에서 매우 흔합니다.

object Main {
  def main(args: Array[String]): Unit = {
    val threshold = 3
    val nums = List(1, 2, 3, 4, 5)
    val big = nums.filter(_ > threshold)
    println(big)
  }
}

반복문에서 포착할 때의 함정

Scala에서는 for 반복문의 변수에 매 반복마다 새로운 바인딩이 만들어지므로 클로저가 서로 다른 값을 포착합니다. 덕분에 다른 일부 언어에서 볼 수 있는 고전적인 오류를 피할 수 있습니다.

object Main {
  def main(args: Array[String]): Unit = {
    val fns = for (i <- 1 to 3) yield () => i
    println(fns.map(f => f()))
  }
}

클로저는 동작과 데이터를 캡슐화합니다

클로저는 동작(함수 본문)과 데이터(포착된 변수)를 하나로 묶습니다. 이는 메서드 하나를 가진 작은 객체를 대신할 수 있는 간단한 방법입니다.

object Main {
  def discounter(rate: Double): Double => Double = price => price * (1 - rate)
  def main(args: Array[String]): Unit = {
    val sale = discounter(0.25)
    println(sale(80))
    println(sale(200))
  }
}

빠른 확인

클로저는 주변 범위에서 무엇을 포착합니까?

복습

클로저에 대해 배웠습니다.

  • 클로저는 바깥 범위의 자유 변수를 포착합니다
  • 포착된 변수는 함수를 정의한 함수보다 오래 유지됩니다
  • 각 클로저 인스턴스는 자신만의 포착된 상태를 가집니다
  • 클로저는 참조를 포착하므로 변경 가능한 포착 대상은 바뀔 수 있습니다
  • map/filter에 전달하는 람다는 일상적으로 사용하는 클로저입니다

자주 묻는 질문

“클로저” 강의는 무료인가요?

네 — “클로저” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Scala for Backend Engineering & Functional Programming 강의 전체를 잠금 해제할 수 있습니다. Scala for Backend Engineering & Functional Programming 강의에는 총 4개의 강의가 포함되어 있습니다.

“클로저”에서 뭘 배우나요?

상태를 캡처합니다 브라우저에서 직접 실행하는 실습 코드로 Scala for Backend Engineering & Functional Programming을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Scala for Backend Engineering & Functional Programming을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Scala for Backend Engineering & Functional Programming은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“클로저” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Scala for Backend Engineering & Functional Programming 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Scala for Backend Engineering & Functional Programming 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 값으로서의 함수
  2. 커링
  3. 함수 조합
  4. 클로저
← Scala for Backend Engineering & Functional Programming(으)로 돌아가기