2023.03.17 TIL

์ •์Šน์›ยท2023๋…„ 3์›” 19์ผ
0
post-thumbnail

๐Ÿ“’ ๋ชฉ์ฐจ

  • ๐Ÿ“Œ ํ”„๋ก ํŠธ์—”๋“œ(HTML ๋ฒ„ํŠผ)์— axios ์—ฐ๋™ํ•˜๊ธฐ
  • ๐Ÿ“Œ Axios ์—ฐ๋™ํ•˜๊ธฐ
  • ๐Ÿ“Œ CORS ๋ฌธ์ œ
  • ๐Ÿ“Œ apollo-server ์„ค์น˜
  • ๐Ÿ“Œ GraphQl-API ๋งŒ๋“ค๊ธฐ ์‹ค์Šต

๐Ÿ“Œ ํ”„๋ก ํŠธ์—”๋“œ(HTML ๋ฒ„ํŠผ)์— axios ์—ฐ๋™ํ•˜๊ธฐ

ํ”„๋ก ํŠธ์—”๋“œ(HTML ๋ฒ„ํŠผ)์— axios ์—ฐ๋™ํ•˜๊ธฐ
์˜ค๋Š˜ Apollo์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Graphql-api๋ฅผ ์ œ๊ณตํ•˜๋Š” ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž!!
apollo ์„œ๋ฒ„๋Š” graphql-api๋ฅผ ์ œ๊ณตํ•˜๋Š” ์„œ๋ฒ„๋ฅผ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ํŒจํ‚ค์ง€์ด๋‹ค.
๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ express์™€ ์—ญํ• ์ด ๋น„์Šทํ•˜๋‹ค.

์‹ค์Šต์„ ํ•ด๋ณด๊ธฐ ์œ„ํ•ด ์šฐ์„  ๊ฐ„๋‹จํ•œ html๋ฌธ์„œ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž
ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•œ ๋’ค, ์ธ์ฆํ•˜๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฒŒ ๋˜๋ฉด, ์ธ์ฆ์ƒํƒœ ๋ฌธ๊ตฌ๊ฐ€ ์ธ์ฆ์™„๋ฃŒ๋กœ ๋ฐ”๋€Œ๋Š” ๋กœ์ง์ด๋‹ค.

๐Ÿ“Œ Axios ์—ฐ๋™ํ•˜๊ธฐ

์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ html ๋ฌธ์„œ์™€ ์ž‘์„ฑํ•œ api๊ฐ„ ์†Œํ†ต์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด๋ณด์ž!!
์ง€๊ธˆ๊นŒ์ง€๋Š” postman์„ ํ†ตํ•ด api๋ฅผ ํ…Œ์ŠคํŠธํ•ด์™”๋‹ค.
์ด๋ฒˆ์—๋Š” ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ๋ฅผ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋กœ ์š”์ฒญํ•˜๊ธฐ ์œ„ํ•ด axios๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.

์šฐ์„  HTML ํŒŒ์ผ์—์„œ axios๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด <script>ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์šด๋กœ๋“œ๋ฅผ ๋ฐ›์•„์•ผ ํ•œ๋‹ค.
์ด๋ ‡๊ฒŒ ๋‹ค์šด๋กœ๋“œ ๋ฐ›๋Š” ๋ฐฉ์‹์„ CDN(contens delevery network)๋ผ ๋ถ€๋ฅธ๋‹ค.

axios.cdn์„ ๊ฒ€์ƒ‰ํ•ด๋ณด๋ฉด ๊ณต์‹๋ฌธ์„œ์— ์•„๋ž˜์™€ ๊ฐ™์€ cdn ์ฝ”๋“œ๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ด๊ฒƒ์„ ์•ž์„œ ๋งํ•œ <script>ํƒœ๊ทธ ์•ˆ์— ๋„ฃ์–ด์ค€๋‹ค.

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

์ด์ œ axios๋ฅผ ์‚ฌ์šฉํ•  ์ค€๋น„๊ฐ€ ๋ชจ๋‘ ๋๋‚ฌ๋‹ค.
axios๋ฅผ ์ด์šฉํ•˜์—ฌ api๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋ณด์ž

