๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Kotlin][ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…] Tail Recursion Optimization (Tail Call Optimization)

์ถœ์ฒ˜

ChatGPT


Tail Recursion Optimization ๋˜๋Š” Tail Call Optimization(TCO)๋Š” ํ•จ์ˆ˜๊ฐ€ tail call๋กœ ๋๋‚˜๋Š” ์žฌ๊ท€ ํ˜ธ์ถœ์„ ์ตœ์ ํ™”ํ•˜์—ฌ ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์„ ์ค„์ด๋Š” ๊ธฐ๋ฒ•์ด๋‹ค. ์ด ์ตœ์ ํ™”๋Š” ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•ด StackOverflowError๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
 

1. Tail Recursion(๊ผฌ๋ฆฌ ์žฌ๊ท€)๋ž€?

Tail Recursion์ด๋ž€, ํ•จ์ˆ˜์˜ ๋งˆ์ง€๋ง‰ ๋™์ž‘์ด ์ž์‹ ์„ ํ˜ธ์ถœํ•˜๋Š” ํ˜•ํƒœ์˜ ์žฌ๊ท€๋ฅผ ๋งํ•œ๋‹ค. ์ฆ‰, ํ•จ์ˆ˜๊ฐ€ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœ๋  ๋•Œ ๊ทธ ๊ฒฐ๊ณผ๊ฐ€ ๊ณง๋ฐ”๋กœ ๋ฐ˜ํ™˜๋˜์–ด ๋” ์ด์ƒ์˜ ๊ณ„์‚ฐ์ด ํ•„์š”์—†๋Š” ๊ฒฝ์šฐ๋ฅผ ๋งํ•œ๋‹ค.
 
์•„๋ž˜ ํ•จ์ˆ˜๋Š” tail recursive์ด๋‹ค.

fun tailRecFactorial(n: Int, accumulator: Int = 1): Int {
    return if (n == 1) accumulator
    else tailRecFactorial(n - 1, n * accumulator)
}

 
์—ฌ๊ธฐ์„œ tailRecFactorial ํ•จ์ˆ˜์˜ ๋งˆ์ง€๋ง‰ ๋™์ž‘์€ tailRecFactorial(n - 1, n * accmulator)์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ˜ธ์ถœ๋œ ํ›„์—๋Š” ์•„๋ฌด๋Ÿฐ ์ถ”๊ฐ€ ์ž‘์—…์ด ์—†๋‹ค. ์ด์™€ ๊ฐ™์€ ํ˜•ํƒœ๋ฅผ tail call์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
 

2. Tail Recursion Optimization์˜ ์›๋ฆฌ

Tail Recursion Optimization์€ tail recursive ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ ์ƒˆ๋กœ์šด ์Šคํƒ ํ”„๋ ˆ์ž„์„ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ํ˜„์žฌ ์Šคํƒ ํ”„๋ ˆ์ž„์„ ์žฌ์‚ฌ์šฉํ•˜๋„๋ก ์ตœ์ ํ™”ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
 
๋ณดํ†ต์˜ ์žฌ๊ท€ ํ˜ธ์ถœ์€ ๊ฐ ํ˜ธ์ถœ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์Šคํƒ ํ”„๋ ˆ์ž„์„ ์ƒ์„ฑํ•ด ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์€ ์žฌ๊ท€ ๊นŠ์ด๊ฐ€ ๊นŠ์–ด์งˆ์ˆ˜๋ก ๋งŽ์€ ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์†Œ๋น„ํ•˜๊ณ , ๊ฒฐ๊ตญ StackOverflowError๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
 
๊ทธ๋Ÿฌ๋‚˜ tail call์˜ ๊ฒฝ์šฐ ํ˜„์žฌ ์Šคํƒ ํ”„๋ ˆ์ž„์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ํ˜ธ์ถœ์ด ์™„๋ฃŒ๋œ ํ›„์— ํ•  ์ผ์ด ๋” ์ด์ƒ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋”ฐ๋ผ์„œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์Šคํƒ์„ ๋ฎ์–ด์“ฐ๊ณ , ์ƒˆ๋กœ์šด ์Šคํƒ ํ”„๋ ˆ์ž„์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์ด ํšจ์œจ์ ์ด๋‹ค.
 

3. Tail Recursion Optimization์˜ ์˜ˆ์ œ

์ผ๋ฐ˜ ์žฌ๊ท€์™€ Tail Recursion์„ ๋น„๊ตํ•ด๋ณด์ž.
 

์ผ๋ฐ˜ ์žฌ๊ท€(Non-Tail Recursion) ์˜ˆ์ œ

fun factorial(n: Int): Int {
    return if (n == 1) 1
    else n * factorial(n - 1)
}

 
์ด ํ•จ์ˆ˜๋Š” factorial(n - 1) ํ˜ธ์ถœ ํ›„์— 'n * ' ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ์žฌ๊ท€๋Š” tail recursive๊ฐ€ ์•„๋‹ˆ๋‹ค.
 
Tail Recursive ์˜ˆ์ œ

fun tailRecFactorial(n: Int, accumulator: Int = 1): Int {
    return if (n == 1) accumulator
    else tailRecFactorial(n - 1, n * accumulator)
}

 
์ด ํ•จ์ˆ˜๋Š” tail recursive์ด๋‹ค. tailRecFactorial(n - 1, n * accumulator)์ด ๋งˆ์ง€๋ง‰์œผ๋กœ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜์ด๋ฉฐ, ๊ทธ ํ›„์— ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค.
 
