본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] sys.setrecursionlimit 변경 시 발생하는 3가지 치명적 부작용과 해결 방법

by Papa Martino V 2026. 3. 16.
728x90

ys.setrecursionlimit
ys.setrecursionlimit

 

파이썬으로 알고리즘 문제를 풀거나 복잡한 트리 구조를 탐색하다 보면 한 번쯤 RecursionError: maximum recursion depth exceeded라는 에러 메시지를 마주하게 됩니다. 이때 많은 개발자가 임시방편으로 sys.setrecursionlimit() 함수를 사용하여 제한을 늘리는 방법을 선택합니다. 하지만 이 숫자를 무분별하게 키우는 것은 단순히 에러를 회피하는 것을 넘어, 프로그램의 안정성을 근본적으로 흔드는 위험한 행위입니다. 본 아티클에서는 파이썬 인터프리터의 메모리 관리 체계를 바탕으로 리미트 변경 시 발생하는 부작용과 이를 우아하게 극복할 수 있는 해결책을 전문적으로 분석합니다.

1. 파이썬 재귀 제한(Recursion Limit)의 존재 이유

파이썬은 기본적으로 재귀 호출의 깊이를 약 1,000회 정도로 제한하고 있습니다. 이는 파이썬 가상 머신(PVM)이 C 기반의 스택 프레임을 사용하기 때문입니다. 재귀 호출이 발생할 때마다 새로운 프레임 객체가 생성되고 메모리에 쌓이는데, 제한이 없다면 무한 재귀로 인해 운영체제의 스택 영역이 가득 차버리는 스택 오버플로(Stack Overflow)가 발생하여 프로그램이 예고 없이 강제 종료될 수 있습니다.


2. sys.setrecursionlimit 변경 시 발생하는 3가지 핵심 부작용

단순히 에러를 막기 위해 리미트를 5,000이나 10,000으로 늘렸을 때, 내부적으로 발생하는 차이와 위험성을 정리합니다.

표: 재귀 제한 기본 설정 vs 확장 설정 비교 분석

비교 항목 기본 설정 (약 1,000) 확장 설정 (10,000 이상)
안전성 매우 높음 (PVM 차원에서 보호) 낮음 (세그멘테이션 오류 위험)
메모리 점유 예측 가능하고 안정적임 급격한 스택 메모리 팽창 가능성
프로그램 종료 방식 RecursionError 예외 발생 예외 없이 프로세스 강제 종료 (Crash)
OS 의존성 거의 없음 플랫폼 스택 크기에 따라 결과 상이

부작용 1: 세그멘테이션 오류 (Segmentation Fault)

파이썬 엔진이 허용하는 리미트와 실제 OS가 허용하는 스택 크기는 다릅니다. 파이썬 리미트를 크게 늘려두면, 파이썬 예외가 발생하기 전에 OS 수준에서 메모리 침범으로 판단하여 프로그램을 즉시 종료시킵니다. 이는 디버깅을 불가능하게 만드는 가장 큰 부작용입니다.

부작용 2: 가비지 컬렉션(GC)의 부담 증가

수만 개의 프레임 객체가 힙(Heap)과 스택에 동시에 존재하게 되면, 파이썬의 세대별 가비지 컬렉터가 객체 간의 참조 관계를 추적하는 데 더 많은 시간을 소모하게 됩니다. 이는 전체적인 애플리케이션의 응답 속도를 저하시키는 원인이 됩니다.

부작용 3: 스레드 안전성 문제

멀티스레드 환경에서 특정 스레드만 재귀 리미트를 늘리는 것은 불가능합니다. sys.setrecursionlimit은 프로세스 전체에 영향을 미치므로, 다른 스레드에서 의도치 않은 메모리 점유가 발생하여 전체 시스템이 불안정해질 수 있습니다.

3. Sample Example: 리미트 변경과 크래시 현상

아래 예제는 리미트를 무리하게 늘렸을 때 파이썬 예외 처리 없이 프로그램이 죽는 현상을 모사합니다.


import sys

# 1. 재귀 한계 확인
print(f"현재 재귀 리미트: {sys.getrecursionlimit()}")

# 2. 리미트를 극단적으로 상향 (위험한 시도)
sys.setrecursionlimit(1000000)

def dangerous_recursion(n):
    # 아무런 종료 조건이 없는 무한 재귀
    return dangerous_recursion(n + 1)

try:
    dangerous_recursion(1)
except RecursionError:
    print("안전하게 파이썬 예외로 처리됨")
except Exception as e:
    print(f"기타 에러: {e}")

# 결과: 대부분의 환경에서 RecursionError 출력 전 
# 'Segmentation fault'와 함께 프로세스가 강제 종료됩니다.

4. 근본적인 성능 개선 및 해결 방법 3가지

리미트를 늘리는 대신 전문가들이 권장하는 해결책은 다음과 같습니다.

  • 반복문(Iteration)으로 전환: 모든 재귀 함수는 스택(Stack) 자료구조를 활용한 while 문으로 변환 가능합니다. 이는 프레임 생성 비용을 없애 성능을 극대화합니다.
  • 메모이제이션(Memoization): 이미 계산된 결과를 캐싱하여 중복 재귀 호출을 줄이면, 호출 깊이 자체를 획기적으로 낮출 수 있습니다.
  • 꼬리 재귀 최적화 모방: 파이썬은 언어 차원의 TCO를 지원하지 않지만, 제너레이터를 활용한 '트램펄린(Trampoline)' 기법을 사용하면 스택 소모 없이 무한 재귀를 구현할 수 있습니다.

5. 결론: 안전한 코딩을 위한 가이드라인

sys.setrecursionlimit은 도구 상자의 마지막 수단이어야 합니다. 알고리즘의 깊이가 기본 제한을 살짝 상회하는 수준(예: 2,000 내외)이라면 조정이 유효할 수 있지만, 5,000을 넘어서는 구조라면 로직 자체를 검토해야 합니다. 메모리 효율성과 안정성을 동시에 잡는 가장 좋은 방법은 데이터의 규모에 상관없이 일정한 성능을 보장하는 반복적(Iterative) 설계를 지향하는 것입니다.

콘텐츠 참조 및 기술 자료

  • Python Runtime Services.
  • Stack Overflow: "Why is the Python recursion limit so low?"
  • CPython Internals: Frame Objects and Stack management.
728x90