18일차)[React/JS] CORS / 백엔드서버 만들기(API)

김재범·2022년 7월 28일
0

코드캠프

목록 보기
21/46
post-thumbnail

✍map과 forEach의 차이

방식은 똑같지만 return이 되냐 안되냐의 차이

💡 return 안하고 state에 저장만 할꺼면 foreach의 성능이 낫다.

✍CORS(Cross Origin Resource Sharing)

교차된 상태에서 데이터를 쉐어링 해줄 수 있는가?
YES or No

aaa.com에서 mystic.com 백엔드 API를 받아오려면
백엔드에서 CORS를 반드시 허용해줘야 함

※ 앱과 백엔드는 주소가 없기 때문에 요청이 가능(브라우저는 불가능)

브라우저가 백엔드에 데이터 요청을 2번 보내게 되는데(preflight(options),graphql)

먼저 preflight에서 CORS 허용인지 아닌지를 포함해서 백엔드를 줌
-> CORS유무에 따라 브라우저가 보낼지 말지 결정

프록시 서버

이렇게 백엔드에서 우회해서 서버를 받을 수 있도록 하는 데 이를 프록시 서버라 한다.

✍백엔드 서버

📌브라우저에서 api를 요청할 수 있도록 ApolloServer 세팅

  1. graphql을 이용해서 api를 만들기 때문에 이를 위한 apollo-server 설치
    yarn add apollo-server

  2. 아폴로 서버 생성을 위해 typeDefs(API type) 와 resolver(API) 필요

1) API 타입 지정(typeDefs)

 type Query {
    fetchProducts: [Product]
    fetchProduct(productId: ID): Product
  }

  type Mutation {
    createProduct(
      seller: String!
      createProductInput: CreateProductInput!
    ): String

    updateProduct(
      productId: ID
      updateProductInput: UpdateProductInput!
    ): String

    deleteProduct(productId: ID): String
  }

2) API 생성(resolver)

const resolvers = {
  Query: {
    fetchProducts: async () => {  
      const result = await Product.find();
      console.log(result);
      return result;
    },
    fetchProduct: async (_: any, args: any) => {
      const result = await Product.findOne({
        where: { _id: args.productId },
      });

      return result;
    },
  },

  Mutation: {
    createProduct: async (_: any, args: any) => {
      await Product.insert({
        seller: args.seller,
        ...args.createProductInput,

        // writer: args.createBoardInput.writer,
        // title: args.createBoardInput.title,
        // contents: args.createBoardInput.contents,
      });

      return "게시물 등록에 성공했습니다!!";
    },
    updateProduct: async (_: any, args: any) => {
      await Product.update(
        { _id: args.productId },
        { ...args.updateProductInput }
      );
      return "게시물 수정에 성공했습니다!!";
    },

    deleteProduct: async (_: any, args: any) => {
      await Product.update({ _id: args.productId }, { deletedAt: new Date() });

      return "게시물 삭제에 성공했습니다!!";
    },
  },
};
  1. ApolloServer 만들기

// typeDefs와 resolvers는 위에 우리가 만들어준 타입과 api 입니다.
const server = new ApolloServer({
	typeDefs :  typeDefs,
	resolvers : resolvers,
	cors : true
})
  1. 서버 24시간 열고 접속 기다리기
AppDataSource.initialize().then(() => {
  // DB 접속 성공시 실행
  console.log("DB 연결 성공!!")
  server.listen({ port: 4000 }).then(() => {
		// 서버접속 완료시 콘솔 표기
    console.log("서버 실행 성공!")
  })
})

위의 기본 기능들을 사용하기 위해 postgres.ts 파일에서 💡BaseEntity를 사용

//Board.postgres.ts 파일
//Board 테이블
import { Column, Entity, PrimaryGeneratedColum, BaseEntity } from "typorm"

 @Entity() 
	export class Board extends BaseEntity{
           // Primary GenrateCOlum은 자동으로 생성되는 값(번호, 아이디 등)		
			@PrimaryGenerateColumn(’increment’) 
			number: number;
			
		// 데이터베이스의 타입을 임의로 바꾸고 싶다면 아래와 같이 안에 적기
			@Column({type : “text”})
			writer: string;
			
			@Column()
			title: string;
			
			@Column()
			contents: string;
}

📌API 만들기 createBoard

1) 받아올 인자의 타입을 지정해주기

import {Board} from "Board.postgres.ts 경로"

const typeDefs = gql`
	// 인풋값의 타입을 객체로 묶어 따로 지정
input CreateBoardInput {
		writer : String!,
		title : String!,
		contents : String!
	}

 type Mutation {
		createBoard(createBoardInput:CreateBoardInput) : String
	}

// 인풋과 타입의 차이점은 type은 받아올 때만, input은 입력값을 넣을 때 사용

2) API 만들기(resolvers)

const resolvers = {
mutation : {
  //인자에는 parent와 args가 있는데 쓰지 않는 parent 부분은 _ 넣기
	createBoard : async (_: any , args: any){ 
		// Board 테이블에 값넣기  ---> 백엔드에서 데이터 베이스에 값을 넣어주는 부분.
			await Board.insert({
				...args.CreateBoardInput
				// writer : args.CreateBoardInput.writer,
				// title : args.CreateBoardInput.title,
				// contents : args.CreateBoardInput.contents
			})
			return "createBoard 요청이 완료되었습니다."
		}
	}
    

📌API 만들기 fetchBoard

1) 받아올 인자의 타입을 지정해주기

const typeDefs = gql`
	type Board {
			wirter : String
			number : Int
			title : String
			contents : String
			}
	type Query {
			
			fetchBoards : [Board]
			}
//여러개 가지고 오기 때문에 타입을 [Board]라는 배열에 담아서 보내준다

2) API 만들기(resolvers)

Query : {
	// 누군가 해당 api를 요청했다면 아래의 함수가 실행
	fetchBoards: async(){
			// 여러개 조회할땐 find, 하나만 조회할땐 findOne
			// isDelete는 삭제때문에 들어간 내용이니 아래에서 확인
		result = await Board.find({ where : {writer : "철수"}, isDelete : false })
		return 
		}
	},

📌deleteBoard API 만들기

1) API 만드는부분

const resolvers = {
mutation : {
	deleteBoards: async(_:any, args){
		//update에는 2가지. 앞에는 조건, 뒤에는 변경내용
		await Board.update({ number : args.number },{deleteAt : new Date()})
		return 
		}
	},

※ ❗❗실무에서는 실제로 삭제하지 않음❗❗

Board.update({ number: 3 }, { isDeleted: true}) 또는,
Board.update({ number: 3 }, { deletedAt: new date()});
을 사용하여 업데이트로 삭제된 부분을 표시

profile
지식을 쌓고 있습니다.

0개의 댓글