안녕하세요. 여러분 혹시 이런 코드 보신 적 있으신가요?
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를 사용해서 구현하면 더 좋은 성능을 기대해 볼 수 있을 거 같네요.
'Flutter > 기본' 카테고리의 다른 글
[Flutter] 텍스트 폰트 설정하기 (Pretendard폰트) (0) | 2023.06.23 |
---|---|
[Flutter] 상태 표시줄 또는 스테이터스 바 설정하기 (0) | 2023.06.22 |
[Flutter] flutter_dotenv 패키지 사용해보기 feat. env (0) | 2023.06.09 |
[Flutter] Text에 밑줄, 윗줄, 취소선 추가하기 (0) | 2023.05.30 |
[Flutter] static 키워드 (4) | 2023.04.18 |