Flutter/Dart

Dart 기본 문법 4 - 클로저, 고차함수, 익명함수

빈코더 2025. 1. 11. 00:11
728x90

안녕하세요! 이번 포스팅에서는 Flutter 개발에 필수적인 Dart 문법 중 클로저, 고차함수, 익명함수에 대해서 알아보겠습니다.

 

그전에 무조건 앞에 문법 확인하고 오세요 ~ 

 

1. Dart 언어의 기본 문법 1편 - 변수, 함수, 클래스, 리스트, 조건문, 반복문

 

Dart 기본 문법 1 - 변수, 함수, 클래스, 리스트, 조건문, 반복문

안녕하세요! 오늘은 Flutter 개발에 필수적인 Dart 언어의 기본 문법을 정리해 보겠습니다. Dart는 Google에서 만든 프로그래밍 언어로, 특히 Flutter 앱 개발에서 사용됩니다. 이번 포스팅에서는 Dart의

binogood.tistory.com

 

2. Dart 언어의 기본 문법 2편 - Map, Null Safety, Enum, Set, 연산자

 

Dart 기본 문법 2 - 맵(Map), Null Safety, Enum, Set, 연산자

안녕하세요! 오늘은 Flutter 개발에 필수적인 Dart 언어의 기본 문법 1편에 이어 2편을 정리해 보겠습니다. 이번 포스팅에서는 Dart의 핵심 문법인 맵(Map),  Enum, Null Safety, Set, 연산자을 다룰 예정

binogood.tistory.com

 

3. Dart 언어의 기본 문법 3편 - Future와 async/await

 

Dart 기본 문법 3 - Future와 async/await

안녕하세요! 오늘은 Flutter 개발에 필수적인 문법 중  1. Dart 언어의 기본 문법 1편 - 변수, 함수, 클래스, 리스트, 조건문, 반복문 Dart 기본 문법 1 - 변수, 함수, 클래스, 리스트, 조건문, 반복문안

binogood.tistory.com

1.  클로저(Closure)란?

클로저는 외부 함수의 변수에 접근할 수 있는 내부 함수입니다.

Dart에서는 함수가 생성된 스코프(scope)에 정의된 변수에 접근할 수 있는 특성을 클로저라고 합니다. 

 

1-1 클로저의 특징

  • 외부 함수의 지역 변수에 접근 가능: 내부 함수는 외부 함수가 실행된 이후에도 외부 함수의 변수에 접근할 수 있습니다.
  • 상태를 유지: 외부 변수의 상태를 기억하고 변경할 수 있습니다.
  • 클로저는 상태를 유지해야 하는 비즈니스 로직에서 유용합니다.
Function makeCounter() {
  int count = 0;

  return () {
    count++;
    return count;
  };
}

void main() {
  var counter = makeCounter();

  print(counter()); // 출력: 1
  print(counter()); // 출력: 2
  print(counter()); // 출력: 3
}

 

설명

  • makeCounter함수는 count라는 변수를 생성하고, 이 변수에 접근하는 익명 함수를 반환 합니다.
  • 반환된 익명 함수는 클로저로 동작하며, count의 상태를 유지합니다.

 

2.  익명 함수(Anonymous Function)란?

익명 함수는 이름이 없는 함수입니다.

한 번만 사용하거나 간단한 로직을 처리할 때 사용합니다. 

 

기본 문법

(parameters) {
  // 함수 내용
};

 

익명 함수는 변수에 할당하거나 다른 함수의 인수로 전달할 수 있습니다.

 

익명 함수 사용 예제

void main() {
  // 익명 함수를 변수에 할당
  var multiply = (int a, int b) {
    return a * b;
  };

  print(multiply(3, 4)); // 출력: 12

  // 함수 내에서 직접 사용
  var list = [1, 2, 3];
  list.forEach((item) {
    print(item * 2); // 2, 4, 6 출력
  });
}

3.  고차 함수(Higher-Order Function)란?

고차 함수는 다른 함수를 인자로 받거나, 함수를 반환하거나, 또는 둘 다 할 수 있는 함수 입니다.

Dart는 함수를 1급 객체로 다루기 때문에, 함수를 변수처럼 전달하거나 반환할 수 있습니다.

 

3-1 고차 함수의 특징

  • 함수를 인수로 전달: 함수가 다른 함수에 인수로 전달됩니다.
  • 함수를 반환: 함수가 다른 함수를 반환합니다.

예제 1: 함수를 인수로 전달

void printWithExclamation(String message, Function modify) {
  print(modify(message));
}

void main() {
  printWithExclamation('Hello', (msg) => '$msg!');
  // 출력: Hello!
}

 

예제 2: 함수를 반환

Function makeMultiplier(int multiplier) {
  return (int value) => value * multiplier; // 함수 반환
}

void main() {
  var doubleIt = makeMultiplier(2);
  print(doubleIt(5)); // 출력: 10

  var tripleIt = makeMultiplier(3);
  print(tripleIt(5)); // 출력: 15
}

 

4.  고차 함수,  익명함수,  클로저 사용 예제

