ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] 고차함수(Higher-Order Function) 란?
    IT 2026. 1. 21. 14:41

    고차함수(Higher-Order Function)는 함수형 프로그래밍의 핵심 개념이자, 파이썬을 더 파이썬답게 작성하기 위해 반드시 이해해야하는 개념입니다. 파이썬 공식 문서, 다양한 개발 블로그, 그리고 클린 코드 관련 자료에서도 고차함수는 반복해서 등장합니다.

     

    이 글에서 고차함수의 개념을 아주 기초부터, 왜 필요한지, 그리고 파이썬 예제를 중심으로 충분히 길고 자세하게 설명해보겠습니다.

    단순히 문법 설명이 아니라, 사고 방식 자체를 이해하는 것이 목표입니다.

     

    1. 고차 함수란 무엇인가?

    📌 정의

    고차함수란 다음 조건 중 하나 이상을 만족하는 함수입니다.

     

    1. 함수를 인자(argument)로 받는다

    2. 함수를 반환(return) 한다

     

    이 정의에서 가장 중요한 문장은 바로 "함수는 값이다"라는 개념입니다.

    파이썬에서는 함수가 다음과 같은 특징을 가집니다.

    • 변수에 할당할 수 있음
    • 리스트나 딕셔너리에 저장 가능
    • 다른 함수의 인자로 전달 가능
    • 함수의 반환값으로 사용 가능

    즉, 함수는 정수나 문자열과 동등한 지위를 가진 객체입니다.

    def greet():
        return "Hello"
    
    
    print(greet) # <function greet at 0x...>
    print(greet()) # Hello

    이러한 특성 덕분에 고차함수가 가능해집니다.

     

    2. 함수를 인자로 받는 고차함수

     가장 단순한 예제

    def say_something(func):
        print(func())
    
    
    def hello():
        return "안녕하세요"
    
    
    def bye():
        return "안녕히 가세요"
    
    
    say_something(hello)
    say_something(bye)
    • say_something은 함수를 인자로 받음
    • 어떤 함수가 오느냐에 따라 동작이 달라짐
    • 행동을 외부에서 주입 받는 구조

    이 패턴은 고차함수의 본질을 가장 잘 보여줍니다.

     

    3. 왜 고차함수가 필요한가?

    많은 개발 블로그에서 공통적으로 말하는 이유는 다음과 같습니다.

     중복 제거 (DRY 원칙)

    ❌ 고차함수 사용 전

    def print_double_1():
        print("Hello")
        print("Hello")
    
    
    def print_double_2():
        print("Bye")
        print("Bye")

    출력 내용만 다르고 구조는 완전히 동일합니다.

     

    ✅ 고차함수 사용 후

    def repeat(action):
        action()
        action()
    
    
    repeat(lambda: print("Hello"))
    repeat(lambda: print("Bye"))
    • 반복되는 구조를 함수로 추상화
    • 변경되는 행동만 함수로 전달

     추상화 수준 상승 (어떻게 -> 무엇)

    umbers = [1, 2, 3, 4, 5]
    
    
    evens = []
    for n in numbers:
    	if n % 2 == 0:
    		evens.append(n * 2)

    위 코드는 틀리지 않았지만, 의도가 한눈에 보이지 않습니다.

    evens = list(map(lambda x: x * 2, filter(lambda x: x % 2 == 0, numbers)))

    이 코드는 다음을 명확하게 표현합니다.

    • 필터링한다
    • 변환한다

    즉, "무엇을 하는 코드인지"가 바로 드러납니다.

     

    4. 파이썬의 대표적인 고차함수

    🔹 map

    numbers = [1, 2, 3, 4]
    
    
    def square(x):
        return x * x
    
    
    result = list(map(square, numbers))
    # [1, 4, 9, 16]
    • 각 요소에 함수를 적용
    • 새로운 iterable 반환

    🔹 filter

    numbers = [1, 2, 3, 4, 5, 6]
    
    
    def is_even(x):
        return x % 2 == 0
    
    
    result = list(filter(is_even, numbers))
    # [2, 4, 6]

    🔹 reduce

    from functools import reduce
    
    
    numbers = [1, 2, 3, 4]
    
    
    sum_value = reduce(lambda acc, cur: acc + cur, numbers, 0)
    # 10
    • 누적 계산을 수행
    • 상태를 외부로 노출하지 않음

     

    5. 함수를 반환하는 고차함수 (클로저)

    def multiply_by(multiplier):
        def inner(value):
            return value * multiplier
        return inner
    
    
    double = multiply_by(2)
    triple = multiply_by(3)
    
    
    print(double(5)) # 10
    print(triple(5)) # 15

    이 코드의 핵심

    • multiply_by 는 함수를 반환 -> 고차함수
    • inner 함수는 multiplier 를 기억함
    • 이 현상은 클로저(Closure) 라고 부름

    이 패턴은 설정 값에 따라 동작이 달라지는 함수를 만들 때 매우 유용합니다.

     

    6. 실전 예제: 공통 로직 추출

    ❌ 고차함수 미사용

    def log_user():
    	print("[USER] action")
    
    def log_admin():
    	print("[ADMIN] action")

    ✅ 고차함수 사용

    def with_log(role):
        def logger():
       		print(f"[{role}] action")
        return logger
    
    log_user = with_log("USER")
    log_admin = with_log("ADMIN")
    • 역할(role)만 바꿔서 재사용 가능
    • 유지보수 및 확장성 증가

    7. 고차함수를 잘 쓰기 위한 팁

    • 함수 하나는 하나의 책임만 가지게 하기
    • 이름은 행동을 드러내게 짓기
    • lambda는 짧게, 길어지면 def 사용
    • 과도한 중첩은 피하기

     

    6. 실전 예제: 공통 로직 추출

    고차함수는 처음에는 어렵지만, 익숙해질수록 다음과 같은 장점이 있습니다.

    • 코드가 짧아진다
    • 의도가 명확해진다
    • 테스트가 쉬워진다
    • 확장에 강해진다

    파이썬을 "그냥 돌아가는 코드"가 아니라 잘 설계된 코드로 작성하고 싶다면, 반드시 넘어야 할 관문입니다.

     

    다음에는 클로저(Closure), 커링(Currying) 등도 다뤄보겠습니다.

     

     

Designed by Tistory.