우선 내가 생각하는 GraphQL의 장점은
1. rest api로 작성할때 각 url 마다 api 를 만들어줄 필요없이 하나의 end-point로 데이터를 주고받는 것이 가능하는 것이다.
2. 내가 만들어 놓은 query나 mutation을 이용하여 필요한 값들만 정확하게 가져와 데이터 낭비를 줄일 수 있다.
더 많은 장점들이 있지만 우선 생각나는 것들이 이것들 뿐이다. 그리고 단점은 file전송 같은 것을 할 때 복잡하다.
이 포스팅을 하는 이유는 주로 Sequelize와 MySQL을 같이 쓰는데 이렇게 GraphQL, Sequelize, MySQL 세 가지를 같이 활용해서 만든 예제들이 충분하지 않아, 만들기 어려웠기 때문이다. 그리고 서버는 아폴로 서버를 이용하여 만들 것이고 프론트는 리액트에 아폴로 클라이언트를 이용하여 데이터를 프론트엔드로 받아올 것이다.
토이프로젝트의 목적은 단계적으로 크게 세 가지다.
1. sequelize를 이용하여 server와 mysql을 연결시킨다.
2. db와 연결된 server를 GraphQL을 이용하여 데이터를 뽑아온다.
3. 뽑아온 데이터를 client(front-end)에서 그려낸다.
1. 필요한 package들을 다운로드한다.
npm init -y
npm install --save apollo-server express express-graphql graphql mysql mysql2 nodemon sequelize
2. 프로젝트 폴더 안에서 sequelize init을 이용하여 sequelize 환경을 세팅한다.
sequelize init
3. config/config.json에 자신의 db 정보를 입력해준다.
{
"development": {
"username": "root",
"password": "****",
"database": "test",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
4. models/index.js에 아래 코드를 입력한다.
'use strict';
const path = require('path');
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
const sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.User = require("./user")(sequelize, Sequelize);
module.exports = db;
5. models/user.js를 만들어 생성할 table 정보를 정의한다.
module.exports = (sequelize, DataTypes) =>
sequelize.define(
"user",
{
firstName: {
type: DataTypes.STRING(40),
allowNull: true,
},
lastName: {
type: DataTypes.STRING(40),
allowNull: true,
},
password: {
type: DataTypes.STRING(100),
allowNull: true,
},
},
{
timestamps: true,
paranoid: true,
}
);
6. 제일 하위 경로에 서버가될 index.js를 만든다.
const express = require('express');
const app = express();
const PORT = 3030;
const path = '/graphql';
const { ApolloServer, gql } = require('apollo-server-express');
const { User } = require('./models/index');
User.sequelize.sync().then(() => {
console.log("sequelize success")
}).catch(err => {
console.log("sequelize fail", err)
})
const typeDefs = gql`
type User {
id: Int
firstName: String
lastName: String
password: String
}
type Query {
getUserData: [User!]!
getAllUser(id: Int!): User
}
type Mutation {
createUser(firstName: String!, lastName: String!, password: String!): User
updateUser(id: Int!, firstName: String!, lastName: String!, password: String!): User
deleteUser(id: Int!, firstName: String!, lastName: String!, password: String!): User
}
`;
const resolvers = {
Query: {
getUserData: async () => {
const getUsers = await User.findAll();
return getUsers;
},
getAllUser: async (_, args) => {
await context.User.findOne()
console.log(args)
const { id } = args;
const resultData = await User.findOne( {where: { id: id } });
return resultData;
}
},
Mutation: {
createUser: async (_, { firstName, lastName, password }) => {
const newUser = await User.create({
firstName,
lastName,
password
});
const user = await User.findOne( { where: { id: id } });
return user;
},
updateUser: async (_, { id, firstName, lastName, password }) => {
console.log(id)
const oldUser = await User.update({firstName, lastName, password}, {where: { id: id } });
const user = await User.findOne( { where: { id: id } });
return user;
},
deleteUser: async (_, { id }) => {
console.log(id)
const oldUser = await User.destroy({where: { id: id } });
const user = await User.findOne( { where: { id: id } });
return user;
},
}
};
const server = new ApolloServer({ typeDefs, resolvers });
server.applyMiddleware({ app, path });
// The `listen` method launches a web server.
app.listen({ port: PORT }, () =>
console.log(`🚀 Server ready at http://localhost:${PORT}${path}`)
)
typeDefs는 쿼리를 보낼 것의 형태를 정의해준다.
resolvers에는 query나 mutation에서 쓸 sequelize문들을 정의해 준다.
그리고 ApolloServer에서 이것들을 이용하여 playground를 만들어준다.
이렇게 되면 큰 틀에서 server의 준비는 끝났다. crud기능들의 쿼리들은 모두 만들었다.
GraphQL에서는 query에서는 read기능만을 넣어야하고 mutation에는 create, update, delete기능을 넣어야한다.
이제 client(front-end) 환경 설정을 해야한다.
1. front가 될 폴더에서 react환경을 다운받아준다.
npm init -y
npx create-react-app ./
npm install --save graphql @apollo/client react-router-dom styled-components
2. 만들어진 react 환경에서 index.js에 들어간다.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { ApolloClient, InMemoryCache, useQuery } from '@apollo/client';
import { ApolloProvider, gql } from '@apollo/client';
const client = new ApolloClient({
uri: 'http://localhost:3030/graphql',
cache: new InMemoryCache()
});
ReactDOM.render(
<React.StrictMode>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
3. App.js에 들어간다.
import React, { useState, useEffect } from "react";
import './App.css';
import { ApolloClient, InMemoryCache, useQuery } from '@apollo/client';
import { ApolloProvider, gql } from '@apollo/client';
function App() {
const GET_USER = gql`
query{
getUserData{
firstName
lastName
password
}
}
`
const { loading, error, data } = useQuery(GET_USER);
if (loading) return <p>'Loading...'</p>
if (error) return `Error ${error.message}`
return (
<div>
<h1>{data.getUserData.map((value, key)=> (<div>{value.firstName}</div>))}</h1>
<h2>My first Apollo app 🚀</h2>
</div>
);
}
export default App;
지금은 간단하게 userdata를 가져오는 쿼리만 날려보았다. 이런식으로 응용하여 만들어놓은 crud 기능들을 다 활용할 수 가 있다.
자세한 코드는 github에 올려놓았다.
github.com/ukcasso/graphql_sequelize_mysql
그리고 자세한 것들은 역시나 공식문서들을 참고해 보는 것이 좋다.
www.apollographql.com/docs/apollo-server/
www.apollographql.com/docs/react/
'토이 프로젝트' 카테고리의 다른 글
electron 프로그램 자동 업데이트 진행 시키기 (auto-updater), amazon s3 (0) | 2021.03.15 |
---|---|
[자바스크립트] 네이버 검색광고 API 이용하기 (Node.js) - 네이버 검색량 조회 예제 (/keywordstool API) (18) | 2021.03.05 |
[자바스크립트 ] 매크로 만들기 - puppeteer (간단한 자동 로그인) (0) | 2021.01.15 |
로또 추점기, 로또 번호 생성기 (로또 추첨 사이트) (0) | 2020.10.30 |
[자바스크립트] 작은 도서관 프로그램 만들기 (MySQL, Express, Fetch API, Node.js) - Mysql, express, fetch api crud example (2) (0) | 2020.10.21 |