개발/Python

[중급반] Step 2. 일급 함수와 클로저: 함수를 데이터처럼 다루기

ophelisis 2025. 12. 26. 14:27
반응형

Step 2에서는 파이썬이 함수를 어떻게 처리하는지 깊이 있게 다룹니다. 파이썬에서 함수는 단순한 코드 블록이 아니라 **'일급 객체(First-class Object)'**입니다. 이 개념을 이해하면 코드의 재사용성을 극대화하는 **클로저(Closure)**와 **데코레이터(Decorator)**를 자유자재로 다룰 수 있게 됩니다.


1. 🌟 일급 객체(First-class Object)로서의 함수

파이썬의 함수는 숫자나 문자열과 똑같은 대우를 받습니다. 즉, 다음과 같은 작업이 가능합니다.

  • 변수에 할당 가능: 함수를 변수에 담아 나중에 호출할 수 있습니다.
  • 인자로 전달 가능: 다른 함수의 파라미터로 함수를 넘길 수 있습니다. (고차 함수)
  • 결과값으로 반환 가능: 함수 내부에서 또 다른 함수를 만들어 반환할 수 있습니다.
Python
 
def say_hello(name):
    return f"안녕, {name}!"

# 1. 변수에 할당
greet = say_hello
print(greet("파이썬")) # 안녕, 파이썬!

# 2. 인자로 전달 (map 같은 고차 함수)
def formal_greet(func, name):
    return func(name).replace("!", ".")

print(formal_greet(say_hello, "미스터 킴")) # 안녕, 미스터 킴.

2. 🔐 클로저(Closure): 사라진 환경을 기억하는 힘

클로저는 함수가 종료된 후에도 해당 함수가 선언될 당시의 외부 변수(자신을 둘러싼 환경)를 기억하고 있는 특수한 함수를 말합니다.

  • 조건: 중첩 함수여야 하며, 내부 함수가 외부 함수의 변수를 참조해야 하고, 외부 함수가 내부 함수를 반환해야 합니다.
Python
 
def make_multiplier(n):
    # 외부 함수의 변수 n
    def multiplier(x):
        return x * n # 내부 함수가 n을 기억함
    return multiplier

times3 = make_multiplier(3)
times5 = make_multiplier(5)

print(times3(10)) # 30
print(times5(10)) # 50

왜 쓰는가? 전역 변수 사용을 억제하고, 데이터를 숨기면서도 상태를 유지하고 싶을 때(은닉화) 사용합니다.


3. 🎀 데코레이터(Decorator): 코드 위에 씌우는 마법

데코레이터는 클로저의 원리를 이용해 기존 함수를 수정하지 않고 새로운 기능을 추가할 때 사용합니다. @ 심볼을 사용하는 것이 특징입니다.

🛠️ 실전 예시: 실행 시간 측정 데코레이터

Python
 
import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs) # 원래 함수 실행
        end = time.time()
        print(f"[{func.__name__}] 실행 시간: {end - start:.4f}s")
        return result
    return wrapper

@timer
def heavy_job():
    time.sleep(1)
    print("작업 완료!")

heavy_job()
# [heavy_job] 실행 시간: 1.000x s
# 작업 완료!

💡 시니어의 조언: 데코레이터는 '관심사의 분리'

데코레이터의 진가는 **비즈니스 로직(핵심 기능)**과 **부가 기능(로그, 인증, 성능 측정 등)**을 분리하는 데 있습니다. 이를 통해 코드는 훨씬 깔끔해지고 유지보수가 쉬워집니다. 플라스크(Flask)나 장고(Django) 같은 웹 프레임워크에서 라우팅이나 권한 체크를 할 때 데코레이터를 핵심적으로 사용하는 이유이기도 합니다.

반응형