재귀(Recursion)란 무엇인가?
함수가 스스로를 다시 호출하는 프로그래밍 기법을 재귀(recursion)라고 합니다. 자바스크립트 역시 다른 프로그래밍 언어와 마찬가지로 재귀를 지원하며, 반복문을 사용하지 않고도 복잡한 문제를 간결하게 해결할 수 있게 해줍니다.
재귀 함수가 올바르게 작동하려면 반드시 두 가지 요소가 필요합니다.
- 종료 조건(Base Case): 재귀 호출을 멈추는 조건으로, 이 조건이 없으면 함수는 무한히 자신을 호출하다가 스택 오버플로우(stack overflow) 오류가 발생합니다.
- 재귀 단계(Recursive Step): 함수가 자기 자신을 더 작은 입력값과 함께 호출하는 부분으로, 매번 종료 조건에 가까워져야 합니다.
예제: 재귀로 구현한 팩토리얼 계산
재귀의 대표적인 활용 사례는 팩토리얼(factorial) 계산입니다. n! = n × (n-1) × (n-2) × ... × 1이며, 아래 예제는 displayFact라는 함수가 자기 자신을 호출하여 5의 팩토리얼을 구하는 코드입니다.
코드 예시
<html>
<body>
<script>
function displayFact(value) {
if (value < 0) {
return -1; // 음수는 처리하지 않음
}
// 0의 팩토리얼은 1 (종료 조건)
else if (value == 0) {
return 1;
} else {
// 자기 자신을 호출하는 재귀 단계
return (value * displayFact(value - 1));
}
}
var res = displayFact(5);
document.write("5 factorial = " + res);
</script>
</body>
</html>
실행 결과
5 factorial = 120
재귀 함수의 동작 원리 단계별 살펴보기
displayFact(5)가 호출되면 다음과 같은 과정으로 값이 계산됩니다.
displayFact(5)→5 * displayFact(4)displayFact(4)→4 * displayFact(3)displayFact(3)→3 * displayFact(2)displayFact(2)→2 * displayFact(1)displayFact(1)→1 * displayFact(0)displayFact(0)→ 종료 조건에 도달하여1반환
이후 결과가 거꾸로 거슬러 올라가면서 곱해집니다. 즉, 1 × 1 = 1, 2 × 1 = 2, 3 × 2 = 6, 4 × 6 = 24, 5 × 24 = 120이 최종 결과로 반환됩니다.
재귀 사용 시 주의할 점
- 종료 조건을 반드시 정의하세요. 종료 조건이 없거나 잘못되면 무한 재귀로 인해 브라우저가 멈추거나 Maximum call stack size exceeded 오류가 발생합니다.
- 매 호출마다 입력값이 감소해야 합니다. 위 예제처럼 value - 1을 전달해야 종료 조건에 도달할 수 있습니다.
- 깊은 재귀는 성능에 영향을 줄 수 있습니다. 자바스크립트는 콜 스택(call stack)을 사용하기 때문에 호출 깊이가 너무 깊어지면 스택 오버플로우가 발생할 수 있습니다.
마무리
재귀는 트리 순회, 분할 정복 알고리즘, 중첩된 데이터 구조 처리 등에 특히 유용한 강력한 기법입니다. 종료 조건과 재귀 단계만 명확히 설계하면, 반복문보다 더 직관적이고 읽기 쉬운 코드를 작성할 수 있습니다.