axios.post : api ์š”์ฒญ ๋ณด๋‚ด๊ธฐ
axios.then : ์š”์ฒญ์„ ๋ณด๋‚ธ ํ›„, ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ (์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต)

// signup.html

<head>
    <title>ํšŒ์›๊ฐ€์ž… ์—ฐ์Šตํ•˜๊ธฐ</title>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script>
      function check() {
        // 1. ์ž…๋ ฅํ•œ ํœด๋Œ€ํฐ๋ฒˆํ˜ธ ๊ฐ€์ ธ์˜ค๊ธฐ
        const myphone = document.getElementById('qqq').value;
        console.log('๋‚˜์˜ ํ•ธ๋“œํฐ๋ฒˆํ˜ธ: ', myphone);

        // 2. ํ•ด๋‹น ํœด๋Œ€ํฐ๋ฒˆํ˜ธ๋กœ ์ธ์ฆ๋ฒˆํ˜ธAPI ์š”์ฒญํ•˜๊ธฐ
        axios
          .post('http://localhost:3000/tokens/phone', {
            qqq: myphone,
          })
          .then((res) => {
            console.log(res);
				document.getElementById("zzz").innerText = res.data
          });
      }
    </script>
  </head>

์ด์ œ backend์—์„œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ณ , ์š”์ฒญ์„ ๋ณด๋‚ด๋ณด์ž
๊ทธ๋Ÿฐ๋ฐ, ์ œ๋Œ€๋กœ๋œ ์‘๋‹ต์ด ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๋Š”๋‹ค...

๊ฐœ๋ฐœ์ž ๋„๊ตฌ์˜ ์ฝ˜์†”์ฐฝ์„ ํ™•์ธํ•ด๋ณด๋ฉด ์ด์œ ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
์—ฌ๋Ÿฌ ์—๋Ÿฌ๋“ค์ด ๋‚˜ํƒ€๋‚˜๊ณ  ์žˆ์ง€๋งŒ ์ด ์ค‘, CORS์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ธฐ๋กœ ํ•˜์ž!!

๐Ÿ“Œ CORS ๋ฌธ์ œ

postman์—์„œ ์„ฑ๊ณตํ–ˆ๋˜ ์š”์ฒญ๊ณผ ๊ฐ™์€ ์š”์ฒญ์„ ์ง์ ‘ ๋งŒ๋“  ๋ฒ„ํŠผ์„ ํ™œ์šฉํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง„ํ–‰ํ–ˆ๋Š”๋ฐ ์™œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๊ฑธ๊นŒ?
์ด์œ ๋Š” CORS ๋•Œ๋ฌธ์ด๋‹ค.
CORS๋Š” (cross origin resources sharing)์˜ ์•ฝ์ž๋กœ ์„œ๋กœ๋‹ค๋ฅธ ์ถœ์ฒ˜(origin)๋ฅผ ๊ฐ€์ง„ ์ฃผ์†Œ๋กœ ์š”์ฒญ์ด ๋“ค์–ด์™”์„ ๋•Œ, ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ์ด๋‹ค.
์—ฌ๊ธฐ์„œ ์ถœ์ฒ˜๋ž€ portq๋ฒˆํ˜ธ๊นŒ์ง€ ํฌํ•จํ•œ url์„ ์˜๋ฏธํ•œ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด http://localhost:3000/tokens/phone)์—์„œ http://localhost:3000๋ถ€๋ถ„์„ origin์ด๋ผ ํ•œ๋‹ค.
port ๋ฒˆํ˜ธ๊ฐ€ ๋‹ค๋ฅธ ๊ฒฝ์šฐ์—๋„ CORS๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋ฐ, ์ด์œ ๋Š” ๊ฐ™์€ localhost์ด๋”๋ผ๋„ ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ ์ธ์‹๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋”ฐ๋ผ์„œ, CORS๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฐฑ์—”๋“œ ์„œ๋ฒ„์˜ ์‘๋‹ต ํ—ค๋”์˜ accss-control-allow-originํ•ญ๋ชฉ์— ํ—ˆ์šฉํ•˜๊ณ ์žํ•˜๋Š” origin์„ ๋‹ด์•„ CORS ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

