본문 바로가기
Flutter

플러터에서 위젯을 분리 하는 방법

by Maccrey Coding 2024. 11. 11.
728x90
반응형

 

위젯을 분리하는 방법은 Flutter 앱을 더 깔끔하고 유지보수하기 쉽게 만드는 중요한 방법입니다.

하나의 화면이나 클래스가 너무 커지면 여러 가지 문제가 발생할 수 있습니다. 예를 들어, 가독성이 떨어지고 코드가 복잡해지며 디버깅이 어려워집니다.

따라서 Flutter에서는 위젯을 적절히 분리하는 것이 중요합니다.

여기서는 위젯을 분리하는 기본적인 방법과 실용적인 예시를 소개합니다.

1. 기본적인 위젯 분리

Flutter에서 위젯을 분리하는 방법은 크게 두 가지로 나눌 수 있습니다:

  • 상태가 없는 StatelessWidget: 상태가 없고 단순히 UI를 표시하는 위젯을 분리.
  • 상태가 있는 StatefulWidget: 상태를 관리하는 로직을 가진 위젯을 분리.

2. 상태 없는 위젯 분리

상태가 없는 위젯은 UI를 렌더링하는 역할만 합니다. 이를 별도의 위젯으로 분리할 때는 보통 화면에 표시되는 내용에 따라 분리합니다.

예를 들어, TopTitlePart와 WeekCalendarScreen을 별도의 위젯으로 분리할 수 있습니다.

예시: TopTitlePart 분리하기

class TopTitlePart extends StatelessWidget {
  final VoidCallback onBackPressed;

  const TopTitlePart({required this.onBackPressed, Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        TextButton(
          child: const Text(
            "Today,",
            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24),
          ),
          onPressed: onBackPressed,
        ),
        Row(
          children: [
            const Text(
              'Coding Study',
              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24),
            ),
            IconButton(
                onPressed: () {
                  const Text('프로필 버튼 동작 확인');
                },
                icon: const Icon(
                  Icons.person,
                  size: 30,
                )),
          ],
        ),
      ],
    );
  }
}

이렇게 TopTitlePart를 분리하면 CoddingHome에서 더 깔끔한 구조가 됩니다.

CoddingHome에서 TopTitlePart 사용

class CoddingHome extends StatefulWidget {
  const CoddingHome({super.key});

  @override
  State<CoddingHome> createState() => _CoddingHomeState();
}

class _CoddingHomeState extends State<CoddingHome> {
  bool stateStudy = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(18.0),
          child: Column(
            children: [
              TopTitlePart(
                onBackPressed: () {
                  Navigator.of(context).pop();
                },
              ),
              WeekCalendarScreen(),
              Imagechange(
                stateStudy: stateStudy,
                startTimer: startTimer,
                resetTimer: resetTimer,
                stopTimer: stopTimer,
              ),
              const SizedBox(height: 20),
              ChangedButton(stateStudy),
            ],
          ),
        ),
      ),
    );
  }

  void startTimer() {
    // timer logic
  }

  void stopTimer() {
    // stop timer logic
  }

  void resetTimer() {
    // reset timer logic
  }
}

3. 상태 있는 위젯 분리

상태를 관리하는 StatefulWidget도 분리할 수 있습니다. 이때, 상태를 변경하는 로직과 UI를 분리하는 것이 중요합니다. 예를 들어, ImageChange는 상태를 관리하고, startTimer, stopTimer와 같은 타이머 관련 로직을 처리하므로 이를 별도의 위젯으로 분리할 수 있습니다.

예시: ImageChange 분리하기

class ImageChange extends StatefulWidget {
  bool stateStudy;
  final Function startTimer;
  final Function stopTimer;
  final Function resetTimer;

  ImageChange({
    super.key,
    required this.stateStudy,
    required this.startTimer,
    required this.stopTimer,
    required this.resetTimer,
  });

  @override
  _ImageChangeState createState() => _ImageChangeState();
}

class _ImageChangeState extends State<ImageChange> {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        const SizedBox(height: 10),
        GestureDetector(
            onTap: () {
              setState(() {
                widget.stateStudy = !widget.stateStudy;
                if (widget.stateStudy == false) {
                  widget.startTimer();
                } else {
                  widget.stopTimer();
                  widget.resetTimer();
                }
              });
            },
            child: widget.stateStudy
                ? Image.asset(
                    'lib/assets/images/study_night_boy.png',
                    width: 70,
                  )
                : Image.asset(
                    'lib/assets/images/kokage_tree_necchusyou.png',
                    width: 76,
                  )),
      ],
    );
  }
}

CoddingHome에서 ImageChange 사용

ImageChange(
  stateStudy: stateStudy,
  startTimer: startTimer,
  stopTimer: stopTimer,
  resetTimer: resetTimer,
)

4. 위젯 분리 팁

  • 단일 책임 원칙(Single Responsibility Principle): 각 위젯은 하나의 책임만 가지도록 분리합니다. 예를 들어, ImageChange는 이미지 변경만 책임지고, 타이머 로직은 CoddingHome이나 다른 위젯에서 처리하도록 합니다.
  • 재사용성: 분리한 위젯은 재사용성을 높이기 위해 외부에서 전달받는 데이터나 콜백을 활용합니다. 이렇게 하면 다른 화면에서도 동일한 위젯을 재사용할 수 있습니다.
  • 유지보수 용이성: 복잡한 UI나 로직을 작은 단위로 나누면 수정할 때 더 적은 영향을 미치므로 유지보수가 쉬워집니다.

5. 상태 관리 및 데이터 흐름

상태를 공유해야 할 경우, Provider, Riverpod, Bloc, setState 등 다양한 상태 관리 방법을 사용할 수 있습니다. 위에서 예시를 든 것은 간단한 setState 방식이지만, 복잡한 앱에서는 Provider와 같은 상태 관리 라이브러리를 사용하는 것이 좋습니다.

6. 위젯 분리 후의 장점

  • 가독성 향상: 각 위젯이 독립적으로 동작하기 때문에 코드가 더 읽기 쉬워집니다.
  • 재사용성 증가: 한 번 정의한 위젯을 다른 화면이나 곳에서도 재사용할 수 있습니다.
  • 유지보수 용이성: 위젯이 작고 독립적이므로 버그 수정이나 새로운 기능 추가가 더 쉬워집니다.

이제 위젯을 분리하는 방법을 이해하셨을 거예요.

예시에서처럼 위젯을 작은 단위로 분리하고, 각 단위가 독립적으로 동작하도록 하면 앱의 구조가 더욱 효율적이고 깔끔해집니다.

 

구독!! 공감과 댓글,

광고 클릭은 저에게 큰 힘이 됩니다.

 

Starting Google Play App Distribution! "Tester Share" for Recruiting 20 Testers for a Closed Test.

 

Tester Share [테스터쉐어] - Google Play 앱

Tester Share로 Google Play 앱 등록을 단순화하세요.

play.google.com

 

728x90
반응형