DB 두번째시간.
데코레이터 원리(@):
역할==> 함수를 표현하기 쉽게 작성한것으로 즉, @가 붙은것이 함수라는 말.
ts-node는 폴더. 즉, node-modules에 있기에 그것을 기준으로 실행해야하니 package.json에 스크립트(scrips)로 명령어 추가해주기
제공을 요청하는 쪽이 클라이언트
제공하는쪽이 서버 ===> 둘은 누가 요청하느냐에따라 달라짐.
프론트엔드에서 사용했던 방법은 두가지.
rest-API를 사용하기위해 axios를 사용,
graphql-API를 사용하기위해 @apollo/client사용.(라이브러리 앞의 @는 회사명을 나타냄)
벡엔드에서 만들때는 다른 것을 이용한다.
rest의 경우는 express를 ,
graphql의 경우에는 apollo-server를 사용하였다.
오늘 실습도구로 사용한것은 apollo-server였다.
npm에서 검색을 해보았다. 그런데 강의와는 달리 위쪽에 결과가뜨지 않아 찾아보았다.
This package has been deprecated
Theapollo-server
package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the@apollo/server
package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.
이러한 메시지가 위
쪽에 써있고 현재는 대충 사용되지 않는다는 말 같아 파파고를 돌려보았더니
이 패키지는 더 이상 사용되지 않습니다.
아폴로 서버 패키지는 아폴로 서버 v2와 v3의 일부로 현재는 사용되지 않는다(2023년 10월 22일 수명 만료). 이 패키지의 기능은 이제 "@apolo/server" 패키지에 있습니다. 자세한 내용은 https://www.apollographql.com/docs/apollo-server/previous-versions/을 참조하십시오.
라고 번역되었다...
그래도 일단 이것으로 수업을 하니 다운명령어
yarn add apollo-sever graphql
으로 설치를 했다.
그 아래쪽에 있는 세팅부분도 복사해 붙여놓았다.
const typeDefs= 이라고 적혀 있는 부분이 Docs부분이고
그 아래
const resolvers = 라고 적힌부분이 API라고 하는데 그러한 설명이 무슨말인지 처음에는 이해를 못했다.
알고보니 그래프 큐앨처럼 옆에 나와있는 Docs을 적는 부분이
typeDefs였다.
세팅의 맨 아랫부분에 server.listen()부분이 있는데 이부분을 풀이해보면 일단 서버라는건 24시간 접속을 기다리는 것이다. 그래서 전체를 보면 지금부터 24시간 기다리겠다는 서버 실행부분이라고 할 수 있다.
세팅이 다 끝나고 실행을 해야하니 맨 아랫쪽 부분으로 보낸다.
`AppDataSource.initialize()
.then(() => {
console.log("DB접속에 성공했습니다!!!");
//DB연결까지 모두 끝나고 가장 마지막에 실행. 다른사람들의 접속을 기다리기 위해서
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});`
이렇게.
url 부분은 서버 주소이다. listen에 아무것도 적어주지않으면 포트번호는 default로 4000이 실행된다.
수업에서는 default가 3000이라고 했는데 4000이 실행된걸 보니 아마 4000이 default?
모든 주소에는 포트번호가 있다. 다만, 포트번호가 default 인경우에는 생략이 가능하다.
http://.....:80
https://.... :443
기본적으로 http는 80번, https는 443번을 가진다.
따라서 포트번호가 쓰여있지 않은 경우에는 기본포트를 사용했다는 의미이다.
작업을 하면서
`//Docs와 API합쳐 서버 만듬
const server = new ApolloServer({
typeDefs,
resolvers,
cors: true,
});`
cors허용여부도 결정할 수 있다.
아예 막아놓거나 ==>cors:false
또는 일부만 열어두는 형식이다.
//선택한 사이트만 cors풀어주고 싶을때 // cors:{ // origin:["http://naver.com","http://qqq.com"] // }
origin부분에 대괄호로 허용해주고 싶은 사이트 주소를 넣어주면된다.
Docs 부분에는 각 타입을,
API라고 한 리졸버 부분에는 query할것, mutation할 것을 적어주면된다.
// const { ApolloServer, gql } = require("apollo-server"); => 옛날방식(commonjs)
import { ApolloServer, gql } from "apollo-server"; // => 요즘방식(module)
위의 const {} 로 되어있는 것이 알고보니 import 부분이었다.
common js라는 옛날 방식으로 적어둔 것으로 저 방식은 require부분에서 모두 가져온 뒤 일부만 뽑아쓰는것이기에 용량을 많이 차지한다.
반면 import 로 가져오는 module방식은 애초부터 중괄호의 것만 가져오기에 훨씬 용량? 을 덜 차지한다고 할 수 있겠다.
input CreateBoardInput { # 입력에 들어가는 타입은 반드시 input이라고 바꾸기
writer: String
title: String
contents: String
}
type MyBoard {
number: Int
writer: String
title: String
contents: String
}
type Query {
fetchBoards: [MyBoard]
}
const resolvers = {
Query: {
fetchBoards: async () => {
// 모두꺼내기
const result = await Board.find();
// 한개만 골라 꺼내기
// Board.findOne({where: {number:3}})
return result; // 배열안의 객체 형태[{number:1,writer:"철수",title:"안녕하세요~",contents:"반갑습니다~~"},{},{}...]
},
},
Mutation: {
createBoard: async (parent: any, args: any, context: any, info: any) => {
await Board.insert({ // ==>insert 등록하기
// 데이터 넣기. 등록되는동안 기다려야함
// 하나하나 모두 입력하는 방식
// writer: args.createBoardInput.writer,
// title: args.createBoardInput.title,
// contents: args.createBoardInput.contents,
...args.createBoardInput, // 가운데 알맹이만 뽑으면 스프레드로 한번에 표현가능, 위와 동일함
});
args ? ==> 입력값으로 들어온 즉, 브라우저에서 받아온 값들이 들어옴.
==> 브라우저에서 API요청시 인자들이 args로 들어온다.
parent ==> API에서 API를 호출시 들어오는 곳.
context ==> 요청 정보들
info ==> 기타 그래프 큐엘 정보가 들어옴.
벡엔드 없이 프론트 엔드에서 DB에 저장하는 법.
FireBase라는 서비스를 사용해보았다.
FireBase ==> 데이터 베이스와 백엔드를 제공하는 서비스로 BaaS라고 한다.
BaaS ==> Backend As A Service
의 준말로 FireBase는 구글 벡엔드가 브라우저에서 보낸 데이터를 받아 DB에 저장하는 방식이다.
BaaS외 SaaS, PaaS, Iaas 등도 있는데 현 시점에서는 중요하지 않으니 일단 넘어가자.
FireBase이용하기:
검색창에 검색 ==> 세 프로젝트 만들기 ==> 원하는이름 입력후 배포를 하여 나중애 접속자, 이탈률 등을 볼거면 구글에널리틱스 부분을 체크하면 나중에 그 사이트에 접속해 코드를 발급받고 그것을 해드태그 부분에 붙여넣으면 볼 수 있으나 현재는 단순히 실습용이기에 체크해제==> 계속 ==> </> 웹표시 클릭 ==> 앱등록 닉네임. 일단 프로젝트이름과 통일 ==> 호스팅은 배포관연. 현재는 사용안하니 체크 안하고 넘어가기 ==> 앱등록 ==> npm사용체크 ==> npm install 부분을 yarn 을 사용하니
yarn add firebase
로 프론트엔드실습폴더에 설치.
==> 아랫부분 설정내용 복사해 _app.tsx의 import부분쪽에 붙여넣기
==> 콘솔로 이동 클릭 ==> 왼쪽 빌드 라는부분클릭, storage는 사진을 저장하는 부분.
hosting은 배포시
DB 사용하는 것이 두가지가 있음.
-Firestore Database ==> 데이터를 등록, 조회하는 일반적인 방식.
-Realtime Database ==> 실시간 데이터 베이스.
채팅 만들때 사용하는 것으로 원래 request를 날리고 response하는 것이 일반적이나 이 경우에는 DB만 바뀌면 바뀐내용을 받을 수 있게 전송한다.
보통 채팅구연시에는 웹소켓이라는것을 사용하는데 같은것이라고 보면 된다.
단순히 등록, 조회만 해보기위해 Firestore Database 를 선택 ==> 데이터베이스 만들기 클릭 ==> 프로덕션은 배포용이기에 그 아래 테스트 모드 클릭, ==> 데이터 저장될위치 (서울)asia-northeast3선택 ==> 사용설정 클릭
그러면 아래쪽?에 컬랙션 추가가 있는데 눌러보면 문서추가 라는 말이 있다.
? 문서??
NoSQL에서 문서로 저장한다는 말을 했었다.
따라서 이것은 NoSQL 방식!!
SQL과 NoSQL은 둘다 장점과 단점이 존재한다.
SQL의 경우는 일일이 적어줘야한다는 게 단점이고, 등록된 데이터 이외는 넣지 못한다.
NoSQL은 넣는대로 다 들어가고 따라서 쉽게 사용이 가능하지만, 규모가 커질수록 어떤데이터가 들어갔는지 알기가 어렵다.
따라서 큰 규모에서는 복잡하나 안정적인 SQL방식을 이용하는것이 대부분이다.
위쪽의 문서로 이동 부분을 클릭 ==> 빌드 ==> firestore를 들어가면 docs를 볼 수 있다.
그걸보고 설정을 하는것인데... 다시 읽어봐도 뭐를 어디서 가져왔는지 왜 이렇게 쓰여있는지... 하나로 합쳐진게 없으니 추측만 해보았다.
`import {
collection,
addDoc,
getDocs,
getFirestore,
} from "firebase/firestore/lite";
import { firebaseApp } from "../_app";export default function FirebasePage() {
const onClickSubmit = async () => {
const board = collection(getFirestore(firebaseApp), "board"); // 없으면 만들어서 등록됨
await addDoc(board, {
writer: "철수",
title: "제목입니다",
contents: "내용이에요",
});
};const onClickFetch = async () => {
const board = collection(getFirestore(firebaseApp), "board");
const result = await getDocs(board);
const datas = result.docs.map((el) => el.data());
console.log(datas);
};
return (
<>
등록하기
조회하기
</>
);
}
`
collection은 문서, addDocs로는 문서 추가,getDocs로는 문서를 받아볼수 있는 것이다.
저 firebaseApp 라는 부분은 app.tsx에 설정해준 곳에서 받아온 것.
등록 버튼을 누르면 board라는 데이터? 에 등록되는데 막약 없다면 자동으로 생성해 등록된다.
그리고 조회버튼을 누르면 문서에서 getDocs로 조회되어 콘솔창에 찍힌다.
배열형태로 result안에 doc가 들어오고 묶여있기에 그것들을 하나하나 뽑아줘야하기에 map을 사용했다.
아직 Docs 보는것이 익숙지 않은 탓인지 골라보기가 안되어 실습이 어려웠다. 천천히 한단계씩 나아가자...