Flutter 화면 전환 방법: Navigator와 PageRouteBuilder 비교

Flutter 화면 전환 방법은 Navigator와 PageRouteBuilder가 있습니다. 이 둘은 플러터(Flutter) 앱 개발에서 자주 사용되는 화면 전환 방법으로, 각각의 장단점이 있습니다. 이번 글에서는 이 두 방법을 비교하고, 어떤 상황에서 각각을 사용하는 것이 좋을지를 작성해 보겠습니다.

Navigator는 Flutter에서 가장 기본적이고 직관적인 화면 전환 도구입니다. Navigator.push와 Navigator.pop 같은 메서드를 사용하여 새로운 화면으로 이동하거나 이전 화면으로 돌아갈 수 있습니다.

장점

  • 간단함과 직관성: 몇 줄의 코드로 새로운 화면을 표시하거나 현재 화면을 스택에서 제거할 수 있습니다.
  • 통합성: Flutter의 기본 라우팅 메커니즘과 잘 통합되어 있어, 대부분의 개발자에게 친숙합니다.

단점

  • 한계된 사용자 정의: 복잡한 화면 전환과 사용자 정의 애니메이션을 구현하기 어려울 수 있습니다.
  • 관리 복잡성: 큰 규모의 앱에서 라우트 관리가 복잡해질 수 있습니다.

예제 코드

Navigator.push 메서드를 사용하여 MaterialPageRoute를 통해 화면 전환을 구현할 수 있습니다. 이는 Flutter의 기본 전환 애니메이션을 사용합니다. 아래 코드는 Navigator를 사용하여 두 번째 화면으로 전환하는 방법을 보여줍니다. 이제 Navigator.push를 호출하여 SecondScreen으로 이동합니다.

import 'package:flutter/material.dart';
import 'second_screen.dart';

// 앱의 시작점입니다. Flutter 앱은 main 함수에서 시작합니다.
void main() {
  // MaterialApp 위젯을 실행합니다. 이것은 Material Design 앱을 생성합니다.
  runApp(MaterialApp(
    title: 'Custom Route Transition', // 앱의 제목을 정의합니다. 시스템 태스크 관리자에서 사용됩니다.
    home: FirstScreen(), // 앱이 시작될 때 표시될 첫 번째 화면을 정의합니다.
  ));
}

// 첫 번째 화면을 정의하는 StatelessWidget 클래스입니다.
class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Scaffold는 Material Design의 기본 레이아웃 위젯입니다.
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'), // 앱 바의 제목을 설정합니다.
      ),
      body: Center(
        // ElevatedButton은 누르면 높아지는 효과가 있는 버튼 위젯입니다.
        child: ElevatedButton(
          child: Text('Go to Second Screen'), // 버튼의 텍스트를 정의합니다.
          onPressed: () {
            // Navigator.push를 사용하여 SecondScreen으로 화면 전환을 수행합니다.
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondScreen()), // 라우트를 생성하여 SecondScreen을 로드합니다.
            );
          },
        ),
      ),
    );
  }
}

SecondScreen 클래스에 Navigator.pop을 사용하여 현재 화면(두 번째 화면)에서 이전 화면으로 돌아가는 기능을 추가하는 코드 예시입니다. Navigator.pop 메소드는 스택에서 현재 경로를 제거하여 이전 화면으로 사용자를 되돌려 보냅니다. 아래 코드에서는 ElevatedButton을 추가하여 사용자가 버튼을 클릭하면 이전 화면으로 돌아갈 수 있도록 구현합니다.

import 'package:flutter/material.dart';

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Screen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Welcome to the Second Screen!'),
            SizedBox(height: 20), // 버튼과 텍스트 사이의 간격을 추가합니다.
            ElevatedButton(
              // 버튼을 클릭하면 이전 화면으로 돌아갑니다.
              onPressed: () {
                Navigator.pop(context);
              },
              child: Text('Go back'),
            ),
          ],
        ),
      ),
    );
  }
}

PageRouteBuilder 사용하기

PageRouteBuilder는 더 세밀한 화면 전환 애니메이션을 구현할 수 있게 해주는 도구입니다. 개발자는 전환 애니메이션의 모든 측면을 제어할 수 있으며, 화면 간의 전환을 완전히 사용자 정의할 수 있습니다.