Tail Recursion Optimization์ด ์ž‘๋™ํ•œ๋‹ค๋ฉด, tailRecFactorial์€ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœ๋˜์ง€๋งŒ ์Šคํƒ ํ”„๋ ˆ์ž„์ด ์ถ”๊ฐ€๋˜์ง€ ์•Š๊ณ  ํ˜„์žฌ ์Šคํƒ ํ”„๋ ˆ์ž„์„ ์žฌ์‚ฌ์šฉํ•œ๋‹ค.
 

4. Kotlin์—์„œ Tail Recursion Optimization ์ ์šฉ

์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” tailrec ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด Tail Recursion Optimization์ด ๊ฐ€๋Šฅํ•จ์„ ๋ช…์‹œ์ ์œผ๋กœ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋‹ค.

tailrec fun tailRecFactorial(n: Int, accumulator: Int = 1): Int {
    return if (n == 1) accumulator
    else tailRecFactorial(n - 1, n * accumulator)
}

 
์—ฌ๊ธฐ์„œ tailrec ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”ํ‹€๋ฆฐ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ด ํ•จ์ˆ˜๊ฐ€ tail call ์ž„์„ ์ธ์‹ํ•˜๊ณ  ์ตœ์ ํ™”๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ํ•จ์ˆ˜๊ฐ€ tail call์ด ์•„๋‹Œ ๊ฒฝ์šฐ, ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.
 
 
โ€ป ์ž๋ฐ”๋Š” Tail Recursion Optimization์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ•˜์ง€๋งŒ ๋Œ€์ฒดํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค์ด ์กด์žฌํ•œ๋‹ค.

 

5. Tail Recursion Optimization์˜ ์žฅ์ 

ํšจ์œจ์ ์ธ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ

Tail Recursion Optimization์„ ํ†ตํ•ด ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” StackOverflowError๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค.

๋” ๋‚˜์€ ์„ฑ๋Šฅ

์ตœ์ ํ™”๋œ ์ฝ”๋“œ๋Š” ๋” ์ ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์Šคํƒ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋น ๋ฅด๊ฒŒ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋‹ค.

๊ฐ€๋…์„ฑ ๋ฐ ์œ ์ง€๋ณด์ˆ˜์„ฑ

์žฌ๊ท€์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ์Šคํƒ ์‚ฌ์šฉ์„ ์ค„์ผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๋ณต์žกํ•œ ๋ฐ˜๋ณต ๊ตฌ์กฐ๋ณด๋‹ค ๊ฐ„๊ฒฐํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ์ฝ”๋“œ ์ž‘์„ฑ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
 

6. ์ œ์•ฝ ์‚ฌํ•ญ ๋ฐ ์ฃผ์˜์ 

  • ๋ชจ๋“  ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ Tail Recursion Optimization์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ž๋ฐ”์˜ ํ‘œ์ค€ JDK๋Š” Tail Recursion Optimization์„ ์ž๋™์œผ๋กœ ์ง€์›ํ•˜์ง€ ์•Š์ง€๋งŒ, Kotlin ์ปดํŒŒ์ผ๋Ÿฌ๋Š” tailrec ํ‚ค์›Œ๋“œ๋กœ ์ด๋ฅผ ์ง€์›ํ•œ๋‹ค.
  • ์žฌ๊ท€ ํ˜ธ์ถœ์ด ๋ฐ˜๋“œ์‹œ ํ•จ์ˆ˜์˜ ๋งˆ์ง€๋ง‰ ๋™์ž‘์ด์–ด์•ผ ํ•˜๋ฉฐ, ๋‹ค๋ฅธ ์—ฐ์‚ฐ์ด ๋’ค๋”ฐ๋ผ์„œ๋Š” ์•ˆ ๋œ๋‹ค.
  • ์žฌ๊ท€ ํ˜ธ์ถœ์ด ํ•„์š”ํ•œ ๋ชจ๋“  ๋ฌธ์ œ์— Tail Recursion Optimization์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํŠน์„ฑ์— ๋”ฐ๋ผ ์ตœ์ ํ™” ๊ฐ€๋Šฅ ์—ฌ๋ถ€๊ฐ€ ๊ฒฐ์ •๋œ๋‹ค.

 

๊ฒฐ๋ก 

Tail Recursion Optimization์€ ์žฌ๊ท€ ํ˜ธ์ถœ์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ณ  ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์„ ์ค„์ด๋Š” ์ค‘์š”ํ•œ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์ด๋‹ค. Kotlin๊ณผ ๊ฐ™์€ ํ˜„๋Œ€์ ์ธ ์–ธ์–ด๋Š” ์ด๋ฅผ ์ง์ ‘์ ์œผ๋กœ ์ง€์›ํ•˜๋ฉฐ, ์ด ๊ธฐ๋ฒ•์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ํšจ์œจ์ ์ธ ์žฌ๊ท€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. tailrec ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋ช…์‹œ์ ์œผ๋กœ ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์ตœ์ ํ™”๋ฅผ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ด ์ข‹์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ์˜ ์•ˆ์ •์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ๋ชจ๋‘ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.