[개발하는남자 핸즈온 플러터] 챕터14 홈 화면 구성 리뷰
개요
안녕하세요, 개발하는남자 개남입니다. 지난 포스트가 챕터12였는데 바로 챕터 14로 넘어와서 챕터 13은 어디 있는지 찾고 계시지 않으셨나요? 13챕터는 책에서 다루는 내용 외에 따로 소개드릴 내용이 없다고 생각되었습니다. 즉, 책의 내용만으로도 충분히 내용 이해에 어려움이 없다고 판단되었기 때문에 생략한 것이고 챕터 14로 넘어온 것입니다.
챕터 14 리뷰에서는 최신화할 만한 것은 없고 내부 위젯 클래스의 특징에 대해서 간단히 다루고 넘어가도록 하겠습니다.
소스코드 : https://github.com/sudar-life/bamtol_market_clone_coding
브런치 정보 : chapter14
플러터 버전 : Flutter 3.32.5
Dart 버전 : Dart 3.8.1
내부 위젯 클래스의 특징
페이지 485페이지에서 body 구성을 할 때 build 함수 내부에 작성하지 않고 별도의 위젯 클래스로 분리하여 작성되어 있습니다.
body: const _ProductList(),
별도의 위젯 클래스를 만들어 분리하는 이유에 대해서 간단히 책에서는 이렇게 기록되어 있습니다.
- 소스 관리 측면의 장점
- 별도로 상태 있는 위젯으로 변경할지 상태 없는 위젯으로 변경할지에 대한 확장성
- 위젯 재사용을 할 수 있다는 장점
이렇게 설명하며 _ProductList라는 이름의 위젯 클래스를 생성해서 관리하고 있습니다.
여기서 볼 두 가지 특징은 위젯 이름에 _(언더바)로 시작한다는 점과 동일한 파일 내에 클래스를 생성했다는 점이 특징입니다.
보통 위젯(컴포넌트)의 경우 별도의 파일로 생성하는 게 일반적입니다. 그래야 소스코드의 라인 수도 줄일 수 있고 재사용성으로도 이점이 있기 때문입니다. 하지만 위 특징으로 위젯 이름에 _(언더바)로 시작의 특징 때문에 동일한 파일 내에 정의해야만 합니다.
Flutter(Dart)에서는 _(언더바)로 시작되는 변수나 클래스의 경우 private 변수, private 클래스의 성질로 변하게 됩니다. private 키워드에서 알 수 있듯 동일 라이브러리 내에서만 접근 가능하다는 점입니다.
// user_model.dart class User { String name; String _password; // private 변수 void _validatePassword() { // private 메소드 // 비밀번호 검증 로직 } } // main.dart import 'user_model.dart'; void main() { User user = User(); user.name = "김개발"; // ✅ 접근 가능 user._password = "123"; // ❌ 오류! private 변수 user._validatePassword(); // ❌ 오류! private 메소드 }
다시 말해 홈 화면에 리스트 화면을 담당하는 _ProductList() 위젯은 home_page.dart 파일 내에서만 재사용이 가능하며 다른 파일에서는 해당 위젯을 재사용할 수 없음을 의미합니다.
그렇다면 왜 홈 화면에 상품 리스트를 다른 곳에서 사용하지 못하도록 private class로 정의했을까요?
가장 큰 이유는 불필요한 위젯 생성을 막기 위함입니다.
프로젝트를 진행하다 보면 모든 위젯을 파일로 관리하면 재사용하지 않는 위젯들이 넘쳐나게 됩니다. 그렇게 되면 꼭 재사용해야 하는 위젯들을 찾기도 어려워지고 파일 수가 많아지면 build 속도에도 영향을 주기 때문입니다. 그래서 웬만한 페이지 내에 설계할 때에 기획된 기획서나 디자인 시안을 통해 재사용할 수 있는 화면들을 정리해서 필요한 위젯들만 별도 파일로 위젯을 설계하는 것이 좋습니다.
밤톨마켓의 화면 기획을 보면 홈 화면에 사용되는 상품 목록이 다른 곳에서 사용되지 않기 때문에 별도 파일로 분리하지 않은 것이고, 만일 개발을 진행하다 보면 홈 화면에서 사용된 상품 목록의 위젯이 필요하다 생각이 들면 해당 위젯을 별도 파일로 분리하여 작업하는 리펙토링 과정을 거치게 될 것입니다.
클래스형 위젯과 함수형 위젯 차이
책 487페이지에 리스트 itemBuilder로 함수형 위젯을 사용했습니다.
itemBuilder: (context, index) { return _productOne(index); // ---- 1 },
이 부분을 집필 당시에는 빠른 접근성을 목적으로 내부 함수 위젯으로 설계했는데요, 이 경우 성능적으로 개선을 위해서는 클래스 위젯으로 변경해주는 것이 좋습니다. 간단히 클래스 위젯과 함수형 위젯에 대한 내용을 다뤄보겠습니다.
클래스 위젯 (Class Widget)
정의
class MyClassWidget extends StatelessWidget { final String title; final VoidCallback onPressed; const MyClassWidget({ Key? key, required this.title, required this.onPressed, }) : super(key: key); Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, child: Text(title), ); } }
장점
- 타입 안정성: 컴파일 타임에 타입 체크
- 성능 최적화: Widget tree에서 효율적인 리빌드
- 개발 도구 지원: Flutter Inspector에서 잘 보임
- const 생성자: 메모리 효율성
- 상속 가능: 다른 위젯으로 확장 가능
함수 위젯 (Function Widget)
정의
Widget myFunctionWidget({ required String title, required VoidCallback onPressed, }) { return ElevatedButton( onPressed: onPressed, child: Text(title), ); } Widget build(BuildContext context){ return Container( child : myFunctionWidget() ); }
장점
- 간단함: 빠르게 작성 가능
- 적은 보일러플레이트: 클래스 선언 불필요
- 함수형 프로그래밍: 순수 함수 스타일
성능 차이점
클래스 위젯의 성능 우위
// 클래스 위젯 - 효율적인 리빌드 class OptimizedWidget extends StatelessWidget { const OptimizedWidget({Key? key}) : super(key: key); Widget build(BuildContext context) { print('클래스 위젯 빌드됨'); // 필요할 때만 호출 return Container(child: Text('Hello')); } } // 함수 위젯 - 매번 새로운 객체 생성 Widget unoptimizedWidget() { print('함수 위젯 빌드됨'); // 부모가 리빌드될 때마다 호출 return Container(child: Text('Hello')); }
실제 사용 예시
class MyHomePage extends StatefulWidget { _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; Widget build(BuildContext context) { return Scaffold( body: Column( children: [ // ✅ 클래스 위젯 - _counter가 변해도 리빌드되지 않음 const OptimizedWidget(), // ❌ 함수 위젯 - _counter가 변할 때마다 리빌드됨 unoptimizedWidget(), Text('Counter: $_counter'), ElevatedButton( onPressed: () => setState(() => _counter++), child: Text('증가'), ), ], ), ); } }
결론
| 구분 | 클래스 위젯 | 함수 위젯 |
|---|---|---|
[object Object] | ✅ 우수 | ❌ 떨어짐 |
[object Object] | ✅ 높음 | ❌ 낮음 |
[object Object] | ✅ 높음 | ⚠️ 보통 |
[object Object] | ⚠️ 보통 | ✅ 빠름 |
[object Object] | ✅ 쉬움 | ⚠️ 보통 |
[object Object] | ✅ 쉬움 | ⚠️ 보통 |
권장: 대부분의 경우 클래스 위젯을 사용하고, 정말 간단한 UI 조각에만 함수 위젯을 사용하세요!
Write by :
개발하는남자
Developer
💬댓글 (0)
댓글을 작성하려면 로그인이 필요합니다.
댓글을 불러오는 중...