Node, GraphQL 및 React를 사용하여 CRUD 단순화

30424 단어 reactgraphqlnode
저자: Avanthika Meenakshi✏️
GraphQL은 모든 요청을 단일 노드로 추상화하여 API 구축의 복잡성을 줄입니다.전통적인 RESTAPI와 달리 성명적이다.무엇을 요구하든지 되돌아갈 것이다.
물론 모든 프로젝트에 GraphQL이 필요한 것은 아니다. 단지 데이터를 통합하는 도구일 뿐이다.그것은 정의가 좋은 모델을 가지고 있기 때문에 우리는 과도하게 추출하지 않을 것이라고 확신한다.그러나 만약에 우리가 하나의 데이터 원본에서 나온 데이터에 의존하는 안정적인 RESTful API 시스템을 가지고 있다면 우리는 GraphQL을 필요로 하지 않을 것이다.
예를 들어 우리가 자신을 위해 블로그를 만들고 있다고 가정하면 우리는 하나의 MongoDB 데이터베이스에 데이터를 저장하고 검색하며 통신하기로 결정했다.이런 상황에서 우리는 구조가 복잡한 일을 하지 않았고 GraphQL도 필요하지 않았다.
다른 한편, 만약에 우리가 성숙한 제품을 가지고 있다고 가정하면 그것은 여러 출처의 데이터 (예를 들어 MongoDB, MySQL, Postgres 및 기타 API) 에 의존한다.이 경우 GraphQL을 사용해야 합니다.
예를 들어 만약에 우리가 자신을 위해 투자조합 사이트를 설계하고 있다면 우리는 소셜 미디어와 GitHub의 데이터(공헌을 표시하기 위해)가 필요하고 우리도 자신의 데이터베이스를 가지고 블로그를 유지할 수 있다. 우리는 GraphQL을 이용하여 업무 논리와 모델을 작성할 수 있다.그것은 데이터를 단일한 진상 원천으로 통합시킬 것이다.
일단 우리가 해상도 기능이 있으면 정확한 데이터를 전방으로 보낼 수 있고, 우리는 단일 원본에서 데이터를 쉽게 관리할 수 있다.이 문서에서는 GraphQL을 사용하여 간단하고 포괄적인 CRUD 작업을 수행합니다.

graphql 서버가 있는 CRUD


서버 설정


우리는 express-graphql을 사용하여 간단한 GraphQL 서버를 파생하고 이를 MySQL 데이터베이스에 연결할 것이다.소스 코드 및 MySQL 파일은 repository에 있습니다.
GraphQL 서버는 패턴 및 해석기 위에 구축됩니다.첫 번째 단계로 우리는 모델 (정의 유형, 조회, 돌연변이와 구독) 을 구축한다.이 모델은 전체 응용 프로그램 구조를 묘사했다.
그 다음으로 모델에 정의된 내용에 대해 우리는 각자의 해상도를 구축하여 데이터를 계산하고 스케줄링하고 있다.분해기는 함수로 동작을 비추기;typedef에서 설명한 모든 검색에 대해 데이터를 되돌려주는 해상도를 만듭니다.
마지막으로, 우리는 단점과 전달 설정을 정의하여 서버 설정을 완성합니다.우리는 /graphql을 응용 프로그램의 단점으로 초기화했다.우리는 구축된 모델과 루트 해상도를 graphqlHTTP 중간부품에 전달할 것이다.
모드와 루트 해상도를 제외하고 우리는 GraphiQL을 사용했다.GraphiQL은 대화식 브라우저 내의 GraphQL IDE로, 우리가 구축한 GraphQL 조회를 처리하는 데 도움을 줍니다.
var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');

var schema = buildSchema(`
  type Query {
    hello: String
  }
`);

var root = {
  hello: () => "World"
};

var app = express();

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));

app.listen(4000);

console.log('Running a GraphQL API server at localhost:4000/graphql');
서버가 정상적으로 실행되면 node index.js을 사용하여 응용 프로그램을 실행하면 http://localhost:4000/graphql에서 서버를 시작합니다.우리는 hello를 조회하고 문자열 "World"를 응답으로 받을 수 있습니다.

데이터베이스 연결


다음과 같이 MySQL 데이터베이스에 연결합니다.
var mysql = require('mysql');

app.use((req, res, next) => {
  req.mysqlDb = mysql.createConnection({
    host     : 'localhost',
    user     : 'root',
    password : '',
    database : 'userapp'
  });
  req.mysqlDb.connect();
  next();
});
우리는 여러 개의 데이터베이스/원본을 연결하여 분석기에 통합할 수 있다.여기서 MySQL 데이터베이스에 연결합니다.이 문서에서 사용한 데이터베이스 덤프는 GitHub 저장소에 있습니다.

GraphQL로 데이터 읽기 및 쓰기


우리는 데이터 원본의 데이터를 읽고 수정하기 위해 조회와 돌연변이를 사용한다.이 예에서, 나는 데이터베이스 조회를 돕기 위해 유니버설queryDB 함수를 정의했다.

조회


