React와 Parse로 데이터 쿼리 수행하기 - 개발자 가이드
React에서 Parse를 사용한 쿼리
소개
이 가이드에서는 Parse에서 기본 쿼리를 수행하고 이러한 쿼리를 사용하여 React 컴포넌트를 구현합니다. Back4App과 React를 사용하여 현실적인 데이터를 설정하고 쿼리하는 방법을 배웁니다.
전제 조건
이 튜토리얼을 완료하려면 다음이 필요합니다:
- 이 가이드의 예제 프로젝트를 실행하려면 Ant Design 라이브러리를 설정해야 합니다.
목표
React 애플리케이션에서 Back4App에 저장된 데이터를 쿼리합니다.
1 - Parse.Query 클래스 이해하기
모든 Parse 쿼리 작업은 Parse.Query 객체 유형을 사용하며, 이는 앱 전반에 걸쳐 데이터베이스에서 특정 데이터를 검색하는 데 도움이 됩니다. Parse.Query는 retrieve 메서드(예: Parse.Query.find 또는 Parse.Query.get 호출 후에만 해결되므로, 쿼리를 설정하고 실제로 호출되기 전에 여러 수정자를 연결할 수 있습니다.
새로운 Parse.Query, 원하는 Parse.Object 서브클래스를 매개변수로 전달해야 합니다. 이 서브클래스는 쿼리 결과를 포함하게 됩니다. 아래에서 볼 수 있는 예제 쿼리에서는 가상의 Profile 서브클래스가 쿼리되고 있습니다.
1 // This will create your query
2 let parseQuery = new Parse.Query("Profile");
3 // The query will resolve only after calling this method
4 let queryResult = await parseQuery.find();다음에 대한 자세한 내용을 읽을 수 있습니다 Parse.Query 클래스 공식 문서에서 여기.
2 - Back4App에 데이터 저장하기
이 가이드에서 쿼리의 대상이 될 Profile 클래스를 생성해 보겠습니다. Parse JS 콘솔에서는 JavaScript 코드를 직접 실행하여 JS SDK 명령을 사용하여 애플리케이션 데이터베이스 내용을 쿼리하고 업데이트할 수 있습니다. 아래 코드를 JS 콘솔에서 실행하고 Back4App에 데이터를 삽입하세요.
대시보드에서 JS 콘솔이 어떻게 보이는지 확인해 보세요:

사용자 프로필 클래스를 다음 예제 내용으로 생성하세요:
1 // Add Profile objects and create table
2 // Adam Sandler
3 let Profile = new Parse.Object('Profile');
4 Profile.set('name', 'Adam Sandler');
5 Profile.set('birthDay', new Date('09/09/1966'));
6 Profile.set('friendCount', 2);
7 Profile.set('favoriteFoods', ['Lobster', 'Bread']);
8 await Profile.save();
9
10 // Adam Levine
11 Profile = new Parse.Object('Profile');
12 Profile.set('name', 'Adam Levine');
13 Profile.set('birthDay', new Date('03/18/1979'));
14 Profile.set('friendCount', 52);
15 Profile.set('favoriteFoods', ['Cake', 'Bread']);
16 await Profile.save();
17
18 // Carson Kressley
19 Profile = new Parse.Object('Profile');
20 Profile.set('name', 'Carson Kressley');
21 Profile.set('birthDay', new Date('11/11/1969'));
22 Profile.set('friendCount', 12);
23 Profile.set('favoriteFoods', ['Fish', 'Cookies']);
24 await Profile.save();
25
26 // Dan Aykroyd
27 Profile = new Parse.Object('Profile');
28 Profile.set('name', 'Dan Aykroyd');
29 Profile.set('birthDay', new Date('07/01/1952'));
30 Profile.set('friendCount', 66);
31 Profile.set('favoriteFoods', ['Jam', 'Peanut Butter']);
32 await Profile.save();
33
34 // Eddie Murphy
35 Profile = new Parse.Object('Profile');
36 Profile.set('name', 'Eddie Murphy');
37 Profile.set('birthDay', new Date('04/03/1961'));
38 Profile.set('friendCount', 49);
39 Profile.set('favoriteFoods', ['Lettuce', 'Pepper']);
40 await Profile.save();
41
42 // Fergie
43 Profile = new Parse.Object('Profile');
44 Profile.set('name', 'Fergie');
45 Profile.set('birthDay', new Date('03/27/1975'));
46 Profile.set('friendCount', 55);
47 Profile.set('favoriteFoods', ['Lobster', 'Shrimp']);
48 await Profile.save();
49
50 console.log('Success!');3 - 데이터 쿼리하기
이제 클래스가 채워졌으므로, 기본 쿼리를 수행할 수 있습니다. 이름으로 결과를 필터링하는 것부터 시작해 보겠습니다. 이는 문자열 유형 필드로, 프로필 이름이 포함된 값을 검색합니다. 아담 을(를) 사용하여 Parse.Query.contains 메서드를 사용합니다:
1 // Create your query
2 let parseQuery = new Parse.Query('Profile');
3
4 // `contains` is a basic query method that checks if string field
5 // contains a specific substring
6 parseQuery.contains('name', 'Adam');
7
8 // The query will resolve only after calling this method, retrieving
9 // an array of `Parse.Objects`
10 let queryResults = await parseQuery.find();
11
12 // Let's show the results
13 for (let result of queryResults) {
14 // You access `Parse.Objects` attributes by using `.get`
15 console.log(result.get('name'));
16 };이제 숫자 유형 필드로 쿼리해 보겠습니다. friendCount 를 사용하여 또 다른 일반 쿼리 메서드인 Parse.Query.greaterThan. 이 경우, 친구 수가 20보다 많은 프로필 을(를) 원합니다.
1 // Create your query
2 let parseQuery = new Parse.Query('Profile');
3
4 // `greaterThan` is a basic query method that does what it
5 // says on the tin
6 parseQuery.greaterThan('friendCount', 20);
7
8 // The query will resolve only after calling this method, retrieving
9 // an array of `Parse.Objects`
10 let queryResults = await parseQuery.find();
11
12 // Let's show the results
13 for (let result of queryResults) {
14 // You access `Parse.Objects` attributes by using `.get`
15 console.log(`name: ${result.get('name')}, friend count: ${result.get('friendCount')}`);
16 };다른 반복 쿼리 메서드는 Parse.Query.ascending 및 Parse.Query.descending, 쿼리를 정렬하는 역할을 합니다. 이 정렬은 대부분의 데이터 유형에서 수행할 수 있으므로, 날짜 필드 birthDay 를 기준으로 가장 어린 사람으로 쿼리를 정렬해 보겠습니다.
1 // Create your query
2 let parseQuery = new Parse.Query('Profile');
3
4 // `descending` and `ascending` can and should be chained
5 // with other query methods to improve your queries
6 parseQuery.descending('birthDay');
7
8 // The query will resolve only after calling this method, retrieving
9 // an array of `Parse.Objects`
10 let queryResults = await parseQuery.find();
11
12 // Let's show the results
13 for (let result of queryResults) {
14 // You access `Parse.Objects` attributes by using `.get`
15 console.log(`name: ${result.get('name')}, birthday: ${result.get('birthDay')}`);
16 };앞서 언급했듯이, 더 정교한 결과를 얻기 위해 쿼리 메서드를 연결할 수 있으며 연결해야 합니다. 그러면 이전 예제를 단일 쿼리 요청으로 결합해 보겠습니다:
1 // Create your query
2 let parseQuery = new Parse.Query('Profile');
3
4 parseQuery.contains('name', 'Adam');
5 parseQuery.greaterThan('friendCount', 20);
6 parseQuery.descending('birthDay');
7
8 // The query will resolve only after calling this method, retrieving
9 // an array of `Parse.Objects`
10 let queryResults = await parseQuery.find();
11
12 // Let's show the results
13 for (let result of queryResults) {
14 // You access `Parse.Objects` attributes by using `.get`
15 console.log(`name: ${result.get('name')}, friend count: ${result.get('friendCount')}, birthday: ${result.get('birthDay')}`);
16 };4 - React 컴포넌트에서 쿼리하기
이제 React의 컴포넌트 내에서 예제 쿼리를 사용해 보겠습니다. 결과를 보여주는 목록과 쿼리를 호출하기 위한 4개의 버튼이 있는 간단한 인터페이스를 가지고 있습니다. 컴포넌트 코드의 배치는 다음과 같으며, doQuery 함수가 포함되어 있으며, 이전의 예제 코드 형식을 포함하고 있습니다.
1 import React, { useState } from 'react';
2 import Parse from 'parse/dist/parse.min.js';
3 import './App.css';
4 import { Button, Divider } from 'antd';
5 import { CloseOutlined, SearchOutlined } from '@ant-design/icons';
6
7 export const QueryBasic = () => {
8 // State variable
9 const [queryResults, setQueryResults] = useState();
10
11 const doQueryByName = async function () {
12 // Create our Parse.Query instance so methods can be chained
13 // Reading parse objects is done by using Parse.Query
14 const parseQuery = new Parse.Query('Profile');
15
16 // `contains` is a basic query method that checks if string field
17 // contains a specific substring
18 parseQuery.contains('name', 'Adam');
19
20 try {
21 let profiles = await parseQuery.find();
22 setQueryResults(profiles);
23 return true;
24 } catch (error) {
25 // Error can be caused by lack of Internet connection
26 alert(`Error! ${error.message}`);
27 return false;
28 }
29 };
30
31 const doQueryByFriendCount = async function () {
32 // Create our Parse.Query instance so methods can be chained
33 // Reading parse objects is done by using Parse.Query
34 const parseQuery = new Parse.Query('Profile');
35
36 // `greaterThan` is a basic query method that does what it
37 // says on the tin
38 parseQuery.greaterThan('friendCount', 20);
39
40 try {
41 let profiles = await parseQuery.find();
42 setQueryResults(profiles);
43 return true;
44 } catch (error) {
45 // Error can be caused by lack of Internet connection
46 alert(`Error! ${error.message}`);
47 return false;
48 }
49 };
50
51 const doQueryByOrdering = async function () {
52 // Create our Parse.Query instance so methods can be chained
53 // Reading parse objects is done by using Parse.Query
54 const parseQuery = new Parse.Query('Profile');
55
56 // `descending` and `ascending` can and should be chained
57 // with other query methods to improve your queries
58 parseQuery.descending('birthDay');
59
60 try {
61 let profiles = await parseQuery.find();
62 setQueryResults(profiles);
63 return true;
64 } catch (error) {
65 // Error can be caused by lack of Internet connection
66 alert(`Error! ${error.message}`);
67 return false;
68 }
69 };
70
71 const doQueryByAll = async function () {
72 // Create our Parse.Query instance so methods can be chained
73 // Reading parse objects is done by using Parse.Query
74 const parseQuery = new Parse.Query('Profile');
75
76 parseQuery.contains('name', 'Adam');
77 parseQuery.greaterThan('friendCount', 20);
78 parseQuery.descending('birthDay');
79
80 try {
81 let profiles = await parseQuery.find();
82 setQueryResults(profiles);
83 return true;
84 } catch (error) {
85 // Error can be caused by lack of Internet connection
86 alert(`Error! ${error.message}`);
87 return false;
88 }
89 };
90
91 const clearQueryResults = async function () {
92 setQueryResults(undefined);
93 return true;
94 };
95
96 return (
97 <div>
98 <div className="header">
99 <img
100 className="header_logo"
101 alt="Back4App Logo"
102 src={
103 'https://blog.back4app.com/wp-content/uploads/2019/05/back4app-white-logo-500px.png'
104 }
105 />
106 <p className="header_text_bold">{'React on Back4App'}</p>
107 <p className="header_text">{'Basic Queries'}</p>
108 </div>
109 <div className="container">
110 <div className="flex_between">
111 <h2 className="heading">{'Query List'}</h2>
112 <div className="flex">
113 <Button
114 onClick={() => doQueryByName()}
115 type="primary"
116 className="heading_button"
117 color={'#208AEC'}
118 icon={<SearchOutlined />}
119 >
120 BY NAME
121 </Button>
122 <Button
123 onClick={() => doQueryByFriendCount()}
124 type="primary"
125 className="heading_button"
126 color={'#208AEC'}
127 icon={<SearchOutlined />}
128 >
129 BY FRIEND COUNT
130 </Button>
131 <Button
132 onClick={() => doQueryByOrdering()}
133 type="primary"
134 className="heading_button"
135 color={'#208AEC'}
136 icon={<SearchOutlined />}
137 >
138 BY ORDERING
139 </Button>
140 <Button
141 onClick={() => doQueryByAll()}
142 type="primary"
143 className="heading_button"
144 color={'#208AEC'}
145 icon={<SearchOutlined />}
146 >
147 BY ALL
148 </Button>
149 <Button
150 onClick={() => clearQueryResults()}
151 type="primary"
152 className="heading_button"
153 color={'#208AEC'}
154 icon={<CloseOutlined />}
155 >
156 CLEAR
157 </Button>
158 </div>
159 </div>
160 <Divider />
161 <div className="flex_between">
162 <div className="flex_child">
163 {/* Query list */}
164 {queryResults !== undefined &&
165 queryResults.map((profile, index) => (
166 <div className="list_item" key={`${index}`}>
167 <p className="list_item_title">{`${profile.get('name')}`}</p>
168 <p className="list_item_description">{`Friend count: ${profile.get(
169 'friendCount'
170 )}, Birthday: ${profile.get('birthDay')}`}</p>
171 </div>
172 ))}
173 {queryResults !== undefined && queryResults.length <= 0 ? (
174 <p>{'No results here!'}</p>
175 ) : null}
176 </div>
177 </div>
178 </div>
179 </div>
180 );
181 };다음 클래스를 App.css 파일에 추가하여 모든 인터페이스 요소를 올바르게 렌더링하세요:
1 html {
2 box-sizing: border-box;
3 outline: none;
4 overflow: auto;
5 }
6
7 *,
8 *:before,
9 *:after {
10 margin: 0;
11 padding: 0;
12 box-sizing: inherit;
13 }
14
15 h1,
16 h2,
17 h3,
18 h4,
19 h5,
20 h6 {
21 margin: 0;
22 font-weight: bold;
23 }
24
25 p {
26 margin: 0;
27 }
28
29 body {
30 margin: 0;
31 background-color: #fff;
32 }
33
34 .container {
35 width: 100%;
36 max-width: 900px;
37 margin: auto;
38 padding: 20px 0;
39 text-align: left;
40 }
41
42 .header {
43 align-items: center;
44 padding: 25px 0;
45 background-color: #208AEC;
46 }
47
48 .header_logo {
49 height: 55px;
50 margin-bottom: 20px;
51 object-fit: contain;
52 }
53
54 .header_text_bold {
55 margin-bottom: 3px;
56 color: rgba(255, 255, 255, 0.9);
57 font-size: 16px;
58 font-weight: bold;
59 }
60
61 .header_text {
62 color: rgba(255, 255, 255, 0.9);
63 font-size: 15px;
64 }
65
66 .heading {
67 font-size: 22px;
68 }
69
70 .flex {
71 display: flex;
72 }
73
74 .flex_between {
75 display: flex;
76 justify-content: space-between;
77 }
78
79 .flex_child {
80 flex: 0 0 45%;
81 }
82
83 .heading_button {
84 margin-left: 12px;
85 }
86
87 .list_item {
88 padding-bottom: 15px;
89 margin-bottom: 15px;
90 border-bottom: 1px solid rgba(0,0,0,0.06);
91 text-align: left;
92 }
93
94 .list_item_title {
95 color: rgba(0,0,0,0.87);
96 font-size: 17px;
97 }
98
99 .list_item_description {
100 color: rgba(0,0,0,0.5);
101 font-size: 15px;
102 }렌더링 및 모든 쿼리 함수로 쿼리한 후 구성 요소가 어떻게 보여야 하는지입니다:

결론
이 가이드의 끝에서, 당신은 Parse에서 기본 데이터 쿼리가 어떻게 작동하는지와 React 앱에서 Back4App으로 이를 수행하는 방법을 배웠습니다. 다음 가이드에서는 이 클래스에서 사용할 수 있는 모든 방법을 사용하여 Parse.Query의 모든 잠재력을 탐구할 것입니다.