장점

  • 고도의 사용자 정의: 복잡한 애니메이션과 화면 전환을 자유롭게 구현할 수 있습니다.
  • 세밀한 제어: 전환의 모든 세부 사항을 개발자가 직접 제어할 수 있습니다.

단점

  • 구현 복잡성: Navigator에 비해 구현이 복잡하며, 세부적인 애니메이션 구현에 시간이 더 소요될 수 있습니다.
  • 코드 관리: 코드가 길어지고 복잡해져 관리가 어려워질 수 있습니다.

예제 코드

GPT PageRouteBuilder를 사용하는 것은 Flutter에서 사용자 정의 페이지 전환을 만들 때 매우 유용합니다. 이를 사용하면 표준 전환 대신 자신만의 전환 애니메이션을 만들 수 있습니다. 다음은 PageRouteBuilder를 사용하여 새로운 화면으로 전환하는 기본 예제입니다. 이 예제에서는 첫 번째 화면에서 버튼을 누를 때 페이드 인(fade-in) 효과를 사용하여 두 번째 화면으로 전환합니다.

import 'package:flutter/material.dart';
import 'second_screen.dart';

// main 함수는 모든 Flutter 앱의 진입점입니다.
void main() {
  // MaterialApp 위젯을 실행하여 머티리얼 디자인이 적용된 앱을 시작합니다.
  runApp(MaterialApp(
    home: FirstScreen(), // 앱에서 처음으로 표시되는 화면을 설정합니다.
  ));
}

// 첫 번째 화면을 위한 상태 없는 위젯을 정의합니다.
class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Scaffold는 화면 레이아웃의 고급 구조를 제공합니다.
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'), // AppBar의 제목입니다.
      ),
      body: Center(
        // 버튼을 화면 중앙에 배치하기 위한 Center 위젯입니다.
        child: ElevatedButton(
          child: Text('Go to Second Screen with Fade Transition'),
          onPressed: () {
            // _createRoute()로 정의된 새로운 경로를 Navigator를 사용하여 푸시합니다.
            Navigator.of(context).push(_createRoute());
          },
        ),
      ),
    );
  }

  // 사용자 정의 라우트 전환을 정의하기 위한 메소드입니다.
  Route _createRoute() {
    // 페이지 전환을 사용자 정의하기 위해 PageRouteBuilder를 사용합니다.
    return PageRouteBuilder(
      pageBuilder: (context, animation, secondaryAnimation) => SecondScreen(), // 네비게이션 할 페이지입니다.
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        // 페이드 전환의 시작점과 끝점을 정의합니다.
        var begin = 0.0;
        var end = 1.0;
        var tween = Tween(begin: begin, end: end); // 페이드 효과를 위한 트윈입니다.
        var fadeAnimation = animation.drive(tween); // 트윈에 의해 구동되는 애니메이션입니다.

        // 자식 위젯에 페이드 효과를 적용하기 위한 FadeTransition 위젯입니다.
        return FadeTransition(
          opacity: fadeAnimation, // 페이드 애니메이션을 적용합니다.
          child: child, // 전환을 겪을 자식 위젯입니다.
        );
      },
    );
  }
}

ElevatedButton의 onPressed 콜백에서 Navigator.pop(context)를 호출함으로써, 현재 화면(SecondScreen)을 닫고 이전 화면으로 돌아갈 수 있게 합니다. 이 로직은 PageRouteBuilder를 사용하여 SecondScreen을 열었을 때도 동일하게 작동합니다.

import 'package:flutter/material.dart';

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Screen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Welcome to the Second Screen!'),
            SizedBox(height: 20), // 버튼과 텍스트 사이의 간격을 추가합니다.
            ElevatedButton(
              // 버튼을 클릭하면 이전 화면으로 돌아갑니다.
              onPressed: () {
                Navigator.pop(context);
              },
              child: Text('Go back'),
            ),
          ],
        ),
      ),
    );
  }
}

마무리

화면 전환 방식의 선택은 앱의 요구 사항과 개발자의 선호도에 따라 달라집니다. 간단한 화면 전환을 원한다면 Navigator가 가장 좋은 선택일 수 있습니다. 반면, 복잡한 사용자 정의 애니메이션이나 세밀한 화면 전환 제어가 필요한 경우 PageRouteBuilder를 사용하는 것이 바람직할 수 있습니다.

Leave a Comment