โœ… CORS ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ

์•ž์„œ ๋งํ•œ๊ฒƒ์ฒ˜๋Ÿผ ์ง์ ‘ ์‘๋‹ต ํ—ค๋”์— origin์„ ์ ๋Š” ๋ฐฉ๋ฒ•๋„ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, CORS ๋ฏธ๋“ค์›จ์–ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜๊ฒŒ ๋˜๋ฉด ๊ฐ„ํŽธํ•˜๊ฒŒ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

							`yarn add cors`

์ดํ›„์—, CORS๋ฅผ import ํ•˜๊ณ  ์ ์šฉ ์‹œ์ผœ์ฃผ๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋œ๋‹ค.
๋˜ํ•œ, app.use(cors())์™€ ๊ฐ™์ด ์ž…๋ ฅํ•˜๋ฉด origin์—์„œ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์„ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ,
์›ํ•˜๋Š” origin๋งŒ ํ—ˆ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด app.use(cors{origin: })๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•˜์—ฌ ํŠน์ • ์˜ค๋ฆฌ์ง„๋งŒ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

// index.js

// ...์ƒ๋žต

import cors from 'cors';

const app = express();
app.use(express.json());
app.use(cors()); // ์ถ”๊ฐ€๋œ ๋ถ€๋ถ„

// ...์ƒ๋žต

์ด์ œ ๋‹ค์‹œ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋ฅผ ๋ช…๋ น์–ด๋กœ ์‹คํ•ด์‹œ์ผœ๋ณด๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด CORS์—๋Ÿฌ๊ฐ€ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“Œ apollo-server ์„ค์น˜

์ง€๊ธˆ๊นŒ์ง€๋Š” Rest-api๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด express๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„๋ฅผ ์—ด์—ˆ์ง€๋งŒ, ์ง€๊ธˆ๋ถ€ํ„ฐ๋Š” graphql-api๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๊ธฐ ์œ„ํ•ด express์™€ ์œ ์‚ฌํ•œ ์—ญํ• ์„ ํ•˜๋Š” apollo-server๋ฅผ ์„ค์น˜ํ•˜๋Š” ์‹ค์Šต์„ ํ•ด๋ณด์ž!!

								$ yarn add @apollo/server graphql

์œ„์˜ ๋ช…๋ น์–ด๋ฅผ ํ„ฐ๋ฏธ๋„์—์„œ ์„ค์น˜ํ•˜๊ฒŒ ๋˜๋ฉด npm ์‚ฌ์ดํŠธ์˜ ์ดˆ๊ธฐ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋‚ด๊ฐ€ ์ƒ์„ฑํ•œ ํŒŒ์ผ์— ๋ถ™์—ฌ๋„ฃ๊ธฐ ํ•œ๋‹ค.
์ถ”๊ฐ€์ ์œผ๋กœ, ๋„์–ด์“ฐ๊ธฐ๋กœ ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์„ ๊ตฌ๋ถ„ํ•ด์ฃผ๋ฉด ๋‹ค์ˆ˜์˜ ๋ชจ๋“ˆ์„ ํ•œ๋ฒˆ์— ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค!!!

์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒŒ ๋˜๋ฉด, ์šฐ์„  ์ด์ „์— ํ•™์Šตํ–ˆ๋˜ express์—์„œ ํŠน์ • ํฌํŠธ๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„๋ฅผ ์—ด ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ์—ˆ๋˜, listen์ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
๋˜ํ•œ

// index.js
import { ApolloServer, gql } from "apollo-server";

const typeDefs = gql`
  type Query {
    qqq: String
  }
`;

const resolvers = {
  Query: {
    qqq: () => {
      return "Hello World!";
    },
  },
};

const app = new ApolloServer({
  typeDefs: typeDefs,
  resolvers: resolvers,
});

app.listen(3000).then(() => {
  console.log("๋ฐฑ์—”๋“œ API ์„œ๋ฒ„๊ฐ€ ์ผœ์กŒ์–ด์š”!!!");
});

import๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” package.json์— "type": "module"์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค!!!

