์ถ์ฒ
ChatGPT
์๋ฐ์์๋ Tail Recursion Optimization(TCO)์ด ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์๋์ง ์๋๋ค. ์ด๋ ์๋ฐ์ ์ปดํ์ผ๋ฌ(Javac)์ JVM์ ์ค๊ณ๊ฐ TCO๋ฅผ ์ต์ ํํ์ง ์๋๋ก ๋์ด ์๊ธฐ ๋๋ฌธ์ด๋ค. Tail Recursion Optimization์ด๋ ์ฌ๊ท ํจ์์ ๋ง์ง๋ง ํธ์ถ์ ์คํ ํ๋ ์์ ์ถ๊ฐํ์ง ์๊ณ ์ฒ๋ฆฌํด StackOverflowError๋ฅผ ๋ฐฉ์งํ๋ ์ต์ ํ ๊ธฐ๋ฒ์ด๋ค.
์๋ฐ์์ Tail Recursion Optimization์ ๋ฏธ์ง์ํ๋ ์ด์
1. JVM ์คํ ๋ชจ๋ธ
์๋ฐ์ JVM์ ์คํ ๊ธฐ๋ฐ์ ๊ฐ์ ๋จธ์ ์ผ๋ก, ๊ฐ ๋ฉ์๋ ํธ์ถ ์๋ง๋ค ์๋ก์ด ์คํ ํ๋ ์์ ์ถ๊ฐํ๋ค. JVM์ ๊ธฐ๋ณธ ์ค๊ณ ์์น ์ค ํ๋๋ ๋ฉ์๋ ํธ์ถ๊ณผ ๊ด๋ จ๋ ๋๋ฒ๊น ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด๋ฏ๋ก, ๋ชจ๋ ํธ์ถ์ด ๋ช ์์ ์ผ๋ก ์คํ ํ๋ ์์ ์ฌ์ฉํ๊ฒ ๋์ด ์๋ค.
2. ์ต์ ํ์ ๋ถํ์ค์ฑ
TCO๋ ์ปดํ์ผ๋ฌ๊ฐ ํ๋จํด ์ต์ ํ๋ฅผ ์ํํด์ผ ํ๋๋ฐ, ์๋ฐ ์ปดํ์ผ๋ฌ(Javac)๋ ์ด๋ฐ ์ต์ ํ๋ฅผ ์ํํ์ง ์๋๋ค. ์๋ฐ๋ ์ฑ๋ฅ๋ณด๋ค ์์ ์ฑ๊ณผ ๋๋ฒ๊น ๊ฐ๋ฅ์ฑ์ ๋ ์ค์ํ๊ฒ ์ฌ๊ธฐ๊ธฐ ๋๋ฌธ์ JVM ๋ ๋ฒจ์์ TCO๋ฅผ ์ง์ํ์ง ์๋๋ค.
3. ๋๋ฒ๊น ๋ฐ ์คํ ์ถ์
์๋ฐ๋ ๋๋ฒ๊น ๊ณผ ์คํ ์ถ์ (Stack Trace)์ ์ฝ๊ฒ ํ๋๋ก ์ค๊ณ๋์๋ค. ์ฌ๊ท ํธ์ถ์์ ์คํ ํ๋ ์์ ์ ๊ฑฐํ๋ฉด ๋๋ฒ๊น ์์ ํธ์ถ ์คํ์ด ์์ค๋๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ๊ฐ ๋ ์ด๋ ค์์ง๋ค.
์๋ฐ์์ Tail Recursion Optimization์ ๋์ฒดํ๋ ๋ฐฉ๋ฒ
์๋ฐ์์ TCO๋ฅผ ์ง์ ์ฌ์ฉํ ์๋ ์์ง๋ง, ๋น์ทํ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ ์ํด ๋ค๋ฅธ ๋ฐฉ๋ฒ๋ค์ ์ฌ์ฉํ ์ ์๋ค.
1. ๋ฐ๋ณต๋ฌธ(Iterative) ์ฌ์ฉ
์ฌ๊ท๋ฅผ ๋ฐ๋ณต๋ฌธ์ผ๋ก ๋ณํํด ์คํ ์ค๋ฒํ๋ก์ฐ๋ฅผ ๋ฐฉ์งํ ์ ์๋ค. ๋ฐ๋ณต๋ฌธ์ ์คํ ํ๋ ์์ ์ถ๊ฐํ์ง ์๊ณ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ์ฝํ๋ฏ๋ก, ์ผ๋ฐ์ ์ผ๋ก ๊น์ ์ฌ๊ท๋ณด๋ค ๋ ์์ ํ๋ค.
public int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}
์ด ์ฝ๋๋ ์ฌ๊ท ๋์ ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํด ํฉํ ๋ฆฌ์ผ์ ๊ณ์ฐํ๋ค. ์คํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ ์ฌ๊ท ๊น์ด์ ์ ํ์ด ์๋ค.
2. ๋ช ์์ ์คํ ์ฌ์ฉ
ํ๋ก๊ทธ๋๋จธ๊ฐ ์ง์ ์คํ ์๋ฃ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๊ท๋ฅผ ๊ด๋ฆฌํ ์ ์๋ค. ์ด ๋ฐฉ๋ฒ์ ์ฌ๊ท๋ฅผ ๋ฐ๋ณต๋ฌธ์ผ๋ก ๋ณํํ๋ฉด์ ์ฌ๊ท ํธ์ถ์ ํน์ฑ์ ์ ์งํ๋ค.
public int factorial(int n) {
Stack<Integer> stack = new Stack<>();
int result = 1;
while (n > 1) {
stack.push(n);
n--;
}
while (!stack.isEmpty()) {
result *= stack.pop();
}
return result;
}
์์ธผ ์ฝ๋์์๋ ์๋ฐ์ Stack ํด๋์ค๋ฅผ ์ฌ์ฉํด ํฉํ ๋ฆฌ์ผ ๊ณ์ฐ์ ์ํ ๋ช ์์ ์คํ์ ๊ด๋ฆฌํ๋ค.
3. ํธ๋ผํ๋ฆฐ (Trampoline) ํจํด
ํธ๋จํ๋ฆฐ ํจํด์ ์ฌ์ฉํ์ฌ ์ฌ๊ท ํธ์ถ์ ๋ฐ๋ณต๋ฌธ์ผ๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ด๋ค. ์ด ํจํด์ ๊ผฌ๋ฆฌ ์ฌ๊ท๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ํธ์ถํ์ง ์๊ณ , ํจ์์ ๋ฐํ ๊ฐ์ ํ์ฉํ์ฌ ๋ค์ ํธ์ถ์ ๊ฒฐ์ ํ๋ ๋ฐฉ์์ด๋ค.
import java.util.function.Supplier;
public class Trampoline<T> {
private final Supplier<Trampoline<T>> nextStep;
private Trampoline(Supplier<Trampoline<T>> nextStep) {
this.nextStep = nextStep;
}
public T result() {
Trampoline<T> step = this;
while (step.nextStep != null) {
step = step.nextStep.get();
}
return step.result();
}
public static <T> Trampoline<T> more(Supplier<Trampoline<T>> nextStep) {
return new Trampoline<>(nextStep);
}
public static <T> Trampoline<T> done(T result) {
return new Trampoline<>(null);
}
}
// Factorial using Trampoline
public static Trampoline<Integer> factorial(int n, int result) {
if (n == 1) {
return Trampoline.done(result);
}
return Trampoline.more(() -> factorial(n - 1, n * result));
}
public static void main(String[] args) {
int n = 5;
int result = factorial(n, 1).result();
System.out.println("Factorial of " + n + " is: " + result);
}
์์ ์ฝ๋์์๋ Trampoline ํจํด์ ์ฌ์ฉํด ํฉํ ๋ฆฌ์ผ ๊ณ์ฐ์ ์ฌ๊ท์ ์ผ๋ก ์ํํ์ง๋ง ์คํ์ ์ฌ์ฉํ์ง ์๋๋ค.
๊ฒฐ๋ก
์๋ฐ์์๋ Tail Recursion Optimization์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ์ง ์์ผ๋ฏ๋ก, ์ฌ๊ท๊ฐ ๊น์ด์ง ์ ์๋ ๊ฒฝ์ฐ ๋ฐ๋ณต๋ฌธ์ผ๋ก ๋ณํํ๊ฑฐ๋, ๋ช ์์ ์คํ ์ฌ์ฉ, ํธ๋จํ๋ฆฐ ํจํด๊ณผ ๊ฐ์ ๋ค๋ฅธ ๋์์ ์ธ ๋ฐฉ๋ฒ๋ค์ ์ฌ์ฉํ ์คํ ์ค๋ฒํ๋ก์ฐ๋ฅผ ๋ฐฉ์งํ ์ ์๋ค. ์ด๋ฌํ ๊ธฐ๋ฒ๋ค์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ์ต์ ํํ๊ณ , ๊น์ ์ฌ๊ท ํธ์ถ์์ ๋ฐ์ํ ์ ์๋ ๋ฌธ์ ๋ค์ ํผํ ์ ์๋๋ก ๋๋๋ค.
'๋น ๊ตฌ๋ฉ ์ฑ์ฐ๊ธฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JVM] Out of Memory VS Memory Leak (0) | 2024.08.28 |
---|---|
[Kotlin][ํ๋ก๊ทธ๋๋ฐ ๊ฐ๋ ] Tail Recursion Optimization (Tail Call Optimization) (2) | 2024.08.28 |
[Java][JVM] StackOverflowError์ ์์ธ๊ณผ ํด๊ฒฐ ๋ฐฉ๋ฒ (0) | 2024.08.27 |
[Java] ์์ธ, ์๋ฌ (0) | 2024.08.27 |
[Java] ์ ๋ค๋ฆญ (1) | 2024.08.27 |