IMCAT.DEV
로그인 가입
Go 중급 함수형

Go 함수형 프로그래밍 패턴 (Functional Programming Patterns)

Go 함수형 프로그래밍 패턴 (Functional Programming Patterns) — 중급

함수형 프로그래밍 패턴 (Functional Programming Patterns)

1. 도입 (왜 배워야 하는가)

함수형 프로그래밍 패턴은 소프트웨어 개발에서 코드의 재사용성과 가독성을 높이는 데 중요한 역할을 합니다. 현대의 많은 프로그래밍 언어가 함수형 프로그래밍을 지원하고 있으며, Go 언어 역시 예외가 아닙니다. 이러한 패턴을 활용하면 코드의 복잡성을 줄이고, 유지보수가 용이한 코드를 작성할 수 있습니다.

함수형 프로그래밍을 모른다면, 코드의 중복이 발생하거나, 상태 변화로 인한 버그가 생길 가능성이 높아집니다. 이는 팀원 간의 협업을 어렵게 하고, 장기적으로 프로젝트의 품질을 저하시킬 수 있습니다. 따라서, 함수형 프로그래밍 패턴을 이해하고 활용하는 것은 개발자에게 필수적인 역량입니다.

2. 핵심 개념 설명

함수형 프로그래밍의 핵심 개념은 아래와 같습니다.

개념설명
일급 함수함수를 변수처럼 다룰 수 있는 특성
고차 함수함수를 인자로 받거나 반환하는 함수
클로저함수와 그 함수가 선언된 환경을 함께 저장
불변성데이터가 변경되지 않도록 하는 원칙

비유

일급 함수는 마치 레스토랑의 메뉴판과 같습니다. 메뉴판(함수)에 있는 음식을 손님(변수)이 선택하여 주문(실행)할 수 있습니다. 고차 함수는 레스토랑의 셰프와 같아서, 손님이 특정 음식을 요청하면 그에 맞춰 요리를 제공할 수 있습니다. 클로저는 요리사가 특정 레시피를 기억하고 있어, 나중에 똑같은 요리를 쉽게 만들 수 있도록 도와주는 역할을 합니다. 불변성은 요리가 완료된 후, 그 요리를 다시 만들지 않고 다른 요리를 만드는 것과 같습니다.

3. 기본 코드 예제

일급 함수와 고차 함수를 사용한 간단한 예제를 살펴보겠습니다.

package main

import "fmt"

// 함수 타입 정의
type Operation func(int, int) int

// 고차 함수
func calculate(a int, b int, op Operation) int {
    return op(a, b)
}

// 더하기 함수
func add(x int, y int) int {
    return x + y
}

func main() {
    result := calculate(5, 3, add) // 고차 함수 호출
    fmt.Println(result) // 8
}

실행 결과

8

코드 설명

  1. Operation이라는 함수 타입을 정의합니다. 이는 두 개의 정수를 받아 정수를 반환하는 함수의 타입입니다.
  2. calculate라는 고차 함수를 정의합니다. 이 함수는 두 개의 정수와 Operation 타입의 함수를 인자로 받아, 그 함수를 실행하여 결과를 반환합니다.
  3. add라는 더하기 함수를 정의합니다. 이 함수는 두 개의 정수를 받아 더한 결과를 반환합니다.
  4. main 함수에서 calculate 함수를 호출하고, add 함수를 인자로 전달하여 실행합니다. 결과는 8입니다.
  5. 4. 실전 활용 예제

    예제 1: 쇼핑몰 장바구니 구현

    쇼핑몰에서 장바구니에 상품을 추가하고, 총 금액을 계산하는 예제를 살펴보겠습니다.

    package main
    
    import "fmt"
    
    type Product struct {
        Name  string
        Price float64
    }
    
    type Cart []Product
    
    // 고차 함수: Cart의 가격 합산
    func (c Cart) totalPrice(op func(float64, float64) float64) float64 {
        total := 0.0
        for _, product := range c {
            total = op(total, product.Price)
        }
        return total
    }
    
    // 더하기 함수
    func add(x, y float64) float64 {
        return x + y
    }
    
    func main() {
        cart := Cart{
            {Name: "Laptop", Price: 1200.00},
            {Name: "Mouse", Price: 25.00},
        }
        total := cart.totalPrice(add) // 가격 합산
        fmt.Printf("Total Price: %.2f\n", total) // Total Price: 1225.00
    }

    실행 결과

    Total Price: 1225.00

    설명

  6. Product 구조체와 Cart 타입을 정의합니다.
  7. totalPrice 메서드는 장바구니에 있는 모든 상품의 가격을 합산하는 고차 함수입니다.
  8. add 함수를 이용해 상품 가격을 합산합니다. 최종적으로 장바구니의 총 가격을 출력합니다.
  9. 5. 흔한 실수와 주의사항

    실수 1: 함수 타입을 잘못 정의하기

    // 잘못된 코드
    type Operation func(int) // 인자의 개수가 맞지 않음

    올바른 코드

    type Operation func(int, int) int // 올바른 인자의 개수

    실수 2: 클로저 사용 시 환경 변수의 변화

    func makeCounter() func() int {
        count := 0
        return func() int {
            count++ // 외부 변수 변경
            return count
        }
    }
    
    func main() {
        counter := makeCounter()
        fmt.Println(counter()) // 1
        fmt.Println(counter()) // 2
    }

    6. 정리

    • 함수형 프로그래밍 패턴은 코드를 명확하고 간결하게 만들어줍니다.
    • 일급 함수와 고차 함수를 통해 함수의 재사용성을 극대화할 수 있습니다.
    • 클로저를 활용하면 상태를 유지하면서도 함수형 프로그래밍의 이점을 누릴 수 있습니다.
    • 불변성을 지키는 것이 코드의 안정성을 높이는 데 기여합니다.

다음에는 Go에서 고급 함수형 프로그래밍이나 에러 처리 패턴을 학습하는 것을 추천드립니다.