🔥Topgrade Fundemax 평생수강패키지 최대 60% · 단과 프리패스 최대 90% 할인할인 보러가기 →
TOPGRADE
...
인기 검색어
아직 집계된 인기 검색어가 없습니다.
추천 검색어
등록된 추천 검색어가 없습니다.
최근 검색어
최근 검색 내역이 없습니다.
TOPGRADE
수학공학자연과학의약학경영경제컴퓨터사이언스어학ㆍ자격
...

카테고리

카테고리 로딩 중...

재귀 함수, 값은 도대체 언제 계산될까?

C 프로그래밍2026년 8월 24일

코드는 짧은데 머릿속이 복잡한 이유

int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}

네 줄입니다. 그런데 factorial(4) 를 눈으로 따라가려 하면 어디까지 계산됐는지 금방 헷갈립니다.

이유가 있습니다. 우리는 코드를 위에서 아래로 읽는데, 재귀는 내려갔다가 다시 올라오기 때문입니다.

한 줄 정의

재귀 함수는 자기 자신을 호출하는 함수이고, 그 호출들은 호출 스택(call stack) 에 차곡차곡 쌓입니다.

핵심은 이겁니다 — 쌓는 동안에는 아무 값도 정해지지 않습니다.

스택이 쌓였다 풀리는 30초

실제로 어떻게 진행되는가

factorial(4) 를 부르면 이렇게 됩니다.

단계스택 상태확정된 값
1f(4)없음 — 4 × f(3) 을 기다림
2f(4) f(3)없음
3f(4) f(3) f(2)없음
4f(4) f(3) f(2) f(1)1 ← 기저 조건
5f(4) f(3) f(2)2 × 1 = 2
6f(4) f(3)3 × 2 = 6
7f(4)4 × 6 = 24

1번부터 3번까지, 세 번을 호출하는 동안 계산된 값은 하나도 없습니다. return n * factorial(n-1) 에서 곱셈을 하려면 오른쪽 값이 필요한데, 그게 아직 없으니 곱셈이 미뤄집니다.

값이 처음 생기는 건 4번 — 기저 조건에 닿았을 때입니다. 그때부터 되돌아오며 하나씩 확정됩니다.

스택 프레임에는 무엇이 들어 있나

호출 하나마다 스택 프레임이 만들어지고, 그 안에 매개변수 n, 지역 변수, 그리고 돌아갈 주소(return address)가 들어갑니다. f(3)nf(2)n 은 이름만 같고 서로 다른 메모리입니다. 그래서 각 단계가 자기 n 을 기억할 수 있습니다.

기저 조건을 빠뜨리면

int bad(int n) {
    return n * bad(n - 1);   // 멈추는 조건이 없다
}

이 함수는 영원히 내려갑니다. 프레임이 계속 쌓이고, 스택에 할당된 메모리를 다 쓰면 스택 오버플로(stack overflow) 로 프로그램이 죽습니다.

무한 루프와는 증상이 다릅니다. 무한 루프는 메모리를 안 먹고 계속 돌지만, 무한 재귀는 메모리를 먹다가 터집니다.

기저 조건은 '있는 것'만으로 부족합니다

if (n == 1) return 1; 로 써두고 bad(0) 이나 bad(-3) 을 부르면 조건에 영영 걸리지 않습니다. 기저 조건은 모든 도달 가능한 입력이 반드시 만나도록 써야 합니다. n <= 1 처럼 범위로 잡는 게 안전한 이유입니다.

재귀 vs 반복

같은 계산을 반복문으로도 쓸 수 있습니다.

int factorial_loop(int n) {
    int r = 1;
    for (int i = 2; i <= n; i++) r *= i;
    return r;
}

이쪽은 곱셈이 즉시 일어납니다. r 에 값이 계속 갱신되니 어느 시점에 봐도 중간 결과가 있습니다. 스택도 한 프레임만 씁니다.

재귀반복
값이 확정되는 시점되돌아올 때매 회차 즉시
메모리호출 깊이만큼 프레임일정
잘 맞는 문제트리·분할정복·백트래킹단순 누적

재귀가 항상 낫다는 뜻이 아닙니다. 구조 자체가 재귀적인 문제(트리 순회, 하노이탑, 병합 정렬)에서는 재귀가 코드를 훨씬 짧고 정확하게 만들지만, 팩토리얼 같은 단순 누적은 반복이 낫습니다.

정리

  • 재귀는 호출할 때 값을 만들지 않습니다. 기저 조건에 닿아야 되돌아오며 확정됩니다
  • 호출마다 스택 프레임이 생기고, 거기에 매개변수·지역변수·돌아갈 주소가 들어갑니다
  • 기저 조건은 모든 입력이 반드시 만나도록 범위로 잡아야 합니다
  • 무한 재귀는 무한 루프와 달리 메모리를 소모하다 터집니다
  • 구조가 재귀적인 문제에 쓰고, 단순 누적은 반복문이 낫습니다

코드가 헷갈렸던 건 어려워서가 아니라, 내려가는 동안 아무 일도 안 일어난다는 걸 몰랐기 때문입니다.

#재귀함수#호출스택#스택프레임#기저조건#스택오버플로#C프로그래밍