FutureBuilder와 StreamBuilder의 차이점

pharmDev·2024년 12월 19일

FutureBuilder와 StreamBuilder의 차이점

FutureBuilderStreamBuilder는 Flutter에서 비동기 데이터를 UI로 렌더링하기 위해 사용됩니다. 주로 데이터의 업데이트 빈도와 지속성에 따라 선택됩니다.


FutureBuilder

특징

  • 1회성 비동기 작업의 결과를 처리.
  • 데이터가 로드된 이후에는 상태가 갱신되지 않음.
  • 예를 들어, 데이터베이스에서 데이터를 한 번 읽어오거나, API 호출을 통해 데이터를 가져올 때 사용.

사용 사례

  • 일정 추가 시 한 번만 데이터를 불러와야 하는 경우.
  • 특정 날짜의 데이터를 로드할 때.

예제

아래는 setState와 함께 사용하는 FutureBuilder를 기반으로 작성한 예제입니다:

FutureBuilder<List<ScheduleTableData>>(
  future: GetIt.I<AppDatabase>().getSchedules(selectedDay), // 한 번 데이터를 가져옴
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return Center(
        child: CircularProgressIndicator(), // 로딩 중 표시
      );
    }

    if (snapshot.hasError) {
      return Center(
        child: Text('오류 발생: ${snapshot.error}'),
      );
    }

    final schedules = snapshot.data ?? []; // 데이터 로드 완료

    return ListView.builder(
      itemCount: schedules.length,
      itemBuilder: (context, index) {
        final schedule = schedules[index];

        return Dismissible(
          key: ObjectKey(schedule.id),
          direction: DismissDirection.endToStart,
          onDismissed: (DismissDirection direction) {
            GetIt.I<AppDatabase>().removeSchedule(schedule.id);
            setState(() {}); // FutureBuilder를 다시 실행하여 UI 갱신
          },
          child: ScheduleCard(
            startTime: schedule.startTime,
            endTime: schedule.endTime,
            content: schedule.content,
            color: Color(int.parse('FF${schedule.color}', radix: 16)),
          ),
        );
      },
    );
  },
);

StreamBuilder

특징

  • 지속적으로 업데이트되는 데이터 흐름(Stream)을 감시.
  • 데이터가 변경될 때마다 UI가 자동으로 갱신.
  • 예를 들어, 데이터베이스의 실시간 변경 사항을 반영하거나, WebSocket에서 데이터를 수신할 때 사용.

사용 사례

  • 실시간으로 변경되는 일정 데이터를 표시해야 할 때.
  • 특정 날짜의 일정이 추가, 수정, 삭제될 때 자동으로 UI를 갱신해야 하는 경우.

예제

아래는 confirmDismiss와 함께 사용하는 StreamBuilder를 기반으로 작성한 예제입니다:

StreamBuilder<List<ScheduleTableData>>(
  stream: GetIt.I<AppDatabase>().streamSchedules(selectedDay), // 지속적으로 데이터를 감시
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return Center(
        child: CircularProgressIndicator(), // 로딩 중 표시
      );
    }

    if (snapshot.hasError) {
      return Center(
        child: Text('오류 발생: ${snapshot.error}'),
      );
    }

    final schedules = snapshot.data ?? []; // 실시간 데이터 반영

    return ListView.builder(
      itemCount: schedules.length,
      itemBuilder: (context, index) {
        final schedule = schedules[index];

        return Dismissible(
          key: ObjectKey(schedule.id),
          direction: DismissDirection.endToStart,
          confirmDismiss: (DismissDirection direction) async {
            final confirm = await showDialog<bool>(
              context: context,
              builder: (context) => AlertDialog(
                title: Text('삭제 확인'),
                content: Text('정말로 삭제하시겠습니까?'),
                actions: [
                  TextButton(
                    onPressed: () => Navigator.of(context).pop(false),
                    child: Text('취소'),
                  ),
                  TextButton(
                    onPressed: () => Navigator.of(context).pop(true),
                    child: Text('삭제'),
                  ),
                ],
              ),
            );

            if (confirm == true) {
              await GetIt.I<AppDatabase>().removeSchedule(schedule.id);
              return true; // 삭제 확정
            }

            return false; // 삭제 취소
          },
          child: ScheduleCard(
            startTime: schedule.startTime,
            endTime: schedule.endTime,
            content: schedule.content,
            color: Color(int.parse('FF${schedule.color}', radix: 16)),
          ),
        );
      },
    );
  },
);

FutureBuilder와 StreamBuilder를 각각 SetState, OnDismissed, ConfirmDismiss와 함께 사용하는 상황

1. FutureBuilder + SetState

  • 상황: 1회성 데이터를 로드하고, 삭제 후 UI를 갱신할 때.
  • 설명: 삭제 후 setState를 호출해 FutureBuilder를 다시 실행합니다.

2. FutureBuilder + OnDismissed

  • 상황: 데이터가 삭제되면 화면에서 즉시 제거해야 할 때.
  • 설명: 삭제 작업 후 FutureBuilder에서 데이터를 다시 불러옵니다.
  • 단점: 삭제 작업이 비동기적으로 완료되기 전에 UI를 변경하면 불일치 오류가 발생할 수 있습니다.

3. StreamBuilder + SetState

  • 상황: 실시간 데이터를 UI에 반영하되, 추가적인 상태 변경이 필요한 경우.
  • 설명: StreamBuilder 자체가 데이터를 감시하므로 setState 호출은 드물게 사용됩니다.

4. StreamBuilder + ConfirmDismiss

  • 상황: 삭제 확인 단계를 추가해야 하면서, 삭제 후 실시간으로 UI를 갱신해야 할 때.
  • 설명: StreamBuilder는 데이터 변경 사항을 자동으로 반영하므로 UI 갱신을 위한 추가 작업이 필요 없습니다.

결론

  1. FutureBuilder1회성 작업(예: 데이터 초기 로드)에 적합하며, 데이터가 삭제되거나 변경될 때마다 다시 호출해야 합니다.
  2. StreamBuilder실시간 데이터 흐름(예: 일정 추가/삭제)에 적합하며, 데이터 변경 시 UI가 자동으로 갱신됩니다.
  3. SetState, OnDismissed, ConfirmDismiss는 데이터의 변경(예: 삭제)을 처리하는 방식에 따라 각각 사용되며, StreamBuilder와 함께 사용할 경우 UI 갱신이 자동으로 이루어지므로 setState의 필요성이 줄어듭니다.

예제를 통해 상황에 맞는 도구를 적절히 사용하세요! 🚀

profile
코딩을 배우는 초보

0개의 댓글