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

[PYTHON] 함수 기본 값(Default Parameter) 설정 시 치명적인 실수와 해결 방안

by Papa Martino V 2026. 2. 13.
728x90

Default Parameter
Default Parameter

파이썬의 유연함 속에 숨겨진 '가변 객체(Mutable Objects)'의 비밀과 안전한 코드 설계 전략


1. 서론: 왜 파이썬의 기본값은 때때로 예상과 다르게 동작하는가?

파이썬을 사용하면서 함수를 정의할 때 인자에 기본값을 설정하는 기능은 매우 편리합니다. def func(a, b=10):와 같은 방식은 코드의 재사용성을 높이고 호출 시 번거로움을 줄여줍니다. 하지만 파이썬의 중급자로 넘어가는 과정에서 반드시 마주하게 되는 기이한 현상이 있습니다. 바로 "함수를 여러 번 호출했는데, 이전 호출의 결과가 다음 호출에 영향을 미치는 현상"입니다.

이는 단순한 버그가 아니라 파이썬의 함수 정의 시점(Definition Time)객체 참조 방식 때문에 발생하는 고유한 특징입니다. 본 포스팅에서는 이 치명적인 함정을 심층 분석하고, 실무에서 안전하게 사용할 수 있는 표준 패턴을 제시합니다.

2. 가장 많이 하는 실수: 가변 객체(Mutable)를 기본값으로 사용

가장 전형적인 문제는 리스트(list)나 딕셔너리(dict) 같은 가변 객체를 함수의 기본 인자로 사용할 때 발생합니다. 파이썬에서 함수의 기본값은 함수가 정의되는 시점에 딱 한 번만 평가되어 함수 객체의 속성에 저장됩니다.

문제의 코드 샘플 (Anti-Pattern)

def add_employee(name, employee_list=[]):
    employee_list.append(name)
    return employee_list

# 첫 번째 호출
print(add_employee("Alice"))  # 결과: ['Alice']

# 두 번째 호출
print(add_employee("Bob"))    # 결과: ['Alice', 'Bob'] (기대값: ['Bob'])

위 코드에서 employee_list는 함수 호출 시마다 새로 생성되는 것이 아니라, 함수가 로드될 때 생성된 동일한 리스트 객체를 계속 공유하게 됩니다. 이것이 바로 '기본값 함정'의 실체입니다.

3. 심층 비교: 가변 객체 vs 불변 객체

왜 숫자나 문자열을 기본값으로 쓸 때는 문제가 없었을까요? 아래 표를 통해 객체 타입에 따른 동작 차이를 비교해 보겠습니다.

특징 불변 객체 (Immutable) 가변 객체 (Mutable)
해당 타입 int, float, str, tuple, None list, dict, set
평가 시점 함수 정의 시점 함수 정의 시점
수정 시 동작 새로운 객체 생성 (기존값 유지) 기존 객체 내부 수정 (상태 공유)
예상치 못한 부작용 없음 매우 높음 (데이터 오염 위험)
권장 사용 여부 적극 권장 절대 금지 (Sentinel 방식 권장)

4. 해결 방안: None과 조건문을 활용한 Sentinel 패턴

파이썬 커뮤니티에서 권장하는 가장 안전하고 표준적인 해결책은 기본값을 None으로 설정하고, 함수 내부에서 객체를 생성하는 것입니다.

[Sample Example] 안전한 기본값 설정 패턴

def add_employee_safe(name, employee_list=None):
    """
    가변 객체를 기본값으로 사용하지 않고
    None을 활용하여 매 호출마다 새로운 리스트를 보장함.
    """
    if employee_list is None:
        employee_list = []  # 호출 시점에 새로운 리스트 생성
    
    employee_list.append(name)
    return employee_list

# 실행 테스트
print(add_employee_safe("Alice")) # ['Alice']
print(add_employee_safe("Bob"))   # ['Bob'] (독립적인 리스트)

이 패턴을 사용하면 함수가 호출될 때마다 employee_listNone인지 확인하고, 필요한 경우에만 새로운 리스트 객체를 할당하므로 부작용을 완벽하게 차단할 수 있습니다.

5. 추가 주의사항: 인자 순서의 규칙

기본값 설정 시 문법적으로도 주의해야 할 점이 있습니다. 파이썬에서는 기본값이 없는 인자가 기본값이 있는 인자보다 앞에 와야 합니다.

  • def func(a, b=10): (O) - 올바른 형식
  • def func(a=10, b): (X) - SyntaxError 발생

이는 호출 시 인자의 위치를 명확하게 구분하기 위한 언어 차원의 설계입니다.

6. 결론 및 요약

파이썬의 기본 인자 값은 강력한 도구이지만, 내부 작동 원리를 이해하지 못하면 찾기 어려운 논리적 오류를 발생시킵니다. "가변 객체는 절대로 기본값 자리에 직접 할당하지 않는다"는 원칙만 지켜도 코드의 안정성은 크게 향상됩니다.

핵심 요약: 1. 기본값은 정의 시점에 한 번만 생성된다. 2. 리스트, 딕셔너리를 직접 기본값으로 쓰면 데이터가 누적된다. 3. None을 기본값으로 쓰고 함수 내부에서 if variable is None: 처리를 하라.

7. 내용 출처

본 포스팅은 아래의 공신력 있는 자료들을 바탕으로 작성되었습니다.

  • Python Software Foundation - "The Python Tutorial: Default Argument Values"
  • Python Enhancement Proposals (PEP 8) - Style Guide for Python Code
  • Effective Python (2nd Edition) by Brett Slatkin - Item 24: Use None and Docstrings to Specify Dynamic Default Arguments
728x90