강아지 9마리를 같이 띄워줘야 하니까 prev앞에 ...으로 스프레드 시킨 다음에, result.data.messagedp 현재 강아지사진을 추가해준다.
그래서 총 9마리 강아지가 화면에 보여지게 되는 것 !
(cross origin resource sharing)
cors 에러
: openAPI 업체에서 보안상의 이유로 아무 브라우저나 허용하지 않게 되면, 브라우저에서 받을수가 없게 되고 cors에러를 보게 된다!
(ex, 네이버에서 카카오 api 요청하면)
graphql을 이용해서 api를 만들어야 하기 때문에 apollo-server 설치 (rest-API는 express 사용)
아폴로 서버를 생성하려면
resolver(api)
,typeDefs(api type)
두가지가 필요하다
// 1. 타입만들기 => typeDefs const myTypeDefs = gql` input CreateBoardInput { writer: String title: String contents: String } # input 으로 안하고 앞에 type으로 하면 오류남 type Board { number: Int writer: String title: String contents: String } type Query { fetchBoards: [Board] # Board가 객체 형태니까 배열로 바꿔주기 위해서 괄호로 감싸주기 [] } type Mutation { # createBoard(writer: String, title: String, contents: String): String # 연습용(example api에서 이런식으로 작성했음) createBoard(createBoardInput: CreateBoardInput): String # freeboard api에서는 createBoard(createBoardInput: CreateBoardInput): String 이렇게 작성 } `; // 2. 함수(API)만들기 => resolvers const myResolvers = { Query: { fetchBoards: async () => { //브라우저에 요청한 패치보드가 여기서 실행됨 const result = await Board.find(); //이 보드는 Board.postgres.ts 의 Board table //게시글 목록 fetch 해야하니까 .find 로 찾아옴 //find() : 목록 조회하기, findOne() : 한 개 찾아오기 return result; //요청했을 때 응답으로 받을 수 있음 //DB에서 꺼내서 result에 저장한 값을 리턴해오기 //return의 type과 myTypeDefs Query의 타입이 일치해야 함 ( [Board]) }, }, Mutation: { createBoard: async (_: any, args: any) => { // 브라우저에 요청한 크리에이트보드가 여기서 실행됨 // parent, args, context, info 총 4개의 인자가 들어옴 // parent : api에서 api 요청할 때 넣어주는 애 // args : 브라우저에서 입력한 데이터(프론트엔트) (wrter:"철수") (주로 args 많이 사용함! parent는 지금 안쓰니까 _ 언더바처리) // context : 로그인정보, info : api정보 await Board.insert({ ...args.createBoardInput, // writer: args.createBoardInput.writer, // title: args.createBoardInput.title, // contents: args.createBoardInput.contents, // freeboard.api에서는 이렇게 바뀜! // writer: args.writer, // title: args.title, // contents: args.contents, // 연습용 api에서는 ...args 로 쓸 수 있음 }); // 게시글을 데이터에 넣어줘야 하니까 .insert() 로 넣어줌 // number는 자동으로 생성됨 // 수정의 경우 // Board.updata({writer: "철수"}, {title: "제목2"}) // 삭제의 경우 // Board.delete({writer: "철수"}) // 실무에서 데이터의 삭제는 굉장히 민감한 부분이기 때문에 실제로 삭제하는것이 아니라 삭제한것처럼 보여줌 // 1. column을 새롭게 만들고 isDelete의 불린값만 true로 바꿔줌, 그다음 isDelete가 false인 데이터들만 보여주면 된다 // 2. 삭제 시간을 명시해준다, 그다음 deleteAt이 null값인 데이터들만 보여주면 된다 // Board.delete({writer: "철수"} {isDeleted: true} {deleteAt: new Date()}) return "게시물 등록에 성공했습니다!"; // 요청했을 때 응답으로 받을 수 있음 }, }, }; // ApolloServer 만들어주기 const server = new ApolloServer({ typeDefs: myTypeDefs, // API type resolvers: myResolvers, // API }); // DataSource: 접속 정보 작성하는곳 const AppDataSource = new DataSource({ type: "postgres", host: "34.64.124.242", port: 5028, username: "postgres", password: "postgres2022", database: "postgres", entities: [Board], // table 이름 입력 synchronize: true, // DB랑 VScode 동기화 logging: true, // 뭐 할때마다 로그 찍기 }); AppDataSource.initialize() //이 접속 정보로 연결 시켜조 .then(() => { //.then() 성공했을때 console.log("연결성공"); // 백엔드 API를 리슨(24시간동안 접속가능하게 대기상태로 만들어주기) server .listen(4000) .then(() => { console.log("서버 실행 성공!"); }) .catch(() => { console.log("서버 실행 실패ㅜ"); }); }) //.catch() 실패했을떄 .catch(() => { console.log("연결실패"); });
yarn dev 결과
mutation 해주기
Firebase
란?
프론트엔드 개발자가 백엔드 없이
데이터를 Firebase 에 직접 넣어줄 수 있게 해주는 것
- Firebase 세팅하기
- _app.tsx 에서 키 설정 하기
- 등록, 조회 실습
++
1. 나는 레이아웃에서 navigation 부분에서 메뉴 선택할 때 onclick 함수를 여러개 만들어서 각 각 따로 해줬었는데,
배열로 묶어즈고, map으로 묶어준 다음, router.push를 event.target.id 로 주면 하나하나 다 따로 안만들어도 될 것 같다!! 효율적으로 리팩토링하기!
const onClickMenu = (event: MouseEvent<HTMLDivElement>) => {
if (event.target instanceof Element) router.push(event.target.id);
};
const NAVIGATION_MENUS = [
{ name: "라이브강아지", page: "/openapis" },
{ name: "라이브게시판", page: "/boards" },
{ name: "라이브상품", page: "/markets" },
{ name: "마이페이지", page: "/mypages" },
];
export default function LayoutNavigationUI(props: ILayoutNavigationUIProps) {
return (
<Wrapper>
{NAVIGATION_MENUS.map((el) => (
<Fragment key={el.page}>
<MenuItem id={el.page} onClick={props.onClickMenu}>
{el.name}
</MenuItem>
</Fragment>
))}
</Wrapper>
);
}
export const Wrapper = styled.div`
height: 64px;
background-color: #5729ff;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 18px;
color: white;
`;
export const MenuItem = styled.div`
margin: 0px 60px;
cursor: pointer;
:hover {
color: orange;
}
`;
map과 forEach의 차이! 둘다 도는건 똑같지만, map은 return 해주고,
forEach는 return을 안 해주는 대신 속도가 map보다 빠르다
return값이 없어도 될 경우에는 forEach를 사용하는게 더 효율적
자유게시판 아직 디자인 못정했는데 넷플, 왓챠 , 시지비 같은걸로 구현해볼까? 영화같은거 api 받아와서 영상 화면에 뿌려주면 좋을 것 같음