트램펄린
스택 안전 재귀를 알아봅니다
트램펄린은(는) 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개의 강의가 포함되어 있습니다.
@tailrec의 한계
@tailrec는 함수가 직접 자기 자신을 호출하는 경우만 최적화합니다. 상호 재귀(서로를 호출하는 두 함수)에는 사용할 수 없으므로 스택이 계속 증가합니다. 이 문제는 트램펄린으로 해결합니다.
상호 재귀 문제
isEven과 isOdd가 서로를 사용하여 정의되었다고 생각해 보십시오. 큰 수에서는 스택이 넘치며, 둘 다 @tailrec로 표시할 수 없습니다.
object Main {
def isEven(n: Int): Boolean = if (n == 0) true else isOdd(n - 1)
def isOdd(n: Int): Boolean = if (n == 0) false else isEven(n - 1)
def main(args: Array[String]): Unit = {
println(isEven(10))
}
}트램펄린이란 무엇인가요?
트램펄린은 재귀 호출을 데이터로 바꿉니다. 자기 자신을 호출하는 대신 함수가 다음 단계에 대한 설명을 반환합니다. 실행 함수가 이 단계들을 반복해서 실행하므로 스택이 일정하게 유지됩니다.
표준 라이브러리의 TailRec
Scala는 TailRec 타입과 함께 scala.util.control.TailCalls를 제공합니다. 최종 결과에는 done(x)을 사용하고, 다음 호출을 지연하려면 tailcall(...)을 사용하십시오.
import scala.util.control.TailCalls._
object Main {
def isEven(n: Int): TailRec[Boolean] =
if (n == 0) done(true) else tailcall(isOdd(n - 1))
def isOdd(n: Int): TailRec[Boolean] =
if (n == 0) done(false) else tailcall(isEven(n - 1))
def main(args: Array[String]): Unit = {
println(isEven(100000).result)
}
}done과 tailcall
두 가지 기본 구성 요소는 다음과 같습니다.
done(value)는 최종 답을 감쌉니다.tailcall(expr)은TailRec을 반환하는 호출을 지연합니다.
.result를 호출하면 트램펄린 반복문이 실행되어 값을 생성합니다.
스택 안전성
각 tailcall은 중첩된 Java 호출을 만드는 대신 실행 함수로 제어를 돌려주므로, JVM 스택은 재귀 깊이에 따라 증가하지 않습니다. 위의 예제는 오버플로 없이 100,000단계를 처리합니다.
자기 재귀에 트램펄린 적용하기
누산기를 쉽게 사용할 수 없는 일반적인 깊은 자기 재귀에도 트램펄린을 사용할 수 있습니다. 여기서는 깊은 카운트다운이 스택 안전하게 유지됩니다.
import scala.util.control.TailCalls._
object Main {
def countDown(n: Int): TailRec[Int] =
if (n == 0) done(0) else tailcall(countDown(n - 1))
def main(args: Array[String]): Unit = {
println(countDown(500000).result)
}
}flatMap으로 결과 결합하기
TailRec은 map과 flatMap을 지원하므로, 스택 안전성을 유지하면서 지연된 호출 후에 작업을 수행할 수 있습니다.
import scala.util.control.TailCalls._
object Main {
def sum(n: Int): TailRec[Int] =
if (n == 0) done(0)
else tailcall(sum(n - 1)).map(_ + n)
def main(args: Array[String]): Unit = {
println(sum(100000).result)
}
}실행 반복문의 작동 방식
개념적으로 .result는 반복문을 실행합니다. 현재 단계를 가져오고, done이면 해당 값을 반환하며, 지연된 호출이면 한 단계만 평가한 뒤 계속합니다. 이 모든 과정이 일정한 스택 공간에서 이루어집니다.
효과 라이브러리에서의 트램펄린
Cats Effect와 ZIO 같은 라이브러리는 내부적으로 flatMap 연쇄에 트램펄린을 적용합니다. 따라서 스택 오버플로 없이 깊게 중첩된 효과 프로그램을 만들 수 있습니다. 트램펄린은 스택 안전한 함수형 효과의 기반입니다.
트램펄린을 사용할 때
다음과 같은 경우 트램펄린을 사용합니다:
- 하나의 꼬리 재귀 함수로 만들 수 없는 상호 재귀가 있는 경우
- 재귀가 스택에 담기에는 너무 깊고 누적자를 적용하기 어려운 경우
단순한 자기 재귀라면 먼저 누적자와 함께 @tailrec를 사용하는 편이 좋습니다.
빠른 확인
트램펄린에 대한 이해도를 확인해 보세요.
복습
트램펄린을 배웠습니다.
- 상호 재귀와 매우 깊은 재귀를 스택 안전하게 만듭니다.
TailCalls의done(x)과tailcall(...)을 사용한 다음.result를 사용합니다.TailRec은map/flatMap을 지원합니다.- 스택 안전한 효과 라이브러리의 기반이 됩니다.
자주 묻는 질문
“트램펄린” 강의는 무료인가요?
네 — “트램펄린” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 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 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.