๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ’ฌ/ใ…ใ……ใ…Œใ…‹ใ…ใ…… ์ฑŒ๋ฆฐ์ง€

46์ผ์ฐจ

๐Ÿฆซ

46์ผ์ฐจ

 

Part 14. GraphQL ๋ง›๋ณด๊ธฐ (Server ๋งŒ๋“ค๊ธฐ)

 


 

 

Part 14. GraphQL ๋ง›๋ณด๊ธฐ (Server ๋งŒ๋“ค๊ธฐ)

 

 

https://slides.com/woongjae/graphql2021

 

GraphQL 2021

๊ทธ๋ž˜ํ”„ํ์—˜ 2021

slides.com

 

https://graphql.org/

 

GraphQL | A query language for your API

Evolve your APIwithout versions Add new fields and types to your GraphQL API without impacting existing queries. Aging fields can be deprecated and hidden from tools. By using a single evolving version, GraphQL APIs give apps continuous access to new featu

graphql.org

 

 

 ๐Ÿ”— Apollo ๋ฅผ ์ด์šฉํ•ด์„œ Node.js ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ 

 

https://github.com/apollographql/apollo-server

 

GitHub - apollographql/apollo-server: ๐ŸŒ  Spec-compliant and production ready JavaScript GraphQL server that lets you develop

๐ŸŒ  Spec-compliant and production ready JavaScript GraphQL server that lets you develop in a schema-first way. Built for Express, Connect, Hapi, Koa, and more. - GitHub - apollographql/apollo-server...

github.com

 

$ npm i apollo-server graphql

$ npm i nodemon -D

 

// ./index.js

const { ApolloServer, gql } = require("apollo-server");

// The GraphQL schema
const typeDefs = gql`
  type Query {
    "A simple type for getting started!"
    hello: String
  }
`;

// A map of functions which return data for the schema.
const resolvers = {
  Query: {
    hello: () => "world",
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  playground: true, // โญ
});

server.listen().then(({ url }) => {
  console.log(`๐Ÿš€ Server ready at ${url}`);
});
// package.json

{
  ...
  "scripts": {
    "dev": "nodemon index.js" // $ npm run dev
  },
  ...
}

 

 

 ๐Ÿ”— typeDef ์™€ resolver 

 

  • typeDef(s)
    • GraphQL Schema ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ณณ
      • โ€‹Object
      • Query
      • Mutation
      • Input
    • gpl ๊ณผ Tagged Template Literals ๋กœ ์ž‘์„ฑํ•œ๋‹ค.
  • resolver(s)
    • Schema ์— ํ•ด๋‹นํ•˜๋Š” ๊ตฌํ˜„์„ ํ•˜๋Š” ๊ณณโ€‹
    • ์š”์ฒญ์„ ๋ฐ›์•„ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒ, ์ˆ˜์ •, ์‚ญ์ œ

 

 

 ๐Ÿ”— ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฐ์ดํ„ฐ ์กฐํšŒํ•˜๊ธฐ - Query 

 

// ./index.js

const { ApolloServer, gql } = require("apollo-server");
const { readFileSync } = require("fs");
const { join } = require("path");

// The GraphQL schema
const typeDefs = gql`
  type Query {
    "A simple type for getting started!"
    hello: String
    books: [Book]
  }

  type Book {
    bookId: Int
    title: String
    message: String
    author: String
    url: String
  }
`;

