a태그는 기존 HTML 페이지 이동방식 => 페이지를 다운로드 받아서 보여준다. 일반적인 속도.
router.push는 react/next에서의 페이지 이동방식 => 이미 있는 화면에서 추가 다운로드를 받아서 화면에 보여줌 => 속도가 매우 빠름!
모바일앱은 전부 SPA(Single Page Application)이다.
그래서 굉장히 빠르다. 그래서 최근 나오는 웹서비스들도 SPA가 많다!
_app.tsx에
<Head>
<script
type="text/javascript"
src="//dapi.kakao.com/v2/maps/sdk.js? appkey=f4c07c9738ac2386adb4ab9a6ae7740b"></script>
</Head>
이 코드를 붙여넣으면 작동되긴 하지만 모든 페이지에서 다 카카오맵을 다운받기 때문에 비효율적이다.
앞으로 작업할 땐 Link 태그 사용한다!!
시멘틱 태그 사용의 장점
- 개발자들간에 커뮤니케이션 용이
- 검색엔진 최적화(SEO)
어쩔 수 없이 router.push를 써야하는 경우
=> 게시물 등록 후 리턴받은 아이디의 상세페이지로 이동할 때!
나는 게시글을 등록하고 게시물 리스트를 다시 불러올 때 refetchqueries
를 썼다. 하지만 refetchqueries
는 그닥 효율적인 방법은 아니다. 왜냐하면 useQuery()
는 수행 후 cache-state
에 저장되는데 refetch
를 사용하게 되면 새롭게 다시 받아오기때문에 비효율적인 구조가 되기 때문에 좋은 방법은 아니다.**
따라서 이제부터는 refetch를 하지 않고 apollo-cache-state를 직접 업데이트하는 방법을 사용해 볼 것 이다.
하지만 무조건 좋은 건 아님! cache-state는 큰 규모의 프로젝트에 적합하다!
오버엔지니어링을 주의하자!
import { useQuery, gql, useMutation } from "@apollo/client";
import { MouseEvent } from "react";
import {
IQuery,
IQueryFetchBoardsArgs,
} from "../../src/commons/types/generated/types";
const FETCH_BOARDS = gql`
query fetchBoards($page: Int) {
fetchBoards(page: $page) {
_id
writer
title
contents
}
}
`;
// 캐시에 저장되는 데이터와 요청 후 받아오는 값이 일치되어야 합니다.
const CREATE_BOARD = gql`
mutation createBoard($createBoardInput: CreateBoardInput!) {
createBoard(createBoardInput: $createBoardInput) {
_id
writer
title
contents
}
}
`;
const DELETE_BOARD = gql`
mutation deleteBoard($boardId: ID!) {
deleteBoard(boardId: $boardId)
}
`;
export default function StaticRoutedPage() {
const { data } = useQuery<Pick<IQuery, "fetchBoards">, IQueryFetchBoardsArgs>(
FETCH_BOARDS
);
const [deleteBoard] = useMutation(DELETE_BOARD);
const [createBoard] = useMutation(CREATE_BOARD);
//삭제 함수
const onClickDelete = (boardId: string) => () => {
void deleteBoard({
variables: { boardId },
update(cache, { data }) {
// 캐시를 수정한다는 뜻의 cache.modify
cache.modify({
// 캐시에있는 어떤 필드를 수정할 것 인지 key-value 형태로 적어줍니다.
fields: {
fetchBoards: (prev, { readField }) => {
const deletedId = data.deleteBoard; // 삭제된ID
const filteredPrev = prev.filter(
(el) => readField("_id", el) !== deletedId // el._id가 안되므로, readField를 사용해서 꺼내오기
);
return [...filteredPrev]; // 삭제된ID를 제외한 나머지 9개만 리턴
},
},
});
},
});
};
//등록 함수
const onClickCreate = () => {
void createBoard({
variables: {
createBoardInput: {
writer: "영희",
password: "1234",
title: "제목입니다~~",
contents: "내용입니다@@@",
},
},
update(cache, { data }) {
// 캐시를 수정한다는 뜻의 cache.modify
cache.modify({
// 캐시에있는 어떤 필드를 수정할 것 인지 key-value 형태로 적어줍니다.
fields: {
fetchBoards: (prev) => {
return [data.createBoard, ...prev];
},
},
});
},
});
};
return (
<>
{data?.fetchBoards.map((el) => (
<div key={el._id}>
<span style={{ margin: "10px" }}>{el.writer}</span>
<span style={{ margin: "10px" }}>{el.title}</span>
<button onClick={onClickDelete(el._id)}>삭제하기</button>
</div>
))}
<button onClick={onClickCreate}>등록하기</button>
</>
);
}
캐시를 직접 수정하기 위해서는 update(){}
라는 기능을 이용하게 된다.
update 기능을 사용할때 파라미터로 데리고 온 cache
는 apollo-cache-state에 있는 global state
이다.
그리고 업데이트 된 결과
는 파리미터의 {data}
에 들어오게 된다.
fields의 prev와 return값
- fields는 캐시에 있는 어떤 데이터를 수정할 것 인지를 알려줍니다.
- fields 의 prev : 이전데이터를 불러온다!
- fields의 return값 : 이전 데이터를 return 값으로 바꿔준다. 업데이트 된 결과가 {data} 이므로 결국 {data} 내부의 값이 된다!