{
  "name": "03-06-grqphql-api-with-apollo-server",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "type": "module",  // ์ถ”๊ฐ€
  "dependencies": {
    "@apollo/server": "^4.5.0",
    "graphql": "^16.3.0"
  }
}

์ฝ”๋“œ๋ฅผ ์กฐ๊ธˆ ๋” ์œ„๋กœ ์˜ฌ๋ ค๋ณด๊ฒŒ ๋˜๋ฉด, app์„ ์ •์˜ํ•˜๊ณ  ์žˆ๊ณ  typedefs, resolvers๊ฐ€ ์ž…๋ ฅ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

const app = new ApolloServer({
  typeDefs: typeDefs,
  resolvers: resolvers,
});

๋จผ์ €, resolver๋ฅผ ๋ณด๊ฒŒ ๋˜๋ฉด, express ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ๋ณด์•˜๋˜ api์™€ ๊ฐ™์€ ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

// express
app.get('/', function (req, res) {
  res.send('Hello Wordld')
})

// apollo-server
const resolvers = {
  Query: {
    qqq: () => 'Hello world',
  },
};

typeDefs๋Š” express์—์„œ ๋ณด์ง€ ๋ชปํ–ˆ๋˜ ์ฝ”๋“œ์ธ๊ฒƒ ๊ฐ™๋‹ค.
express์˜ ๊ฒฝ์šฐ, swagger๋ฅผ ํ†ตํ•ด api-docs๋ฅผ ์ง์  ์ž‘์„ฑํ–ˆ์ง€๋งŒ graphql์˜ ๊ฒฝ์šฐ, docs ๋ถ€๋ถ„์„ typeDefs์—์„œ swagger์™€ ๊ฐ™์ด ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ค€๋‹ค.

๋˜ํ•œ CORS์˜ ๊ฒฝ์šฐ, ApoolloServer ๋‚ด์— ์ ์šฉ์‹œํ‚ค๋ฉด ๋œ๋‹ค.

const app = new ApolloServer({
  typeDefs: typeDefs,
  resolvers: resolvers,
  cors: true,  // ๋ชจ๋“  ์‚ฌ์ดํŠธ ํ—ˆ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ
  // cors: { origin: ["https://naver.com", "https://daum.net"] } // ํŠน์ • ์‚ฌ์ดํŠธ๋งŒ ์ง€์ •ํ•˜๊ณ  ์‹ถ์„ ๋•Œ
});

๐Ÿ“Œ GraphQl-API ๋งŒ๋“ค๊ธฐ ์‹ค์Šต

โœ… graphql ์ ‘์†ํ•˜๊ธฐ

http://localhost:3000/graphql๋ฅผ ์ž…๋ ฅํ•˜๊ฒŒ ๋˜๋ฉด, grapgql์— ์ ‘์†ํ•  ์ˆ˜ ์žˆ๋‹ค.

Query : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์š”์ฒญ์ด๋‹ค. (์กฐํšŒ)
Mutation : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œํ•˜๋Š” ์š”์ฒญ์ด๋‹ค.

์ด์ œ graphql-api๋ฅผ ํ™œ์šฉํ•˜์—ฌ api๋ฅผ ๋งŒ๋“ค์–ด๋ณผ ๊ฒƒ์ด๋‹ค.
์ด์ „์— ๋งŒ๋“ค์—ˆ๋˜ fetchBoards ์™€ createBoard api๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž!!
๊ทธ ์ „์—, resolvers ๋ถ€๋ถ„์€ express์˜ api์™€ ๊ฐ™๊ณ , typeDefs๋Š” api-docs๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ์‘๋‹ต์„ ๋Œ๋ ค์ค„ ํƒ€์ž…์„ ์ •์˜ํ•ด์ฃผ๋Š” ๋ถ€๋ถ„์ด๋‹ค.

โœ… fetchBoards API ์ƒ์„ฑ

GET๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

// index.js

