---
title: Flutter 앱에서 Parse 객체 기본 CRUD 작업 실행 방법
slug: docs-kr/flutter/parse-sdk/data-objects/flutter-crud
description: Flutter와 Back4App으로 Parse 객체 생성, 읽기, 업데이트, 삭제 구현
image: https://www.back4app.com/images/logo-social.png
createdAt: 2024-03-15T13:21:54.274Z
---

이 가이드는 Flutter 플러그인을 사용하여 Back4App에서 Parse 객체를 관리하는 방법을 보여줍니다. 기본 CRUD 작업인 생성, 읽기, 업데이트 및 삭제를 배우게 됩니다. 이 튜토리얼은 이러한 작업을 설명하기 위해 간단한 ToDo 앱을 사용합니다.

Back4app 백엔드 데이터 저장소는 `ParseObject`, JSON 호환 데이터의 키-값 쌍을 보유합니다. Back4App 데이터 저장소는 문자열, 숫자, 불리언, DateTime, GeoPoints, Pointers, Relations, 리스트 및 객체를 포함한 다양한 일반 데이터 유형을 수용합니다. 본질적으로 JSON 형식으로 인코딩할 수 있는 모든 데이터를 지원하여 다양한 데이터 저장 요구에 대한 유연하고 강력한 솔루션을 제공합니다.

## 필수 조건

이 튜토리얼을 완료하려면 다음이 필요합니다:

