Flutter/기본

[Flutter] 람다함수없이 코드를 짜는 방법 feat. Tear-offs

주톨 2023. 6. 15. 01:01
728x90

 

 

 

안녕하세요. 여러분 혹시 이런 코드 보신 적 있으신가요?

 

              ElevatedButton(
                child: Text("increment"),
                onPressed: increment,
              )

 

해당 코드에 이상한 점을 눈치채셨나요?

 

              ElevatedButton(
                child: Text("increment"),
                onPressed: () {
                  increment();
                },
              )

 

대부분의 사람들은 위의 코드처럼 사용하셨을 겁니다. 하지만 작업을 하다가 공부를 하다가 첫 번째 코드 같은 코드를 접해보신 분들도 있으실 겁니다. 오늘 알아볼 것이 바로 첫 번째 코드가 무엇인지? 알아보겠습니다.

 

 

 

1. 람다 함수를 찢어버려~ "Tear-offs"

람다 함수 없이 함수의 이름만으로 사용하는 것을 Tear-offs라고 부릅니다. 직역을 하자면 떼어내다라고 합니다. 불필요한 코드를 떼어냄으로써 코드의 간결함을 추구할 수 있을 거 같습니다. 

 

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int num = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(num.toString()),
              SizedBox(height: 18),
              ElevatedButton(
                child: Text("increment"),
                onPressed: increment,
              ),
            ],
          ),
        ),
      ),
    );
  }

  void increment() {
    setState(() {
      num++;
    });
  }
}

 

전체 코드입니다. increment 함수를 Tear-offs를 이용해 함수 이름만 넣어서 코드를 간결하게 줄인 모습이 보입니다. 하지만 아무 함수이름을 넣어서 사용할 수 있을까요?

 

 

2. Tear-offs 조건

Tear-offs를 하려면 조건을 갖춰야 합니다.

 

 

ElevatedButton의 onPressed의 Type은 void Function()?입니다.  즉 반환값이 없고, 파라미터가 없는 함수를 받는다는 의미입니다. 이 조건에 맞춰서 함수를 만들면 Tear-offs의 조건을 충족하게 됩니다.

 

  void increment() {
    setState(() {
      num++;
    });
  }

 

위에서 만든 increment 함수를 보시면 반환형은 void이고 받는 파라미터는 없는 것을 확인할 수 있습니다. 즉ElevatedButton의 onPressed의 Type과 동일합니다.  Tear-offs의 조건을 충족하기에 함수의 이름만을 이용해서 코드를 작성할 수 있게 된 것입니다. 다른 예제를 살펴볼까요? 

 

 

 

 

 

class _MyAppState extends State<MyApp> {
  String text =  "";

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(text),
              SizedBox(height: 18),
              TextFormField(
                onChanged: (value) {
                  setState(() {
                    text = value;
                  });
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

위의 영상은 해당코드로 동작됩니다. TextFormField의 onChanged를 보시면 현재 람다함수로 구현되어 있습니다. 해당 부분을 Tear-offs를 이용해서 수정해 보겠습니다.

 

 

일단 onChanged의 Type부터 알아봐야겠습니다. 반환이 없고 파라미터로는 String을 받는 함수 Type 이군요. 

  void setText(String value) {
    setState(() {
      text = value;
    });
  }

 

반환형이 없고 파라미터로 String을 받는 함수를 만들었습니다. 이제 해당함수를 Tear-offs를 이용해서 함수명을 onChanged에 람다를 빼고 집어넣어서 사용해 보겠습니다.

 

class _MyAppState extends State<MyApp> {
  String text =  "";

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(text),
              SizedBox(height: 18),
              TextFormField(
                onChanged: setText,
              ),
            ],
          ),
        ),
      ),
    );
  }

  void setText(String value) {
    setState(() {
      text = value;
    });
  }
}

실행해 보면 잘 동작하는 것을 알 수 있습니다. 이렇게 Tear-offs를 사용하면 파라미터도 자동으로 넘겨주는 것을 확인할 수 있습니다. 정말 편리하죠? 알고 나니 의외로 간단한 녀석이었네요.!!

 

 

 

3. Tear-offs의 장점? 

 

 

그렇다면 람다함수를 사용해서 하면 되는걸 굳이 Tear-offs를 사용하는지 의문이 생깁니다. 

 

(1) 가독성

위에서도 설명하였듯이 불필요한 코드를 떼어냄으로써 코드는 간결해지고 함수의 네이밍이 해당 기능에 맞게 잘 지어진 경우에 Tear-offs를 사용하여 해당 기능을 참조하는 것이 코드를 읽고 이해하기 쉽게 만들어 줍니다.

 

(2)  성능

Tear-offs를 사용하면 람다 함수보다 효율적인 성능을 얻을 수 있습니다. 람다 함수는 실행될 때마다 새로운 함수 인스턴스를 생성하는 반면에, Tear-offs는 이미 정의된 함수를 참조하기 때문에 인스턴스 생성 비용이 없습니다.

 

자주 여러 번 호출되는 함수 같은 경우에는 오늘 배운 Tear-offs를 사용해서 구현하면 더 좋은 성능을 기대해 볼 수 있을 거 같네요.