4-1 익명 함수와 고차 함수의 조합

익명 함수는 고차 함수와 함께 자주 사용됩니다.

Dart에서 제공하는 컬렉션 메서드(forEach, map, where, reduce 등)에서 특히 유용합니다.

 

예제: 익명 함수와 고차 함수의 조합

void main() {
  var numbers = [1, 2, 3, 4, 5];

  // map: 각 요소에 함수를 적용
  var squaredNumbers = numbers.map((num) => num * num);
  print(squaredNumbers.toList()); // 출력: [1, 4, 9, 16, 25]

  // where: 조건에 맞는 요소만 필터링
  var evenNumbers = numbers.where((num) => num % 2 == 0);
  print(evenNumbers.toList()); // 출력: [2, 4]

  // reduce: 모든 요소를 하나로 결합
  var sum = numbers.reduce((a, b) => a + b);
  print(sum); // 출력: 15
}

 

4-2 고차 함수의 실용적 활용

 

예제: 정렬 함수 전달

void main() {
  var names = ['Charlie', 'Alice', 'Bob'];

  // 고차 함수로 정렬 기준 제공
  names.sort((a, b) => a.compareTo(b));
  print(names); // 출력: [Alice, Bob, Charlie]
}

 

예제: 커스텀 조건 필터링

List<int> filterNumbers(List<int> numbers, bool Function(int) test) {
  return numbers.where(test).toList();
}

void main() {
  var numbers = [1, 2, 3, 4, 5, 6];

  // 짝수 필터링
  var evenNumbers = filterNumbers(numbers, (num) => num % 2 == 0);
  print(evenNumbers); // 출력: [2, 4, 6]

  // 홀수 필터링
  var oddNumbers = filterNumbers(numbers, (num) => num % 2 != 0);
  print(oddNumbers); // 출력: [1, 3, 5]
}

 

4-3 익명 함수 vs 람다식

람다식(화살표 함수)은 익명 함수의 간단한 형태입니다. 한 줄로 표현할 수 있는 함수에 적합합니다.

 

예제: 익명 함수와 람다식 비교

void main() {
  // 일반 익명 함수
  var multiply = (int a, int b) {
    return a * b;
  };

  // 람다식 (화살표 함수)
  var multiplyShort = (int a, int b) => a * b;

  print(multiply(3, 4));      // 출력: 12
  print(multiplyShort(3, 4)); // 출력: 12
}

 

4-4 익명 함수와 클로저의 조합

익명 함수는 클로저로 활용될 때 강력한 기능을 발휘합니다.

void main() {
  var list = [1, 2, 3];
  var multiplyBy = 2;

  // 클로저를 사용하는 익명 함수
  var multipliedList = list.map((item) => item * multiplyBy).toList();
  print(multipliedList); // 출력: [2, 4, 6]
}

 

설명:

  • 익명 함수 (item) => item * multiplyBy는 외부 스코프의 변수 multiplyBy를 참조합니다.
  • 이는 클로저로 동작하여 multiplyBy의 값을 유지하고, 각 요소에 곱합니다.

4-5 고차 함수와 클로저의 조합

클로저는 고차 함수와 결합하여 함수의 동작을 동적으로 변경하거나 상태를 유지하는 데 유용합니다.

Function createAdder(int base) {
  return (int value) => base + value; // 클로저 생성
}

void main() {
  var addFive = createAdder(5);
  var addTen = createAdder(10);

  print(addFive(3)); // 출력: 8
  print(addTen(3)); // 출력: 13
}

 

설명:

  • createAdder는 매개변수 base를 기억하는 클로저를 반환합니다.
  • 반환된 함수는 외부 변수 base에 접근하여 값을 유지하고, 이를 사용해 덧셈을 수행합니다.

4-5 고차 함수와 익명함수, 클로저의 차이점과 관계

특징 익명 함수 고차 함수 클로저
정의 이름이 없는 함수 다른 함수를 인자로 받거나 반환하는 함수 외부 함수의 변수를 참조하는 내부 함수
역할 간단한 로직 처리 재사용 가능한 유연한 함수 설계 상태 유지 및 외부 변수 참조
활용 고차 함수의 인자로 자주 사용 코드 재사용성과 확장성 증가 비즈니스 로직에서 상태 관리

 

결론

익명 함수, 고차 함수, 그리고 클로저는 각각의 역할을 가지지만, 서로 밀접하게 연결되어 있습니다.

  • 익명 함수는 간단한 로직에서 유용하며, 클로저로 동작할 수도 있습니다.
  • 고차 함수는 코드의 재사용성을 높이고, 클로저를 활용해 동적 동작을 구현할 수 있습니다.
  • 클로저는 함수형 프로그래밍의 핵심으로, 상태를 유지하거나 외부 변수를 참조하는 데 적합합니다.

 

익명 함수와 고차 함수만 다룰 수도 있지만,

클로저를 포함하면 Dart의 함수형 프로그래밍의 강력한 가능성을 더 잘 전달할 수 있습니다.

클로저를 활용한 상태 관리와 같은 실용적인 예제를 포함해보세요! 😊

728x90