const resolvers = {
  Query: {
    fetchBoards: () => {
      // 1. ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋กœ์ง => DB์— ์ ‘์†ํ•ด์„œ ๋ฐ์ดํ„ฐ ๊บผ๋‚ด์˜ค๊ธฐ
      const result = [
        {
          number: 1,
          writer: '์ฒ ์ˆ˜',
          title: '์ œ๋ชฉ์ž…๋‹ˆ๋‹ค~~',
          contents: '๋‚ด์šฉ์ด์—์š”@@@',
        },
        {
          number: 2,
          writer: '์˜ํฌ',
          title: '์˜ํฌ ์ œ๋ชฉ์ž…๋‹ˆ๋‹ค~~',
          contents: '์˜ํฌ ๋‚ด์šฉ์ด์—์š”@@@',
        },
        {
          number: 3,
          writer: 'ํ›ˆ์ด',
          title: 'ํ›ˆ์ด ์ œ๋ชฉ์ž…๋‹ˆ๋‹ค~~',
          contents: 'ํ›ˆ์ด ๋‚ด์šฉ์ด์—์š”@@@',
        },
      ];

      // 2. ๊บผ๋‚ด์˜จ ๊ฒฐ๊ณผ ์‘๋‹ต ์ฃผ๊ธฐ
      return result;
    },
  },
}

rest-api ์—์„œ๋Š” res.send๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ์ง€๋งŒ, graphql-api๋Š” return์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ์ข…๋ฃŒํ•˜๋ฉด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋˜ํ•œ, resolvers์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ’๋“ค์˜ type ์—ญ์‹œ typeDefs์—์„œ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

# index.js

const typeDefs = gql`
  type BoardReturn {
    number: Int
    writer: String
    title: String
    contents: String
  }

  type Query {
    # fetchBoards: BoardReturn => ๊ฐ์ฒด 1๊ฐœ๋ฅผ ์˜๋ฏธ
    fetchBoards: [BoardReturn] # => ๋ฐฐ์—ด ์•ˆ์— ๊ฐ์ฒด 1๊ฐœ ์ด์ƒ์„ ์˜๋ฏธ
  }
`;

๋ฐ˜ํ™˜๊ฐ’์€ ๋ฐฐ์—ด ์•ˆ์˜ ๊ฐ์ฒด์˜ ํ˜•ํƒœ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.
์ตœ์ข…์ ์œผ๋กœ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

โœ… createBoard API ์ƒ์„ฑ

๊ฒŒ์‹œ๊ธ€์„ ๋งŒ๋“œ๋Š” api๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž!!
์ƒ์„ฑ ์ฆ‰, POSTํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ด๊ธฐ ๋•Œ๋ฌธ์— MUTATION์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์„ฑํ•œ๋‹ค.
์ด๋•Œ, ์ƒ์„ฑ๋œ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ž…๋ ฅ๊ฐ’์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ํ•ด๋‹น ํ•จ์ˆ˜๋Š” 4๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

  • parent : ๋ถ€๋ชจํƒ€์ž… resolver์—์„œ ๋ฐ˜ํ™˜๋œ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด
  • args : ์ฟผ๋ฆฌ ์š”์ฒญ ์‹œ ์ „๋‹ฌ๋œ parameter๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด
  • context : graphql์˜ ๋ชจ๋“  resolver๊ฐ€ ๊ณต์œ ํ•˜๋Š” ๊ฐ์ฒด (๋กœ๊ทธ์ธ ์ธ์ฆ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘๊ทผ ๊ถŒํ•œ ๋“ฑ์— ์‚ฌ์šฉ๋œ๋‹ค)
  • info : ๋ช…๋ น ์‹คํ–‰ ์ƒํƒœ ์ •๋ณด๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด
// index.js

const resolvers = {
  Mutation: {
    createBoard: (parent, args, context, info) => {
   
    },
  },
};

rest-api์—์„œ๋Š” ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ req๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.
graphql์—์„œ๋Š” 4๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ค‘ ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธ ๊ฐ€๋Šฅํ•œ args๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž…๋ ฅ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๋‹ค.

// index.js

