Flutter 동적 페이지 라우팅하기

Flutter의 라우팅은 앱의 탐색 흐름을 관리하는 메커니즘입니다. 라우팅을 통해 사용자는 한 화면에서 다른 화면으로 이동하여 애플리케이션의 여러 부분과 상호 작용할 수 있습니다.

그러나 여기서 말하는 동적 페이지는 페이지에 표시되는 콘텐츠나 데이터가 하드코딩되거나 정적이 아니라 사용자 입력, API 또는 기타 소스의 데이터를 기반으로 즉석에서 생성되는 것을 의미합니다.

간단한 예를 들어볼게요.

Flutter 동적 페이지 라우팅하기

이 이미지에는 세 개의 화면이 있습니다.

👉 온보딩 페이지
👉 홈 페이지: 제품(운동화) 목록 표시
👉 세부 정보 페이지: 각 세부 정보에 대한 추가 정보 포함


각 화면의 흐름 주기는 어떻게 되나요?

사용자는 온보딩 페이지에서 화면을 슬라이드하여 홈 페이지로 이동합니다. 사용자가 제품을 클릭하면 세부 정보 페이지로 이동합니다. 다음은 라우팅에 대한 간단한 설명입니다. 라우팅은 앱의 전체 수명 주기를 정의하므로 애플리케이션을 빌드하기 전에 시간을 내어 워크플로를 적절히 계획해야 합니다. 돈을 받지 못하고 식료품과 떠다니는 딸기만 먹게 될 것이 아니라면 말이죠.

그렇다면 집에 약 100개의 제품이 있고 각 제품에 대한 세부 정보 페이지를 만들고 싶다면 100개의 다트 파일을 만들어야 할까요? No! 사용되거나 호출될 때마다 UI를 업데이트하는 동적 매개변수가 있는 동적 화면을 만들면 됩니다.

아래 내용에서 말씀드린 작업을 수행하는 방법을 보여드릴게요.


Flutter 프로젝트 생성하기

새로운 Flutter 프로젝트를 생성해 보겠습니다.

flutter create e_commerce app

"제품" 목록을 처리하는 클래스를 만들어 보겠습니다.

Class Products {
  final String image;
  final String name;
  final String description;
  final double price;
  double rating;

  Products({
    required this.image,
    required this.name,
    required this.description,
    required this.price,
    this.rating = 0.0,
  });
}

제품 클래스를 UI에 사용해보면 이런 코드가 나오겠네요.

import 'package:flutter/material.dart';

class ECommerceApp extends StatelessWidget {
  final List & gt;
  Products & lt;
  productList = [
    Products(
      image: 'https://example.com/product1-image.png',
      name: 'Product 1',
      description: 'Description of Product 1',
      price: 29.99,
      rating: 4.2,
    ),
    Products(
      image: 'https://example.com/product2-image.png',
      name: 'Product 2',
      description: 'Description of Product 2',
      price: 49.99,
      rating: 3.8,
    ),
    Products(
      image: 'https://example.com/product3-image.png',
      name: 'Product 3',
      description: 'Description of Product 3',
      price: 19.99,
      rating: 4.5,
    ),
    Products(
      image: 'https://example.com/product4-image.png',
      name: 'Product 4',
      description: 'Description of Product 4',
      price: 39.99,
      rating: 4.0,
    ),
    Products(
      image: 'https://example.com/product5-image.png',
      name: 'Product 5',
      description: 'Description of Product 5',
      price: 59.99,
      rating: 4.8,
    ),
  ];

  @override
  Widget build(BuildContext context) {
      ...

이 위젯은 앞서 만든 제품 클래스에서 제품 목록을 가져오는 기본 상태 비저장 위젯입니다. 프로퍼티를 원하는 대로 조정할 수 있습니다.

return Scaffold(
  appBar: AppBar(title: Text('E-Commerce App')),
  body: ListView.builder(
    scrollDirection: Axis.horizontal,
    itemCount: productList.length,
    itemBuilder: (context, index) {
      final product = productList[index];
      return ListTile(
        leading: Image.network(product.image),
        title: Text(product.name),
        subtitle: Text(product.description),
        trailing: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            Text('\$${product.price.toStringAsFixed(2)}'),
            Text('Rating: ${product.rating}'),
          ],
        ),
      );
    },
  ),
);

여기서는 Scaffold 방향이 가로인 목록 뷰를 만들었는데, 이 목록 뷰에는 제품 이름을 제목으로 하는 목록 제목과 다른 속성 중 제품의 이미지가 있습니다. 플러터 엔지니어의 임무는 사용자가 제품만 볼 수 있는 것이 아니라 각 항목을 클릭하면 각 화면에 대한 전체 설명을 제공하는 다른 페이지로 이동할 수 있도록 하는 것입니다.

코드를 다시 작성하지 않고, 어떻게 동적 작업을 수행할까요?

UI와 관련된 모든 업데이트와 로직을 처리하는 하나의 화면만 만들면 됩니다. 그것을 위해 제품 세부 정보 화면을 나타내는 새 Dart 파일을 만듭니다. 이 파일의 이름을 product_details_screen.dart로 지정합니다. 이 화면에는 선택한 제품의 세부 정보가 표시됩니다.

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

class ProductDetailsScreen extends StatelessWidget {
  final Products product;

  ProductDetailsScreen({
    required this.product
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(product.name),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Image.network(
              product.image,
              height: 200,
              width: 200,
              fit: BoxFit.cover,
            ),
            SizedBox(height: 20),
            Text(
              'Description: ${product.description}',
              style: TextStyle(fontSize: 18),
            ),
            SizedBox(height: 10),
            Text(
              'Price: \$${product.price.toStringAsFixed(2)}',
              style: TextStyle(fontSize: 18),
            ),
            SizedBox(height: 10),
            Text(
              'Rating: ${product.rating}',
              style: TextStyle(fontSize: 18),
            ),
          ],
        ),
      ),
    );
  }
}

메인 화면을 업데이트합니다: 메인 화면(ECommerceApp)에서 제품을 클릭할 때 탭 이벤트를 처리하고 제품 세부 정보 화면으로 이동하도록 ListTile 위젯을 GestureDetector로 래핑합니다.

class ECommerceApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('E-Commerce App')),
      body: Container(
        height: 200,
        child: ListView.builder(
          scrollDirection: Axis.horizontal,
          itemCount: productList.length,
          itemBuilder: (context, index) {
            final product = productList[index];
            return GestureDetector(
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => ProductDetailsScreen(product: product),
                  ),
                );
              },
              child: ListTile(
                leading: Image.network(product.image),
                title: Text(product.name),
                subtitle: Text(product.description),
                trailing: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    Text('\$${product.price.toStringAsFixed(2)}'),
                    Text('Rating: ${product.rating}'),
                  ],
                ),
              );
            );
          },
        ),
      ),
    );
  }
}

이제 사용자가 제품을 탭하면 onTap 이벤트가 트리거되고, 해당 제품 데이터가 전달된 제품 세부 정보 화면(ProductDetailsScreen)으로 사용자를 안내합니다.

이렇게 하면 UI의 모든 업데이트를 처리하는 하나의 화면만 생성하여 시간을 절약할 수 있습니다.
Previous Post Next Post