[TIL] CRUD 만들기 / Firebase BAAS 서비스

우기·2023년 4월 5일
0
post-thumbnail

📒 오늘 공부한 내용

🔍수업목차

[18-1] ApolloServer 셋팅
[18-2] 웹서비스 구조
[18-3] 게시판 CRUD 만들기
[18-4] Firebase BAAS 서비스

✅ ApolloServer 셋팅


📂 ApolloServer 설치

  • 터미널에 yarn add graphql 을 입력해 graphql을 설치
  • 터미널에 yarn add apollo-server 를 입력해 apolloServer를 설치

📂 기본 API 틀 생성 및 서버 열기

  • 서버를 생성하는데에는 두가지가 필요하다.
    • resolver (API)
    • typeDefs (API Docs)
  • @apollo/server
  • Database를 연결한 index.ts 파일에 아래의 코드를 추가

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로 이루어져있다.

  • 서버라고 하면, 24시간 켜져있는 서버 프로그램이 동작하고 있는 컴퓨터를 의미한다.

💡 프론트엔드 서버

yarn dev해서 실행시키면서 생성된 포트가 동작하고 있는 컴퓨터를 프론트엔드 서버라고 한다.

✅ 게시판 CRUD 만들기


  • 테이블의 데이터를 삭제하고 추가하고 수정하는 일이 생길 수 있다.
//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]
      }
    `;
  • 한 개만 조회하기 API
    // 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 BAAS 서비스


  • 프론트엔드 개발자가 백엔드 없이 데이터를 Firebase에 직접 넣을 수 있다.

  • 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>
    </>
  );
}
profile
개발 블로그

0개의 댓글