데이터를 나열하고 볼 수 있는 모든 SELECT 문구(또는 읽기 작업)는 type Query typedef에 들어갑니다.우리는 여기에서 두 개의 조회를 정의했다. 하나는 데이터베이스에 있는 모든 사용자를 열거하는 데 사용되고, 다른 하나는 id에 따라 한 사용자를 보는 데 사용된다.

  • 데이터 나열: 사용자를 나열하기 위해 User이라는 GraphQL 모드의 대상 유형을 정의했습니다. 이것은 getUsers 조회에서 얻거나 원하는 내용을 표시합니다.그리고 사용자 그룹을 되돌리기 위해 getUsers 조회를 정의합니다.

  • 단일 기록 보기: 단일 기록을 보려면 id을 매개 변수로 하고 우리가 정의한 getUserInfo 조회를 사용합니다.이것은 데이터베이스에서 특정한 id를 조회하고 데이터를 전방으로 되돌려줍니다.

  • 현재 우리는 모든 기록을 가져오고 id에 따라 기록을 보기 위해 조회를 함께 놓았습니다. GraphiQL에서 사용자를 조회하려고 시도할 때, 화면에 사용자 그룹을 표시합니다!🙂
    var schema = buildSchema(`
      type User {
        id: String
        name: String
        job_title: String
        email: String
      }
      type Query {
        getUsers: [User],
        getUserInfo(id: Int) : User
      }
    `);
    
    const queryDB = (req, sql, args) => new Promise((resolve, reject) => {
        req.mysqlDb.query(sql, args, (err, rows) => {
            if (err)
                return reject(err);
            rows.changedRows || rows.affectedRows || rows.insertId ? resolve(true) : resolve(rows);
        });
    });
    
    var root = {
      getUsers: (args, req) => queryDB(req, "select * from users").then(data => data),
      getUserInfo: (args, req) => queryDB(req, "select * from users where id = ?", [args.id]).then(data => data[0])
    };
    

    돌변하다


    데이터베이스 쓰기 작업 - 생성, 업데이트, 삭제 - 일반적으로 "돌연변이"에서 정의됩니다.GraphQL 엔진은 순서대로 돌변을 실행합니다.조회는 병행해서 실행됩니다.
  • 데이터 만들기: MySQL 데이터베이스에 지정된 매개 변수를 사용하여 데이터를 만드는 변이 createUser을 정의했습니다.
  • 데이터 업데이트 또는 삭제: 기록 보기와 유사하게 업데이트(updateUserInfo)와delete(deleteUser)는 id를 매개 변수로 하고 데이터베이스를 수정합니다.
  • 이러한 함수는 변경되었는지 여부를 표시하기 위해 부울 값을 사용합니다.
    var schema = buildSchema(`
      type Mutation {
        updateUserInfo(id: Int, name: String, email: String, job_title: String): Boolean
        createUser(name: String, email: String, job_title: String): Boolean
        deleteUser(id: Int): Boolean
      }
    `);
    
    var root = {
      updateUserInfo: (args, req) => queryDB(req, "update users SET ? where id = ?", [args, args.id]).then(data => data),
      createUser: (args, req) => queryDB(req, "insert into users SET ?", args).then(data => data),
      deleteUser: (args, req) => queryDB(req, "delete from users where id = ?", [args.id]).then(data => data)
    };
    
    현재, 우리는 서버 측의 내용을 설정하고 정렬했습니다. 백엔드를 React 응용 프로그램에 연결하려고 시도합니다.

    graphql 클라이언트가 있는 CRUD


    일단 우리가 서버가 생기면, 클라이언트 논리를 만들어서 데이터를 표시하고 변이하는 것은 매우 쉽다.Apollo Client는 상태 관리 및 캐시를 지원합니다.또한 데이터 검색, 로드 추적, 오류 상태 추적, UI 업데이트에 사용되는 모든 논리는 useQuery 갈고리로 봉인됩니다.

    graphql 서버에 연결


    나는 CRA 템플릿을 만들었고 GraphQL, apollo-boost, @apollo/react-hooks을 설치했다.Apollo 클라이언트를 초기화하고 응답을 위해 연결합니다.
    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './App';
    import ApolloClient from 'apollo-boost';
    import { ApolloProvider } from '@apollo/react-hooks';
    
    const client = new ApolloClient({
      uri: 'http://localhost:4000/graphql'
    });
    
    ReactDOM.render(
      <ApolloProvider client={client}>
        <App />
      </ApolloProvider>,
      document.getElementById('root')
    );
    

    읽기 및 변이 데이터


    소스 코드 Queries 폴더의 모든 GraphQL 질의를 관리했습니다.나는 useQuery 갈고리를 사용하여 서버에서 데이터를 요청할 것이다. 이 갈고리는 React 갈고리 API 위에 구축된다.UI에 데이터를 도입하는 데 도움이 됩니다.
    GraphQL 쿼리는 일반적으로 gql 함수에 포장됩니다.gql은 질의 문자열을 질의 문서로 변환하는 데 도움을 줍니다.다음은 우리가 응용 프로그램에서 조회를 어떻게 정의하는지입니다.
    import { gql } from 'apollo-boost';
    
    export const GET_USERS = gql`
      {
        getUsers {
          id,
          name,
          job_title,
          email
        }
      }
    `;
    
    export const VIEW_USERS = gql`
      query ($id: Int){
        getUserInfo(id: $id) {
          id,
          name,
          job_title,
          email
        }
      }
    `;
    
    export const ADD_USER = gql`
      mutation($name: String, $email: String, $job_title: String) {
        createUser (name: $name, email: $email, job_title: $job_title)
      }
    `;
    
    export const EDIT_USER = gql`
      mutation($id: Int, $name: String, $email: String, $job_title: String) {
        updateUserInfo (id: $id, name: $name, email: $email, job_title: $job_title)
      }
    `;
    
    export const DELETE_USER = gql`
      mutation($id: Int) {
        deleteUser(id: $id)
      }
    `
    
    ApolloProvider을 설정하면 GraphQL 서버에서 데이터를 요청할 수 있습니다.우리가 시도한 조회는 useQuery 갈고리에 전달될 것이며, 그것은 우리에게 결과를 제공할 것이다.
    나는 두 개의 조회를 했는데, 매개 변수가 있고, 매개 변수가 없어서, 우리가 전단의 조회와 돌연변이를 어떻게 처리해야 하는지를 설명한다.useQueryerrorloading의 상태를 추적하고 관련 대상에 반영합니다.서버가 결과를 보내면 데이터 속성에 반영됩니다.
    import React from 'react';
    import { useQuery } from '@apollo/react-hooks';
    import { GET_USERS, VIEW_USERS } from "./Queries";
    import { Card, CardBody, CardHeader, CardSubtitle, Spinner } from 'reactstrap';
    
    function App() {
      const getAllUsers = useQuery(GET_USERS);
      const userInfo = useQuery(VIEW_USERS, { variables: { id: 1 }});
      if (getAllUsers.loading || userInfo.loading) return <Spinner color="dark" />;
      if (getAllUsers.error || userInfo.error) return <React.Fragment>Error :(</React.Fragment>;
    
      return (
        <div className="container">
          <Card>
            <CardHeader>Query - Displaying all data</CardHeader>
            <CardBody>
              <pre>
                {JSON.stringify(getAllUsers.data, null, 2)}
              </pre>
            </CardBody>
          </Card>
          <Card>
            <CardHeader>Query - Displaying data with args</CardHeader>
            <CardBody>
              <CardSubtitle>Viewing a user by id</CardSubtitle>
              <pre>
                {JSON.stringify(userInfo.data, null, 2)}
              </pre>
            </CardBody>
          </Card>
        </div>
      )
    }
    
    export default App;
    
    검색과 유사하게 돌연변이는 같은 useQuery 갈고리를 사용하고 데이터를 변수로 검색에 전달한다.
    const deleteMutation = useQuery(DELETE_USER, { variables: { id: 8 }});
    const editMutation = useQuery(EDIT_USER, { variables: { id: 9, name: "Username", email: "email", job_title: "job" }});
    const createMutation = useQuery(ADD_USER, { variables: { name: "Username", email: "email", job_title: "job" }});
    

    결론


    Ta da!우리는 방금 GraphQL로 CRUD 작업을 끝에서 끝까지 진행했습니다.클라이언트에서 React 갈고리를 도입한 후에 데이터를 읽고 수정하는 것은 매우 간단해졌다.Apollo 클라이언트는 인증, 오류 처리, 캐시, 낙관적인 사용자 인터페이스도 제공합니다.
    구독은 GraphQL의 또 다른 흥미로운 개념입니다.이 응용 프로그램을 모델로 삼아 우리는 계속 다른 유사한 개념을 시도할 수 있다.
    즐거운 인코딩!
    편집자: 이 문장에 무슨 문제가 있습니까?정확한 버전 here을 찾을 수 있습니다.

    플러그인: 네트워크 어플리케이션용 DVR용 LogRocket


     

     
    LogRocket은 프론트 로그 기록 도구로 질문을 다시 재생할 수 있습니다. 마치 브라우저에서 발생한 것처럼.LogRocket은 오류가 발생한 원인을 추측하거나 화면 캡처와 로그 저장을 물어보지 않고 세션을 다시 재생할 수 있도록 합니다.프레임워크가 어떻든지 간에 모든 응용 프로그램과 완벽하게 어울릴 수 있으며, 플러그인은 Redux, Vuex, @ngrx/store의 추가 상하문을 기록합니다.
     
    LogRocket은 Redux 작업과 상태를 기록하는 것 외에도 콘솔 로그, JavaScript 오류, 스택 추적, 헤더+본문이 있는 네트워크 요청/응답, 브라우저 메타데이터와 사용자 정의 로그를 기록합니다.또한 DOM을 사용하여 페이지에 HTML과 CSS를 기록하여 가장 복잡한 단일 페이지 응용 프로그램이라도 픽셀 수준의 비디오를 재구성합니다.
     
    Try it for free .
    게시물 Make CRUD simple with Node, GraphQL, and ReactLogRocket Blog에 먼저 올라왔습니다.

    좋은 웹페이지 즐겨찾기