Flutter/Dart

Dart 클로저 {} 파헤치기 + 익명함수랑 클로저의 차이는 ?

복복씨 2024. 11. 18. 18:27

 

클로저란?

 

클로저는 외부 변수나 상태를 기억하고 쓸 수 있는 함수임.
함수가 만들어질 때 주변에 있던 변수들을 캡처해서 저장해 놓고, 나중에 다시 사용할 수 있게 해줌.

어떻게 동작함?

  1. 클로저는 자기 주변의 스코프(환경)를 기억함.
  2. 함수가 실행된 뒤에도 외부 변수의 상태를 유지함.
  3. 그래서 외부 변수를 읽거나 수정할 수 있음.

Dart에서 클로저 예제

1. 외부 변수를 기억하는 클로저

void main() {
  int counter = 0;

  Function increment = () {
    counter++; // 외부 변수에 접근함
    print("Counter: $counter");
  };

  increment(); // Counter: 1
  increment(); // Counter: 2
}
  • 함수 increment는 외부 변수 counter를 기억하고 계속 사용함.
  • 실행할 때마다 외부 변수 값을 변경함.

2. 클로저를 반환하는 함수

Function makeMultiplier(int multiplier) {
  return (int value) {
    return value * multiplier; // multiplier를 기억함
  };
}

void main() {
  var doubleValue = makeMultiplier(2);
  var tripleValue = makeMultiplier(3);

  print(doubleValue(5)); // 10
  print(tripleValue(5)); // 15
}
  • makeMultiplier 함수는 클로저를 반환함.
  • 반환된 함수는 외부 변수 multiplier 값을 기억하고, 그 값을 계속 사용함.

클로저의 장점

  1. 상태 유지:
    • 함수가 실행된 후에도 외부 변수를 유지함.
    • 외부 값을 저장하고 필요할 때 다시 사용 가능함.
  2. 코드 재사용성:
    • 특정 상태와 동작을 캡슐화해서 어디서든 재사용할 수 있음.
  3. 캡슐화:
    • 외부 변수는 클로저 안에서만 접근 가능함. 다른 코드에서는 수정할 수 없어서 안전함.

클로저는 어디에 쓰임?

  • 상태 관리:
    • 값이나 설정을 유지하면서 동작해야 할 때 사용함.
  • 콜백 함수:
    • 이벤트가 발생했을 때 특정 상태를 기반으로 동작할 때 사용함.
  • 함수형 프로그래밍:
    • Dart에서 고차 함수와 함께 사용될 때 강력한 도구가 됨.

 

익명 함수와 클로저의 정의

  1. 익명 함수:
    • 이름이 없는 함수임.
    • 그 자리에서 바로 정의하고 사용되는 함수.
    • 외부 상태와 관계없이 독립적으로 작동할 수도 있음.
  2. 클로저:
    • 외부 변수를 캡처해서 기억하고 사용하는 함수임.
    • 익명 함수든, 이름 있는 함수든 외부 변수에 의존하면 클로저가 됨.

익명 함수와 클로저의 차이

구분 익명 함수 클로저
이름 이름이 없음 이름이 있을 수도, 없을 수도 있음
외부 변수 캡처 외부 변수와 상관없이 독립적으로 사용 가능 외부 변수(스코프)를 기억하고 사용할 수 있음
사용 방식 콜백 함수나 일회성 작업에서 주로 사용 상태를 저장하고 재사용해야 하는 작업에서 사용
관계 클로저가 될 수도 있음 (외부 변수를 캡처하면 클로저로 작동함) 익명 함수, 이름 있는 함수 모두 클로저가 될 수 있음

코드 예제로 이해하기

1. 익명 함수 (클로저 아님)

외부 변수에 의존하지 않음. 그냥 이름 없는 함수임.

void main() {
  var add = (int a, int b) {
    return a + b;
  };

  print(add(3, 4)); // 7
}
  • 익명 함수: 외부 변수와 관계없이 동작함. 외부 상태를 기억하지 않으므로 클로저가 아님.

2. 클로저 (외부 변수 캡처)

외부 변수(count)를 기억해서 사용하는 함수임.

void main() {
  int count = 0;

  var increment = () {
    count++; // 외부 변수 사용
    print("Counter: $count");
  };

  increment(); // Counter: 1
  increment(); // Counter: 2
}
  • 클로저: 익명 함수가 외부 변수 count를 캡처해서 상태를 유지함.

3. 이름 있는 클로저

익명 함수가 아니어도 클로저가 될 수 있음.

Function makeMultiplier(int multiplier) {
  return (int value) {
    return value * multiplier; // 외부 변수 multiplier 캡처
  };
}

void main() {
  var doubleValue = makeMultiplier(2); // multiplier = 2
  print(doubleValue(5)); // 10
}
  • 반환된 함수는 이름이 없지만, 여전히 외부 변수 multiplier를 캡처해서 사용하는 클로저임.

익명 함수는 언제 클로저가 될까?

익명 함수가 외부 변수를 참조할 때 클로저가 됨.
즉, 모든 익명 함수가 클로저는 아님!

예제:

void main() {
  int x = 10;

  // 클로저
  var closure = () {
    print("x는 $x임");
  };

  closure(); // x는 10임
}
  • 여기서 익명 함수 closure는 외부 변수 x를 참조하므로 클로저임.

왕깔끔정리

외부변수에 의존하면. 클로저임 클로저는 캡쳐를 하닝까