const resolvers = {
  Query: {
    fetchBoards: () => {
      // ...
    },
  },

  Mutation: {
    createBoard: (_, args) => {
      // 1. ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ณด๋‚ด์ค€ ๋ฐ์ดํ„ฐ ํ™•์ธํ•˜๊ธฐ
      console.log(args);
			console.log("=========================")
      console.log(args.createBoardInput.writer)
      console.log(args.createBoardInput.title)
      console.log(args.createBoardInput.contents)

			// 2. DB์— ์ ‘์† ํ›„, ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ => ๋ฐ์ดํ„ฐ ์ €์žฅํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •

      // 3. DB์— ์ €์žฅ๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์— ์‘๋‹ต(response) ์ฃผ๊ธฐ
      return '๊ฒŒ์‹œ๋ฌผ ๋“ฑ๋ก์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค!!';
    },
  },
};

์ด๋ฒˆ์—๋Š” ์š”์ฒญ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ง€์ •ํ•ด๋ณด์•˜๋‹ค.
์•„๋ž˜์™€ ๊ฐ™์ด input์„ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ์˜ ํƒ€์ž…์„ ์ง€์ •ํ•œ๋‹ค.

# index.js

const typeDefs = gql`
  input CreateBoardInput {
    writer: String
    title: String
    contents: String
  }

  type Mutation {
    # createBoard(writer: String, title: String, contents: String): String => ์ž…๋ ฅ๊ฐ’์„ ๋‚ฑ๊ฐœ๋กœ ๋ฐ›์•„์˜ค๋Š” ๊ฒƒ์„ ์˜๋ฏธ
    createBoard(createBoardInput: CreateBoardInput!): String # => ์ž…๋ ฅ๊ฐ’์„ ๊ฐ์ฒด๋กœ ๋ฐ›์•„์˜ค๋Š” ๊ฒƒ์„ ์˜๋ฏธ
  }
`;

์ตœ์ข…์ ์œผ๋กœ apollo sever๋ฅผ ์—ด๊ณ  localhost:3000/graphql์— ์ ‘์†ํ•ด์„œ api ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ด๋ณธ๋‹ค.

# index.js

mutation {
  createBoard(createBoardInput: {
    writer: "์ฝ”๋“œ์บ ํ”„",
    title: "์˜จ๋ผ์ธ ๋ถ€ํŠธ์บ ํ”„ ๋ฐฑ์—”๋“œ",
    contents: "๋งค์šฐ ์ข‹์Šต๋‹ˆ๋‹ค!!!"
  })
}

๐ŸŒˆ ์˜ค๋Š˜ ํ•˜๋ฃจ

์ ์  ์กฐ๊ธˆ์”ฉ ์ง€์ณ๊ฐ€๋Š” ์š”์ฆ˜์ด๋‹ค. ๋‚ ์”จ๋„ ๋งŽ์ด ํ’€๋ ค ๋ด„์ด ์˜ค๊ณ  ์žˆ๊ณ , ๋‚˜๋ฅธํ•ด์ง€๋Š” ๊ธฐ๋ถ„์ด ๋“ ๋‹ค. ํ•ญ์ƒ ๊ฒฐ์‹ฌ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ค์šด ๊ฒƒ ๊ฐ™๋‹ค. ๋ฌผ๋ก  ์˜ค๋Š˜๋„ ์ตœ์„ ์„ ๋‹คํ•œ ํ•˜๋ฃจ์˜€์ง€๋งŒ, ์กฐ๊ธˆ์”ฉ ์ง€์น˜๋Š” ๊ฒƒ์ด ๋Š๊ปด์ ธ ๊ฑฑ์ •์ด๋“ ๋‹ค. ๋ฌธ์ œ๋Š” ํ•˜๋ฃจํ•˜๋ฃจ ์Œ“์—ฌ๊ฐ€๋Š” ๋ณต์Šต๋Ÿ‰์ด๋‹ค... ๊ทธ๋ž˜๊ณ  ๊ธ์ •์ ์ธ ๋งˆ์Œ์œผ๋กœ ํ•˜๋ฃจํ•˜๋ฃจ ์ตœ์„ ์„ ๋‹คํ• ๋ ค ๋…ธ๋ ฅ ํ•  ๊ฒƒ์ด๋‹ค!!!!

0๊ฐœ์˜ ๋Œ“๊ธ€