[18-1] ApolloServer 셋팅
[18-2] 웹서비스 구조
[18-3] 게시판 CRUD 만들기
[18-4] Firebase BAAS 서비스
📂 ApolloServer 설치
yarn add graphql
을 입력해 graphql을 설치yarn add apollo-server
를 입력해 apolloServer를 설치📂 기본 API 틀 생성 및 서버 열기
resolver (API)
typeDefs (API Docs)
npm ApolloServer 자료
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, }); const { url } = await startStandaloneServer(server); console.log(`🚀 Server ready at ${url}`);
기존에 연결한 데이터베이스 자료
const server = new ApolloServer({ typeDefs, resolvers, }); const AppDataSource = new DataSource({ type: "postgres", host: "34.64.201.140", port: 5013, username: "postgres", password: "postgres2022", database: "postgres", entities: [Board], synchronize: true, logging: true, }); AppDataSource.initialize() .then(() => { console.log("DB접속에 성공했습니다!!!"); }) .catch((error) => { console.log("DB접속에 실패했습니다!!!"); console.log("원인: ", error); });
최종
// const qqq: string = "안녕하세요~~"; // console.log(qqq); import { DataSource } from "typeorm"; import { Board } from "./Board.postgres"; import { ApolloServer } from "@apollo/server"; import { startStandaloneServer } from "@apollo/server/standalone"; // API-DOCS 만들기 const typeDefs = `#graphql #나만의 인풋 타입 => input 키워드로 만들기 input CreateBoardInput { writer: String title: String contents: String } # 나만의 리턴 타입 => type 키워드로 만들기 type MyBoard { number: Int writer: String title: String contents: String } type Query { fetchBoards: [MyBoard] } type Mutation { # 연습용(backend-example 방식) # createBoard(writer: String, title: String, contents: String): String # 실무용(backend-practice 방식) createBoard(createBoardInput: CreateBoardInput!): String } `; // API 만들기 const resolvers = { Query: { fetchBoards: async (parent: any, args: any, context: any, info: any) => { // 모두 꺼내기 const result = await Board.find(); // 한개만 꺼내기 // const result = await Board.findOne({ // where: { number: 3 }, // }); return result; }, }, Mutation: { createBoard: async (_: any, args: any) => { await Board.insert({ ...args.createBoardInput, // writer: args.createBoardInput.writer, // title: args.createBoardInput.title, // contents: args.createBoardInput.contents, }); return "게시글 등록에 성공했어요!!"; }, // updateBoard: async () => { // // 3번 게시글을 영희로 바꿔줘! // await Board.update({ number: 3 }, { writer: "영희" }); // }, // deleteBoard: async () => { // await Board.delete({ number: 3 }); // 3번 게시글 삭제해줘! // await Board.update({ number: 3 }, { isDeleted: true }); // 3번 게시글 삭제했다 치자! (소프트삭제) => isDeleted가 초기값인 false 이면? 삭제 안된거, true 이면? 삭제 된거 // await Board.update({ number: 3 }, { deletedAt: new Date() }); // 3번 게시글 삭제했다 치자! (소프트삭제) => deletedAt이 초기값인 NULL 이면? 삭제 안된거, new Date() 들어가 있으면? 삭제 된거 // }, }, }; // @ts-ignore const server = new ApolloServer({ typeDefs, resolvers, }); const AppDataSource = new DataSource({ type: "postgres", host: "34.64.201.140", port: 5013, username: "postgres", password: "postgres2022", database: "postgres", entities: [Board], synchronize: true, logging: true, }); AppDataSource.initialize() .then(() => { console.log("DB접속에 성공했습니다!!!"); startStandaloneServer(server).then(() => { console.log("그래프큐엘 서버가 실행되었습니다!!!"); // 포트: 4000 }); }) .catch((error) => { console.log("DB접속에 실패했습니다!!!"); console.log("원인: ", error); });
웹서비스는 Front-end
서버, Back-end
서버 그리고 DataBase
로 이루어져있다.
💡 프론트엔드 서버
yarn dev해서 실행시키면서 생성된 포트가 동작하고 있는 컴퓨터를 프론트엔드 서버라고 한다.
//Board.postgres.ts 파일에서 BaseEntity를 입력했는지 확인합니다. import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm"; @Entity() export class Board extends BaseEntity{ @PrimaryGeneratedColumn("increment") number!: number; @Column({ type: "text" }) wrtier!: string; @Column({ type: "text" }) title!: string; @Column({ type: "text" }) contents!: string; }
Board.postgres.ts
파일 생성하고 위의 파일을 적고 index.ts
에서 import해서 사용한다.📂 조회하기 API 만들기
모두 조회하기 API
// resolvers const resolvers = { Query: { fetchBoards: async () => { const result = await Board.find(); console.log(result); return result; }, }, };
const typeDefs = ` type MyBoard { writer: String number: Int title: String contents: String } type Query { # 결과가 여러개이므로 배열에 담아서 보내줍니다. # GraphQL에서는 배열 안의 객체를 [객체]로 표기합니다. fetchBoards: [MyBoard] } `;
// resolvers const resolvers = { Query: { fetchBoard: async () => { const resultOne = await Board.findOne({ where: { number: 3 }, }); return resultOne; }, }, };
📂 생성하기 API 만들기
// resolvers const resolvers = { Mutation: { // parent vs args: 브라우저의 요청은 args로 인자를 받고, 다른 api의 요청은 parent로 인자를 받습니다. createBoard: async (parent: any, args: any, context: any, info: any) => { await Board.insert({ /* 1. 연습용(backend-example 방식) */ // writer: args.writer, // title: args.title, // contents: args.contents, /* 2. 실무용(backend-practice 방식) */ ...args.createBoardInput, }); return "게시글 등록에 성공했습니다."; }, }, };
const typeDefs = `#graphql # 인자로 들어가는 객체의 타입은 type이 아닌 input으로 작성합니다. input CreateBoardInput { writer: String title: String contents: String } type Mutation { # GraphQL에서는 문자열의 타입을 String으로 입력해주셔야 합니다. # 필수값인 경우에는 콜론(:) 앞에 !를 붙여주세요. # 1. 연습용(backend-example 방식) # createBoard(writer: String, title: String, contents: String): String # 2. 실무용(backend-practice 방식) createBoard(createBoardInput: CreateBoardInput): String } `;
firebase.ts
에 파이어베이스 자료를 담음// Import the functions you need from the SDKs you need import { initializeApp } from "firebase/app"; // import { getAnalytics } from "firebase/analytics"; // TODO: Add SDKs for Firebase products that you want to use // https://firebase.google.com/docs/web/setup#available-libraries // Your web app's Firebase configuration // For Firebase JS SDK v7.20.0 and later, measurementId is optional const firebaseConfig = { apiKey: "AIzaSyD70Gf9dsGhb8so52aHGIFQvpTktAIoNrg", authDomain: "mrpumpkin-98.firebaseapp.com", projectId: "mrpumpkin-98", storageBucket: "mrpumpkin-98.appspot.com", messagingSenderId: "924504847626", appId: "1:924504847626:web:9ca82445648b4cd83936f3", }; // Initialize Firebase export const firebaseApp = initializeApp(firebaseConfig);
index
파이어베이스 자료를 담음 자료에서 import해 기능을 구현import { collection, getFirestore, addDoc, getDocs } from "firebase/firestore"; import { firebaseApp } from "../../../src/commons/libraries/firebase"; export default function FirebasePage(): JSX.Element { const onClickSubmit = (): void => { const board = collection(getFirestore(firebaseApp), "board"); void addDoc(board, { writer: "재욱", title: "안녕하세요", contents: "반갑습니다.", number: 1, }); }; const onClickFetch = async (): Promise<void> => { const board = collection(getFirestore(firebaseApp), "board"); const result = await getDocs(board); const datas = result.docs.map((el) => el.data()); console.log(datas); }; return ( <> <button onClick={onClickSubmit}>등록</button> <button onClick={onClickFetch}>조회</button> </> ); }