OPEN HYPER STEP
← 목록으로 (math)
MATH · 20 / 45
math
CHAPTER 20 / 45
읽기 약 2
FUNCTION

재귀와 팩토리얼: n! = n × (n-1)!


핵심 개념

재귀 함수의 수학적 기반 — 팩토리얼·기저 조건·스택 오버플로의 원인·꼬리 재귀 최적화.

본문

재귀 = 자기 호출

📋 코드 (5줄)
수학 정의: n! = n × (n-1)!
기저: 0! = 1, 1! = 1

재귀 = "큰 문제 → 동일 구조의 작은 문제로 분할"
        + "기저 조건"

Python 재귀 — 팩토리얼

PYTHON📋 코드 (36줄)
def factorial(n):
    # 기저 조건 — 반드시 필요
    if n <= 1:
        return 1
    # 재귀 호출
    return n * factorial(n - 1)


print(factorial(5))   # 120
print(factorial(10))  # 3628800
print(factorial(20))  # 2432902008176640000


# 호출 스택 시각화
def factorial_traced(n, depth=0):
    indent = '  ' * depth
    print(f"{indent}factorial({n}) 호출")
    if n <= 1:
        print(f"{indent}→ 1 반환 (기저)")
        return 1
    result = n * factorial_traced(n - 1, depth + 1)
    print(f"{indent}→ {result} 반환")
    return result


factorial_traced(5)
# factorial(5) 호출
#   factorial(4) 호출
#     factorial(3) 호출
#       factorial(2) 호출
#         factorial(1) 호출
#         → 1 반환 (기저)
#       → 2 반환
#     → 6 반환
#   → 24 반환
# → 120 반환

기저 조건 누락 → 무한 재귀

PYTHON📋 코드 (17줄)
# ❌ 기저 조건 없음
def bad_factorial(n):
    return n * bad_factorial(n - 1)
    # n=5 → 4 → 3 → ... → -1 → -2 → ...
    # 영원히 멈추지 않음

# 결과: RecursionError: maximum recursion depth exceeded
# Python 기본 한도: 약 1000 깊이


# ✅ 기저 조건 + 진행 보장
def good_factorial(n):
    if n < 0:
        raise ValueError("음수 불가")  # 입력 검증
    if n <= 1:
        return 1
    return n * good_factorial(n - 1)

스택 오버플로 — 재귀 깊이 한도

PYTHON📋 코드 (29줄)
import sys

print(sys.getrecursionlimit())  # 1000 (기본값)


# 깊은 재귀 시도
def deep(n):
    if n == 0:
        return 0
    return 1 + deep(n - 1)


# print(deep(2000))  # RecursionError

# 한도 늘리기 (위험 — 메모리 폭주 가능)
sys.setrecursionlimit(10000)
print(deep(5000))  # 5000


# 안전한 대안 — 반복문으로 변환
def deep_iter(n):
    result = 0
    while n > 0:
        result += 1
        n -= 1
    return result


print(deep_iter(1_000_000))  # 1000000 (재귀 한도 무관)

꼬리 재귀 — 일부 언어에서 최적화

PYTHON📋 코드 (33줄)
# 꼬리 재귀: 마지막 동작이 자기 호출 (다른 연산 X)
def factorial_tail(n, acc=1):
    if n <= 1:
        return acc
    return factorial_tail(n - 1, n * acc)  # 마지막이 함수 호출


print(factorial_tail(10))  # 3628800

# Python·JavaScript는 꼬리 재귀 최적화 안 함 — 여전히 스택 사용
# Scheme·Haskell·Erlang은 꼬리 재귀를 반복문으로 자동 변환

# Python에서 꼬리 재귀를 안전하게 — 데코레이터 트릭
import functools

def trampoline(f):
    @functools.wraps(f)
    def wrapper(*args):
        result = f(*args)
        while callable(result):
            result = result()
        return result
    return wrapper


@trampoline
def factorial_safe(n, acc=1):
    if n <= 1:
        return acc
    return lambda: factorial_safe(n - 1, n * acc)


print(factorial_safe(2000))  # 큰 수도 OK (Python 임의 정밀도)

재귀로 표현되는 다른 문제들

PYTHON📋 코드 (45줄)
# 1. 거듭제곱 a^n
def power(a, n):
    if n == 0:
        return 1
    if n == 1:
        return a
    return a * power(a, n - 1)


# 더 빠른 — O(log n) 분할 정복
def power_fast(a, n):
    if n == 0:
        return 1
    if n % 2 == 0:
        half = power_fast(a, n // 2)
        return half * half
    return a * power_fast(a, n - 1)


print(power_fast(2, 20))  # 1048576


# 2. 최대공약수 (유클리드 호제법)
def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a % b)


print(gcd(48, 36))  # 12
print(gcd(101, 17)) # 1


# 3. 하노이의 탑
def hanoi(n, src, dst, via):
    if n == 1:
        print(f"{src} → {dst}")
        return
    hanoi(n - 1, src, via, dst)
    print(f"{src} → {dst}")
    hanoi(n - 1, via, dst, src)


hanoi(3, 'A', 'C', 'B')
# A → C / A → B / C → B / A → C / B → A / B → C / A → C

다음 챕터

CH.21 "그래프 이론 기초" — 노드와 간선, 인접 행렬·인접 리스트.


AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 재귀 함수를 분석해서 기저 조건 정합성과
스택 오버플로 가능성, 반복문 변환
방법을 알려줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

한국 코딩 테스트 재귀 문제 Top 10과
각각의 풀이 패턴 + 함정을 정리해줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 알고리즘 코드의 모든 재귀 호출을
분석해서 메모이제이션 적용 가능 위치와
예상 성능 향상을 보고해줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 함수형 언어(Haskell/Erlang)의
꼬리 재귀 최적화 vs 명령형 언어 차이를
실무 영향 관점에서 솔직히 알려줘.

⭐ 이것만 기억하세요
재귀와 팩토리얼: n! = n × (n-1)! 이 3가지만 확실히 잡으세요
1.재귀는 "큰 문제 → 작은 문제 + 기저" 패턴 — 기저 조건이 가장 중요
2.재귀 깊이는 콜 스택 한도와 직결 — Python 기본 1000, 깊은 재귀는 반복문 또는 trampoline
3.다음 챕터 CH.21에서 그래프 이론 — 재귀 + 데이터 구조의 결합


공유하기
진행도 20 / 45