:::hint{type="info"}
- Flutter 버전 3.x.x 이상
- [Android Studio ](https://developer.android.com/studio) 또는 [VS Code 설치](https://code.visualstudio.com/) (과 [플러그인](https://docs.flutter.dev/get-started/editor) Dart 및 Flutter)
- Back4App에서 [생성된](https://www.back4app.com/docs/get-started/new-parse-app) 앱:
  - **참고:&#x20;**&#x20;[새 Parse 앱 튜토리얼](https://www.back4app.com/docs/get-started/new-parse-app)을 따라 Back4App에서 Parse 앱을 만드는 방법을 배우세요.
- Back4app에 연결된 Flutter 앱.
  - **참고:&#x20;**&#x20;[Flutter 프로젝트에 Parse SDK 설치](https://www.back4app.com/docs/flutter/parse-sdk/parse-flutter-sdk)을 따라 Back4App에 연결된 Flutter 프로젝트를 만드세요.
- Android 또는 iOS를 실행하는 장치(또는 가상 장치).
:::

## 1. 객체 생성

저장할 `saveTodo` 함수는 제목과 `done` 상태가 false로 설정된 새로운 작업을 생성합니다. 작동 방식은 다음과 같습니다:

1. **속성을 설정하여 Parse 객체 초기화**: `ParseObject`의 인스턴스를 생성합니다(예: 'Todo'). `set` 메서드를 사용하여 키-값 쌍을 정의합니다.
2. **객체 저장**: `save` 메서드를 호출하여 객체를 데이터베이스에 저장합니다.

```dart
Future<void> saveTodo(String title) async {
  final todo = ParseObject('Todo')
    ..set('title', title)
    ..set('done', false);
  await todo.save();
}
```

## 2. 객체 읽기

getTodo 함수는 데이터베이스를 쿼리하고 작업 목록을 반환합니다. 작동 방식은 다음과 같습니다:

1. **쿼리 초기화**: 클래스에 대한 QueryBuilder 인스턴스를 생성합니다.
2. **쿼리 실행**: query 메서드를 사용하여 데이터를 검색합니다.
3. **응답 처리**: 쿼리가 성공했는지 확인하고 결과를 처리합니다.

```dart
Future<List<ParseObject>> getTodo() async {
  QueryBuilder<ParseObject> queryTodo =
      QueryBuilder<ParseObject>(ParseObject('Todo'));
  final ParseResponse apiResponse = await queryTodo.query();

  if (apiResponse.success && apiResponse.results != null) {
    return apiResponse.results as List<ParseObject>;
  } else {
    return [];
  }
}
```

ListView\.builder 함수를 업데이트하여 Parse 객체 값을 추출하고 표시합니다:

```dart
// Get Parse Object Values
final varTodo = snapshot.data![index];
final varTitle = varTodo.get<String>('title')!;
final varDone = varTodo.get<bool>('done')!;
```

## 3. 객체 업데이트

업데이트 `updateTodo` 함수는 기존 작업의 상태를 업데이트합니다. 작동 방식은 다음과 같습니다:

1. **Parse 객체 초기화 및 속성 설정**: `ParseObject`의 인스턴스를 생성하고 `objectId`를 설정합니다. `set` 메서드를 사용하여 키-값 쌍을 업데이트합니다.
2. **객체 저장**: `save` 메서드를 호출하여 데이터베이스에서 객체를 업데이트합니다.

```dart
Future<void> updateTodo(String id, bool done) async {
  var todo = ParseObject('Todo')
    ..objectId = id
    ..set('done', done);
  await todo.save();
}
```

## 4. 객체 삭제

삭제 `deleteTodo` 함수는 데이터베이스에서 기존 작업을 제거합니다. 작동 방식은 다음과 같습니다:

1. **Parse 객체 초기화**: `ParseObject`의 인스턴스를 생성하고 `objectId`를 설정합니다.
2. **객체 삭제**: `delete` 메서드를 호출하여 데이터베이스에서 객체를 제거합니다.

```dart
Future<void> deleteTodo(String id) async {
  var todo = ParseObject('Todo')..objectId = id;
  await todo.delete();
}
```

## 전체 예제 코드

여기 Back4app 백엔드와 통합된 간단한 ToDo 앱의 전체 코드가 있습니다.

```dart
import 'package:flutter/material.dart';
import 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  const keyApplicationId = 'YOUR_APP_ID_HERE';
  const keyClientKey = 'YOUR_CLIENT_KEY_HERE';
  const keyParseServerUrl = 'https://parseapi.back4app.com';

  await Parse().initialize(keyApplicationId, keyParseServerUrl,
      clientKey: keyClientKey, autoSendSessionId: true);

  runApp(const MaterialApp(home: TodoApp()));
}

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

  @override
  // ignore: library_private_types_in_public_api
  _TodoAppState createState() => _TodoAppState();
}

class _TodoAppState extends State<TodoApp> {
  List<ParseObject> tasks = [];
  TextEditingController taskController = TextEditingController();

  @override
  void initState() {
    super.initState();
    getTodo();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
          primaryColor: Colors.white,
          hintColor: Colors.black,
          scaffoldBackgroundColor: Colors.white,
          appBarTheme:
              AppBarTheme(backgroundColor: Color.fromARGB(255, 68, 122, 246))),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Todo List'),
        ),
        body: Container(
          decoration: BoxDecoration(
            border: Border.all(color: Colors.black),
          ),
          child: Column(
            children: [
              const SizedBox(height: 20),
              _buildTaskInput(),
              const SizedBox(height: 20),
              Expanded(child: _buildTaskList()),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildTaskInput() {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 20),
      child: Row(
        children: [
          Expanded(
            child: TextField(
              controller: taskController,
              decoration: InputDecoration(
                hintText: 'Enter tasks',
                filled: true,
                fillColor: Colors.grey[200],
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(8),
                  borderSide: BorderSide.none,
                ),
              ),
            ),
          ),
          const SizedBox(width: 10),
          ElevatedButton(
            onPressed: addTodo,
            style: ButtonStyle(
                foregroundColor:
                    MaterialStateProperty.all<Color>(Colors.black)),
            child: const Text('Add'),
          ),
        ],
      ),
    );
  }

  Widget _buildTaskList() {
    return ListView.builder(
      itemCount: tasks.length,
      itemBuilder: (context, index) {
        final varTodo = tasks[index];
        final varTitle = varTodo.get<String>('title') ?? '';
        bool done = varTodo.get<bool>('done') ?? false;

        return ListTile(
          title: Row(
            children: [
              Checkbox(
                value: done,
                onChanged: (newValue) {
                  updateTodo(index, newValue!);
                },
              ),
              Expanded(child: Text(varTitle)),
            ],
          ),
          trailing: IconButton(
            icon: const Icon(Icons.delete),
            onPressed: () {
              deleteTodo(index, varTodo.objectId!);
            },
          ),
        );
      },
    );
  }

  Future<void> addTodo() async {
    String task = taskController.text.trim();
    if (task.isNotEmpty) {
      var todo = ParseObject('Todo')
        ..set('title', task)
        ..set('done', false);

      var response = await todo.save();

      if (response.success) {
        setState(() {
          tasks.add(todo);
        });
        taskController.clear();
      } else {
        // Handle error
      }
    }
  }

  Future<void> updateTodo(int index, bool done) async {
    final varTodo = tasks[index];
    final String id = varTodo.objectId.toString();

    var todo = ParseObject('Todo')
      ..objectId = id
      ..set('done', done);

    var response = await todo.save();

    if (response.success) {
      setState(() {
        tasks[index] = todo;
      });
    } else {
      // Handle error
    }
  }

  Future<void> getTodo() async {
    var queryBuilder = QueryBuilder<ParseObject>(ParseObject('Todo'));
    var apiResponse = await queryBuilder.query();

    if (apiResponse.success && apiResponse.results != null) {
      setState(() {
        tasks = apiResponse.results as List<ParseObject>;
      });
    } else {
      // Handle error
    }
  }

  Future<void> deleteTodo(int index, String id) async {
    var todo = ParseObject('Todo')..objectId = id;
    var response = await todo.delete();

    if (response.success) {
      setState(() {
        tasks.removeAt(index);
      });
    } else {
      // Handle error
    }
  }
}
```

### 당신의 앱은 다음과 같아야 합니다:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/3advq0EwgQpAeq8ii9lp3_3kcgbfecvvb2myngt1ttp-image.jpg" size="40" width="800" height="1730" position="center" showCaption="false"}

## 결론

이제 Back4App에서 Parse를 사용하여 Flutter 앱에서 기본 CRUD 작업을 구현했습니다. 이 튜토리얼에서는 ToDo 앱에서 작업을 추가, 검색, 업데이트 및 삭제하는 방법을 보여주었습니다.