// A map of functions which return data for the schema.
const resolvers = {
  Query: {
    hello: () => "world",
    books: () => {
      return JSON.parse(readFileSync(join(__dirname, "books.json")).toString());
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  playground: true,
});

server.listen().then(({ url }) => {
  console.log(`๐Ÿš€ Server ready at ${url}`);
});
// ./books.json

[
  {
    "bookId": 1,
    "title": "titke test",
    "message": "message test",
    "author": "author test",
    "url": "url test"
  },
  {
    "bookId": 2,
    "title": "titke test 2",
    "message": "message test 2",
    "author": "author test 2",
    "url": "url test 2"
  }
]

 

 

 ๐Ÿ”— ํŠน์ • ๋ฐ์ดํ„ฐ ์กฐํšŒํ•˜๊ธฐ - Query 

 

// ./index.js

const { ApolloServer, gql } = require("apollo-server");
const { readFileSync } = require("fs");
const { join } = require("path");

// The GraphQL schema
const typeDefs = gql`
  type Query {
    "A simple type for getting started!"
    hello: String
    books: [Book]
    book(bookId: Int): Book
  }

  type Book {
    bookId: Int
    title: String
    message: String
    author: String
    url: String
  }
`;

// A map of functions which return data for the schema.
const resolvers = {
  Query: {
    hello: () => "world",
    books: () => {
      return JSON.parse(readFileSync(join(__dirname, "books.json")).toString());
    },
    book: (parent, args, context, info) => {
      const books = JSON.parse(
        readFileSync(join(__dirname, "books.json")).toString()
      );
      return books.find((book) => book.bookId === args.bookId);
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  playground: true,
});

server.listen().then(({ url }) => {
  console.log(`๐Ÿš€ Server ready at ${url}`);
});

 

 

 ๐Ÿ”— ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ํ•˜๊ธฐ - Mutation 

 

// ./index.js

const { ApolloServer, gql } = require("apollo-server");
const { readFileSync, writeFileSync } = require("fs");
const { join } = require("path");

// The GraphQL schema
const typeDefs = gql`
  type Query {
    "A simple type for getting started!"
    hello: String
    books: [Book]
    book(bookId: Int): Book
  }

  type Mutation {
    addBook(title: String, message: String, author: String, url: String): Book
  }

  type Book {
    bookId: Int
    title: String
    message: String
    author: String
    url: String
  }
`;

// A map of functions which return data for the schema.
const resolvers = {
  // ๋ฐ์ดํ„ฐ ์กฐํšŒ
  Query: {
    hello: () => "world",
    books: () => {
      return JSON.parse(readFileSync(join(__dirname, "books.json")).toString());
    },
    book: (parent, args, context, info) => {
      const books = JSON.parse(
        readFileSync(join(__dirname, "books.json")).toString()
      );
      return books.find((book) => book.bookId === args.bookId);
    },
  },
  // ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€
  Mutation: {
    addBook: (parent, args, context, info) => {
      const books = JSON.parse(
        readFileSync(join(__dirname, "books.json")).toString()
      );
      const maxId = Math.max(...books.map((book) => book.bookId));
      const newBook = { ...args, bookId: maxId + 1 };
      writeFileSync(
        join(__dirname, "books.json"),
        JSON.stringify([...books, newBook])
      );
      return newBook;
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  playground: true,
});

server.listen().then(({ url }) => {
  console.log(`๐Ÿš€ Server ready at ${url}`);
});

// ./books.json

[{"bookId":1,"title":"titke test","message":"message test","author":"author test","url":"url test"},{"bookId":2,"title":"titke test 2","message":"message test 2","author":"author test 2","url":"url test 2"},{"title":"t","message":"m","author":"a","url":"u","bookId":3}]

 

 

 ๐Ÿ”—  ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝํ•˜๊ธฐ - Mutation 

// ./index.js

const { ApolloServer, gql } = require("apollo-server");
const { readFileSync, writeFileSync } = require("fs");
const { join } = require("path");

// The GraphQL schema
const typeDefs = gql`
  type Query {
    "A simple type for getting started!"
    hello: String
    books: [Book]
    book(bookId: Int): Book
  }

  type Mutation {
    addBook(title: String, message: String, author: String, url: String): Book
    editBook(
      bookId: Int
      title: String
      message: String
      author: String
      url: String
    ): Book
  }

  type Book {
    bookId: Int
    title: String
    message: String
    author: String
    url: String
  }
`;

// A map of functions which return data for the schema.
const resolvers = {
  // ๋ฐ์ดํ„ฐ ์กฐํšŒ
  Query: {
    hello: () => "world",
    books: () => {
      return JSON.parse(readFileSync(join(__dirname, "books.json")).toString());
    },
    book: (parent, args, context, info) => {
      const books = JSON.parse(
        readFileSync(join(__dirname, "books.json")).toString()
      );
      return books.find((book) => book.bookId === args.bookId);
    },
  },

  // ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ & ๋ณ€๊ฒฝ & ์‚ญ์ œ
  Mutation: {
    // ์ถ”๊ฐ€
    addBook: (parent, args, context, info) => {
      const books = JSON.parse(
        readFileSync(join(__dirname, "books.json")).toString()
      );
      const maxId = Math.max(...books.map((book) => book.bookId));
      const newBook = { ...args, bookId: maxId + 1 };
      writeFileSync(
        join(__dirname, "books.json"),
        JSON.stringify([...books, newBook])
      );
      return newBook;
    },

    editBook: (parent, args, context, info) => {
      const books = JSON.parse(
        readFileSync(join(__dirname, "books.json")).toString()
      );
      const newBooks = books.map((book) => {
        if (book.bookId === args.bookId) {
          return args;
        } else {
          return book;
        }
      });
      writeFileSync(join(__dirname, "books.json"), JSON.stringify(newBooks));
      return args;
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  playground: true,
});

server.listen().then(({ url }) => {
  console.log(`๐Ÿš€ Server ready at ${url}`);
});

// ./package.json

[{"bookId":1,"title":"titke test","message":"message test","author":"author test","url":"url test"},{"bookId":2,"title":"titke test 2","message":"message test 2","author":"author test 2","url":"url test 2"},{"bookId":3,"title":"t1","message":"m","author":"a","url":"u"}]

 

 

 ๐Ÿ”—  ๋ฐ์ดํ„ฐ ์‚ญ์ œํ•˜๊ธฐ - Mutation 

 

// ./index.js

const { ApolloServer, gql } = require("apollo-server");
const { readFileSync, writeFileSync } = require("fs");
const { join } = require("path");

// The GraphQL schema
const typeDefs = gql`
  type Query {
    "A simple type for getting started!"
    hello: String
    books: [Book]
    book(bookId: Int): Book
  }

  type Mutation {
    addBook(title: String, message: String, author: String, url: String): Book
    editBook(
      bookId: Int
      title: String
      message: String
      author: String
      url: String
    ): Book
    deleteBook(bookId: Int): Book
  }

  type Book {
    bookId: Int
    title: String
    message: String
    author: String
    url: String
  }
`;

// A map of functions which return data for the schema.
const resolvers = {
  // ๋ฐ์ดํ„ฐ ์กฐํšŒ
  Query: {
    hello: () => "world",
    books: () => {
      return JSON.parse(readFileSync(join(__dirname, "books.json")).toString());
    },
    book: (parent, args, context, info) => {
      const books = JSON.parse(
        readFileSync(join(__dirname, "books.json")).toString()
      );
      return books.find((book) => book.bookId === args.bookId);
    },
  },

  // ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ & ๋ณ€๊ฒฝ & ์‚ญ์ œ
  Mutation: {
    // ์ถ”๊ฐ€
    addBook: (parent, args, context, info) => {
      const books = JSON.parse(
        readFileSync(join(__dirname, "books.json")).toString()
      );
      const maxId = Math.max(...books.map((book) => book.bookId));
      const newBook = { ...args, bookId: maxId + 1 };
      writeFileSync(
        join(__dirname, "books.json"),
        JSON.stringify([...books, newBook])
      );
      return newBook;
    },

    editBook: (parent, args, context, info) => {
      const books = JSON.parse(
        readFileSync(join(__dirname, "books.json")).toString()
      );
      const newBooks = books.map((book) => {
        if (book.bookId === args.bookId) {
          return args;
        } else {
          return book;
        }
      });
      writeFileSync(join(__dirname, "books.json"), JSON.stringify(newBooks));
      return args;
    },

    deleteBook: (parent, args, context, info) => {
      const books = JSON.parse(
        readFileSync(join(__dirname, "books.json")).toString()
      );
      const deleted = books.find((book) => book.bookId === args.bookId);
      const newBooks = books.filter((book) => book.bookId !== args.bookId);
      writeFileSync(join(__dirname, "books.json"), JSON.stringify(newBooks));
      return deleted;
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  playground: true,
});

server.listen().then(({ url }) => {
  console.log(`๐Ÿš€ Server ready at ${url}`);
});

// ./package.json

[{"bookId":1,"title":"titke test","message":"message test","author":"author test","url":"url test"},{"bookId":2,"title":"titke test 2","message":"message test 2","author":"author test 2","url":"url test 2"}]

 

'๐Ÿ’ฌ > ใ…ใ……ใ…Œใ…‹ใ…ใ…… ์ฑŒ๋ฆฐ์ง€' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

48์ผ์ฐจ  (0) 2022.03.30
47์ผ์ฐจ  (0) 2022.03.29
45์ผ์ฐจ  (0) 2022.03.28
43, 44์ผ์ฐจ  (0) 2022.03.26
42์ผ์ฐจ  (0) 2022.03.26