본문 바로가기
Flutter & Dart

Flutter & Dart - Functional Programming (함수형 프로그래밍)

by 방정맞은사람 2025. 1. 9.

 

해당 목차는 저의 배움을 설명 하기에 앞서 드리고 싶은 말이 있습니다.
함수형 프로그래밍이란 주제를 가지고 책이 여러권 있을만큼 아직까지도 많은 내용과 사람마다 다양한 생각이 존재하는데요.
제가 설명 드리는 부분이 극히 일부분 + 저의 개인적인 생각이 들어간 부분이 존재하니
FP 관련해서는 제 글 만 보지 마시고 다른 글도 참고 하셔서 유익한 정보만 가져가셨으면 합니다.


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

함수형 프로그래밍이란?

함수형 프로그래밍(Functional Programming)은 프로그래밍 패러다임 중 하나로, 프로그램의 구성 요소를 순수 함수(Pure Function)로 작성하고, 상태 변화와 부작용(Side Effect)을 최소화하여 코드를 작성하는 방법론입니다. 데이터와 함수의 불변성을 중시하며, 선언형 프로그래밍 스타일을 따릅니다.


함수형 프로그래밍의 특징

  1. 순수 함수(Pure Function):
    •  입력값이 같으면 항상 같은 출력값을 반환.
    •  함수 외부의 상태를 변경하지 않으며 부작용이 없음.
    int add(int a, int b) => a + b;  // 순수 함수의 예
  2. 불변성(Immutability):
    •  데이터는 한 번 정의되면 변경되지 않음.
    •  새로운 데이터를 생성할 때 기존 데이터를 복사하여 생성.
    final list = [1, 2, 3];
    final newList = [...list, 4];  // 기존 리스트는 변경되지 않음
  3. 고차 함수(Higher-Order Function):
    •  함수를 매개변수로 받거나 반환값으로 함수 반환 가능.
    Function add(int a) => (int b) => a + b;
    final addFive = add(5);
    print(addFive(10)); // 출력: 15
  4. 지연 평가(Lazy Evaluation):
    •  필요할 때까지 계산을 미루는 방식.
    final numbers = List.generate(10, (i) => i);
    final evenNumbers = numbers.where((n) => n.isEven); // 계산이 지연됨
    print(evenNumbers.toList()); // 여기서 계산 실행
  5. 선언형 프로그래밍(Declarative Programming):
    •  "어떻게(How)"보다는 "무엇을(What)"에 중점을 둔 코딩 스타일.
    // 절차적 프로그래밍
    final accounts = getAccounts();
    final nameList = <String>[];
    for (final account in accounts) {
      final user = getUser(account.userId);
      nameList.add(user.name);
    }
    
    // 함수형 프로그래밍
    final nameList2 = getAccounts()
        .map((account) => account.userId)
        .map((userId) => getUser(userId))
        .map((user) => user.name)
        .toList();

함수형 프로그래밍의 장점

  1. 가독성 향상:
    •  상태 변경이 적어 코드의 흐름이 명확.
    •  선언형 스타일로 작성하여 직관적 이해 가능.
  2. 모듈성(Modularity):
    •  함수를 조합하여 재사용 가능.
  3. 병렬 처리 용이:
    •  데이터의 불변성으로 인해 병렬 프로그래밍 시 충돌 가능성 감소.
  4. 테스트와 디버깅 용이:
    •  순수 함수는 독립적으로 테스트 가능.
    •  외부 상태에 의존하지 않기 때문에 예측 가능성이 높음.

함수형 프로그래밍과 Dart/Flutter

Dart는 함수형 프로그래밍의 특징을 지원하며, Flutter 개발에서도 함수형 프로그래밍 스타일을 자주 활용합니다.

1. 고차 함수와 메서드 체이닝

final numbers = [1, 2, 3, 4, 5];
final squaredEvenNumbers = numbers
    .where((n) => n.isEven)
    .map((n) => n * n)
    .toList();
print(squaredEvenNumbers); // 출력: [4, 16]

2. 클로저와 상태 관리

Function counter() {
  int count = 0;
  return () => ++count;
}

final increment = counter();
print(increment()); // 출력: 1
print(increment()); // 출력: 2

3. Stream을 활용한 비동기 데이터 처리

Stream<int> countStream() async* {
  for (int i = 1; i <= 5; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

countStream().listen((data) => print(data));
// 1초마다 1, 2, 3, 4, 5 출력

함수형 프로그래밍의 한계

  1. 성능:
    •  데이터 복사가 많아 메모리 사용량이 증가할 수 있음.
  2. 러닝 커브:
    •  선언형 프로그래밍과 고차 함수 사용에 익숙하지 않은 개발자들에게는 진입 장벽이 있음.
  3. 실용적 한계:
    •  순수 함수만을 사용하기 어려운 경우가 존재. 예를 들어, UI 업데이트나 데이터베이스 작업 등은 상태 변경이 필요.

결론

함수형 프로그래밍은 코드를 간결하고 읽기 쉽게 만들며, 버그 발생 가능성을 줄이고 병렬 처리를 쉽게 구현할 수 있도록 돕습니다. Dart와 Flutter는 함수형 프로그래밍의 핵심 개념들을 적극적으로 활용할 수 있는 언어와 프레임워크로, 이를 통해 효율적이고 유지보수 가능한 코드를 작성할 수 있습니다.

함수형 프로그래밍을 완전히 따르기보다는, 적절히 활용하여 선언형 코드를 작성하고 상태 변화를 최소화하는 것이 중요합니다.

'Flutter & Dart' 카테고리의 다른 글

Flutter & Dart - Closure  (1) 2025.01.14
Flutter & Dart - Isolates<in Dart>  (1) 2025.01.13
Flutter & Dart - Dart 에서의 커링(Currying)  (0) 2025.01.09
Flutter & Dart - Lambda  (2) 2025.01.08
Flutter & Dart - Iterable  (0) 2025.01.08