GraphQL

스카치·2023년 2월 25일
0

Rest API와 GraphQl

// Rest Api : 요청하는 메소드와 url의 형태로 서버의 데이터를 조회, 수정 ,생성, 삭제하는 방식

//책 목록보기
axios.get(
	'https:// api.marktube.tv/vl/book',
    {headers: 'Bearer ${token}`},
)

// 책 추가하기
axios.post(
     'https:// api.marktube.tv/vl/book',
     {
    	title,
     	message,
     	author,
     	url,
    },
  {headers: `bearer ${token}`},

)
// 책 상세보기
axious.get( 
     'https:// api.marktube.tv/vl/book/${book.id}',
  {headers: `Bearer ${token}`},
)

// 책 수정하기
axious.patch( 
     'https:// api.marktube.tv/vl/book/${book.id}',
     {
    	title,
     	message,
     	author,
     	url,
    },
  {headers: `Bearer ${token}`},
)

//책 삭제하기
axios.delete(
	'https:// api.marktube.tv/vl/book/${book.id}',
    {headers: 'Bearer ${token}`},
)
     

단점은 결과물을 의도대로 받아올 수 없음(여러번 요청, 불필요한 데이터 포함 등)
==> GraphQL : query를 통해 원하는 부분만 가져올 수 있음

Apollo 를 이용해서 Node.js 서버 만들기

mkdir graphql-server
cd graphql-server
npm init -y
npm i apollo-server
npm i nodemon -D // 소스코드를 수정했을 때 자동으로 서버를 새로고침하기 위해 
npm i graphql
code . -r

index.js =>

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';

// The GraphQL schema
const typeDefs = `#graphql
  type Query {
    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, // localhost:4000 접속에 했을 때 playground 띄움
});

const { url } = await startStandaloneServer(server);
console.log(`🚀 Server ready at ${url}`);

package.json -> scripts =>

"dev" :"nodemon index.js"

npm run dev =>
playground==>

hello

typeDef와 resolver

typeDefs : 스키마 정의
resolvers = 스키마에 해당하는 구현체, 스키마에 해당하는 데이터를 리턴하는 function의 맵

여러개의 데이터 조회하기

index.js =>

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';

const { readFileSync } = requre('fs') // node의 api에서 파일을 읽는 함수
 
// The GraphQL schema
const typeDefs = `#graphql
  type Query {
    hello: String
	books : [Book] // Books를 배열 형태로 받겠다
	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 {  // 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(books => 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.boodId))
		  const newBook = {...args, bookID : maxId + 1}
          whiteFileSync(
            join(__dirname, 'books.json'),
			JSON.stringify([...book, 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
            }
          })
          const newBook = {...args, bookID : maxId + 1}
          whiteFileSync(
            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.bookdId)
          })
          const newBook = {...args, bookID : maxId + 1}
          whiteFileSync(
            join(__dirname, 'books.json'),
			JSON.stringify(newBooks)
        )
        return deleted
   		}
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  playground: true, // localhost:4000 접속에 했을 때 playground 띄움
});

const { url } = await startStandaloneServer(server);
console.log(`🚀 Server ready at ${url}`);

books.json =>

[
	{"bookID":1, "title":"title test". "message" : "message", "author": "author test", "url": "url test"}
]

playground =>

query {
	books {
    	bookId
        title
        message
        author
        url
    }
}

특정 데이터 조회하기

playground =>

query {
	book(bookId: 1) {
    	bookId
        title
        message
        author
        url
    }
}

데이터 추가하기

playground =>
// 데이터 추가

Mutation {
	addBook(title:"t", message:"m", author:"a", url:"u") {
    	bookId
        title
        message
        author
        url
    }
}

데이터 변경, 삭제하기

playground =>

// 데이터 변경
Mutation {
	editBook(bookId: 3, title:"t1", message:"m", author:"a", url:"u") {
    	bookId
        title
        message
        author
        url
    }
}

// 데이터 삭제
Mutation {
	deleteBook(bookId: 3) {
    	bookId
        title
        message
        author
        url
    }
}

0개의 댓글