프로그래밍 패러다임은 소프트웨어 개발에서 사용하는 기본적인 스타일이나 접근 방식을 뜻합니다. 문제를 해결하는 방법과 프로그램의 구조를 결정짓는 중요한 원칙과 개념있고 다양한 프로그래밍 패러다임이 존재하며, 각 패러다임은 특정 유형의 문제 해결에 더 적합한 도구와 방법론을 선택할 수 있습니다.
프로그래밍 패러다임은 크게 두 가지로 나눌 수 있습니다:
명령형 패러다임 (Imperative Paradigm):
선언형 패러다임 (Declarative Paradigm):
각 패러다임은 개발자가 코드의 구조를 조직하고 문제를 해결하는 데 도움을 주며, 특정 도메인이나 문제 유형에 따라 가장 적합한 패러다임을 선택하는 것이 중요합니다.
프로그래밍에는 여러 패러다임이 있다. 🧩
저에겐 Java의 객체지향, SQL의 선언형, C의 절차적 프로그래밍이 익숙하네요. 이러한 여러 패러다임 중에 "함수형 프로그래밍 (Functional Programming)"에 대해 알아보겠습니다.🌟

함수형 프로그래밍은 수학적 함수의 개념을 기반으로 하여 프로그래밍 상태 변화와 부작용을 최소화한다는 것에 의의가 있습니다. 함수형 프로그래밍은 다음과 같은 특성이 있습니다.
순수 함수란 동일한 입력에 대해서 항상 동일한 출력을 반환하는 함수입니다. 그렇기 때문에 코드의 동작이 예측 가능해지고 이를 통해 디버깅과 테스트를 쉽게 만들 수 있습니다.
불변성은 데이터가 변하지 않는다는 의미입니다. 데이터가 변하지 않음으로 여러 많은 부작용들을 방지할 수 있고 js같은 멀티 스레드 환경에서 thread safety 즉, race condition을 방지하고 deadlock을 회피 할 수 있으며 원자성을 보장할 수 있다는 이점이 있습니다.
고차 함수는 함수를 인자로 받거나 반환하는 함수입니다. 함수형 프로그래밍에서는 함수는 항상 1급 객체로 취급합니다
1급 객체란?
다음과 같은 객체를 의미한다.
- 변수나 데이터 구조안에 담을 수 있다.
- 파라미터로 전달할수 있다.
- 반환값으로 사용할 수 있다.
- 할당에 사용된 이름과 무관하게 고유한 구별이 가능하다.
함수를 변수에 할당하거나, 다른 함수에 인자로 전달하는 식으로 사용된다. 예시를 보면 쉽게 이해할 수 있다.
예시 : map, filter, reduce가 대표적인 고차 함수이다.
함수와 그 함수가 선언된 렉시컬 환경(lexical environment)을 함께 저장하여 함수가 생성될 때의 외부 변수와 그 값을 “기억”하는 기능을 의미합니다.
클로저는 함수가 생성될 때의 외부 변수를 포함한 환경을 “닫아”서 함수 내에서 참조할 수 있게 만든 것입니다. 즉, 클로저는 함수와 함수가 선언될 때의 스코프의 조합으로, 함수가 실행되는 시점에 외부 스코프에 접근할 수 있도록 합니다.
이러한 클로저는 함수를 일급 객체로 취급할 수 있도록하고 불변성과 캡슐화, 정보 은닉의 특성을 제공하고 비동기 프로그래밍에서 함수가 호출되는 시점에 필요한 상태나 문맥 정보를 유지하는데 유용하게 사용된다.
필자는 코드 예시를 보는 것이 이해하기 쉬웠기 때문에 파이썬 코드 예시를 들고 왔다.
객체지향 프로그래밍의 예시
class BankAccount:
def __init__(self, balance=0):
self.balance = balance
def deposit(self, amount):
if amount > 0:
self.balance += amount
def withdraw(self, amount):
if amount > 0 and amount <= self.balance:
self.balance -= amount
def get_balance(self):
return self.balance
# 사용 예시
account = BankAccount()
account.deposit(100)
account.withdraw(50)
print(account.get_balance()) # 출력: 50
함수형 프로그래밍의 예시
def create_account(balance=0):
return balance
def deposit(account, amount):
if amount > 0:
return account + amount
return account
def withdraw(account, amount):
if amount > 0 and amount <= account:
return account - amount
return account
def get_balance(account):
return account
# 사용 예시
account = create_account()
account = deposit(account, 100)
account = withdraw(account, 50)
print(get_balance(account)) # 출력: 50
불변성 유지: 객체지향 코드에서는 balance 속성이 변경되지만, 함수형 코드에서는 새로운 balance 값을 반환하여 상태를 변경하는 대신 상태를 유지합니다. 즉, 각 함수는 상태를 변경하는 대신 새로운 상태를 반환합니다.
순수 함수 사용: 함수형 프로그래밍에서는 각 함수가 동일한 입력에 대해 동일한 출력을 보장하며, 외부 상태를 변경하지 않습니다. deposit, withdraw, get_balance 함수 모두 외부 변수나 상태에 의존하지 않고, 주어진 인수에 따라서만 작동합니다.
캡슐화와 상태 전달: 상태는 함수 호출 간에 전달되며, 상태를 직접 변경하지 않습니다. 상태 변경이 필요하면 새로운 상태를 반환하고, 이 상태를 다음 함수로 전달합니다.
데이터와 함수의 분리: 객체지향 프로그래밍에서는 데이터와 메서드가 객체 내에 함께 정의되지만, 함수형 프로그래밍에서는 데이터와 함수를 분리하여 처리합니다.
다음은 함수형 프로그래밍 검색을 하다가 정말 이해하기 쉬운 예시를 들고 왔다.
예시는 티라미수 케이크를 만드는 레시피를 예시로 했다.


def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa):
return refrigerate(
sift(
assemble(
fold(
beat(
whisk( # over steam
beat(beat(eggs), sugar1, wine)
),
beat(cheese)
),
whip(cream)
),
soak2seconds(fingers, dissolve(sugar2, espresso))
),
cocoa
)
)

https://mangkyu.tistory.com/1%E3%85%87%E3%84%B9%E3%84%B4
https://velog.io/@teo/functional-programming-study
https://www.lihaoyi.com/post/WhatsFunctionalProgrammingAllAbout.html