์ฐ๋ฆฌ๋๋ผ์์๋ ๋ค์ํ ์ง๋ API ์ค ์นด์นด์ค, ๋ค์ด๋ฒ, ๊ตฌ๊ธ ์ง๋ API๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ค. 3๊ฐ์ง ์ค ๋น์ฉ์ด๋ ์ํฉ์ ๋ง๋ API๋ฅผ ์ ํํ๋ฉด ๋๋ค. ๋๋ ๊ทธ ์ค ์นด์นด์ค ๋งต API๋ฅผ ์ด์ฉํด๋ดค๋ค.
์นด์นด์ค ๊ฐ๋ฐ์ ํ์ด์ง์ ์ ์ํ๋ฉด ์ง๋๋ฅผ ํฌํจํ ๋ค์ํ API๊ฐ ์ ๊ณต๋๊ณ ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ๋์ค์ ํ์ํ ๋ ์จ๋ณด๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
๋ด ์ ํ๋ฆฌ์ผ์ด์ ์ถ๊ฐ > ๋ฌธ์ > ์ง๋ > ์ข์ธก ์ฌ์ด๋๋ฐ์ ์ง๋ ํด๋ฆญ > ๋ธ๋ผ์ฐ์ ์ ํ > ์ผ์ชฝ ํ๋จ์ ๋ฉ๋ด๋ฐ์ ํค ๋ฐ๊ธ ๋ฉ๋ด ํด๋ฆญ > ์์ฑํด๋์ ์ ํ๋ฆฌ์ผ์ด์ ํด๋ฆญ > ์ฉ๋์ ๋ง๋ ํค ์ ํ > Guide ๋ณด๊ณ ๋ฐ๋ผํ๊ธฐ
import Head from 'next/head';
Head ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์ค๊ณ , ์์ ์นด์นด์ค ๋งต script
๋ฅผ ํธ์ถํ ์ ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ค.
return(
<>
<Head>
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey='JavaScript ์ฑ ํค ์
๋ ฅ'"></script>
</Head>
</>
)
๋งต์ ํธ์ถํ JS ์ฝ๋์ ๋งต์ ํธ์ถ ๋ฐ์ ์ถ๋ ฅํ ์์ญ(div)์ ์ค์ ํด์ค๋ค.
const container = document.getElementById('map');
//์ง๋๋ฅผ ๋ด์ ์์ญ์ DOM ๋ ํผ๋ฐ์ค
const options = {
//์ง๋๋ฅผ ์์ฑํ ๋ ํ์ํ ๊ธฐ๋ณธ ์ต์
center: new kakao.maps.LatLng(33.450701, 126.570667), //์ง๋์ ์ค์ฌ์ขํ.
level: 3 //์ง๋์ ๋ ๋ฒจ(ํ๋, ์ถ์ ์ ๋)
};
new kakao.maps.Map(container, options);
//์ง๋ ์์ฑ ๋ฐ ๊ฐ์ฒด ๋ฆฌํด
// return(
// ...
<div id='map' style={{ "width" : "500px", "height" : "400px" }}></div>
// )
ํค ๋ฐ๊ธ > ๋ด ์ ํ๋ฆฌ์ผ์ด์ > ํ๋ซํผ > web ์ฌ์ดํธ ๋๋ฉ์ธ ๋ฑ๋ก
ํ์ด์ง ์ด๋์ ํ๋ฉด ์ง๋๊ฐ ๋ณด์ด์ง ์๊ณ ์๋ฌ๊ฐ ๋ฌ๋ค. ํ์ง๋ง ์ฃผ์์ฐฝ์ ํด๋น ์ฃผ์๋ฅผ ์
๋ ฅํด์ ์ ์์ ํ๋ฉด ์ง๋๊ฐ ์ ์์ ์ผ๋ก ๋ฌ๋ค. ์ ๊ทธ๋ฐ ๊ฑธ๊น? ์ด๊ฒ์ ์ดํดํ๊ธฐ ์ํด์๋ SPA
์ CSR
์ ์์์ผ ํ๋ค.
์์์ ๋ฐ์ํ๋ ์๋ฌ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฝ๋๋ฅผ ๊ฐ์ ธ์๋ดค๋ค.
import { useRouter } from "next/router";
export default function KakaoMapRoutingPage() {
const router = useRouter();
const onClickMoveToMap = () => {
router.push("/29-03-kakao-map-routed");
};
return (
<div>
<button onClick={onClickMoveToMap}>๋งต์ผ๋ก ์ด๋ํ๊ธฐ!</button>
</div>
);
}
์ ์ฝ๋์์ router ๋์ a ํ๊ทธ
๋ฅผ ์ด์ฉํ๋ฉด ์ด๋จ๊น? ์๋ฌด๋ฐ ๋ฌธ์ ์์ด ์ง๋๊ฐ ์ถ๋ ฅ๋๋ค. ๊ทธ๋ ๋ค๋ฉด router์ a ํ๊ทธ๋ ๋ฌด์จ ์ฐจ์ด์ผ๊น?
a ํ๊ทธ
๋ฅผ ํด๋ฆญํ๋ค๋ฉด, ํ๋ก ํธ์๋ ์๋ฒ์ ์ ์ํด์ ํด๋น ํ์ด์ง๋ฅผ ๋ค์ด๋ก๋ ๋ฐ์์ ๋ธ๋ผ์ฐ์ ์์ ๊ทธ๋ ค์ค๋ค.
์ฆ, ํ๊ทธ๋ฅผ ํด๋ฆญํ ๋๋ง๋ค ์๋ก์ด ํ์ด์ง๋ฅผ ๋ค์ด๋ก๋ ๋ฐ์์์ ๋ณด์ฌ์ฃผ๊ธฐ ๋๋ฌธ์ ํ์ด์ง๊ฐ ์ฌ๋ฌ ์ฅ ์๋ ๊ฒ๊ณผ ๊ฐ๋ค. ์ด๋ฌํ ๋ฐฉ์์ MPA(multi page application)
๋ผ๊ณ ํ๋ค.
MPA ์ ๊ฒฝ์ฐ, ํ์ด์ง ์ด๋ ์๋ง๋ค ์๋ฒ์ ์์ฒญํด์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์์ผ ํ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์ ์ข์ง ์๋ค.
๋ฐ๋ฉด react์์๋ SPA(single page application)
๋ฐฉ์์ผ๋ก ์๋ํ๋ค. ์ฒ์ ์ ์ํ ๋ ํด๋น ํ์ด์ง ์ธ์ ๋ค๋ฅธ ํ์ด์ง๊น์ง ํ๋ฒ์ ๋ค์ด๋ก๋ ๋ฐ์์์ ํ์ํ ํ์ด์ง๋ง ๋ฝ์์ ๋ธ๋ผ์ฐ์ ์ ๋ณด์ฌ์ค๋ค.
SPA
๋ ์ฒ์ ๋ค์ด๋ก๋ ๋ฐ์ ๋๋ ์กฐ๊ธ ๋๋ฆด ์ ์์ง๋ง, ํ์ด์ง๋ฅผ ์ด๋ํ ๋ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ด MPA์ ๋นํ์ฌ ์๋์ ์ผ๋ก ์งง๋ค.
MPA๋ ์ ํต์ ์ธ ์๋ฏธ์ ํํ์ด์ง๊ณ , SPA๋ ํํ์ด์ง๋ณด๋ค๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋์ด ๊ฐํ๋ค.
์์์ kakao map undefined
์๋ฌ๊ฐ ๋ฐ์ํ๋ ์ด์ ๋, ์ง๋๋ฅผ ๋ค์ด๋ก๋ ๋ฐ์์ค๋ ๋์ ์ด๋ํ ํ์ด์ง๋ฅผ ๋จผ์ ๊ทธ๋ ค์คฌ๊ธฐ ๋๋ฌธ์ด๋ค.
a ํ๊ทธ
๋ฅผ ์ด์ฉํ๋ฉด ์ค๋ฅ๋ ํด๊ฒฐ๋์ง๋ง, ํ์ด์ง๋ฅผ ์ด๋ํ์ ๋ ํ์ด์ง ์์ฒด๊ฐ ์๋ก ๋ก๋ฉ๋๊ธฐ ๋๋ฌธ์ SPA ํ๋ ์์ํฌ์ธ Next.js๋ฅผ ์ฌ์ฉํ๋ ์๋ฏธ๊ฐ ์์ด์ง๋ค.
๋์ Next.js์์ ์ ๊ณตํ๋ Link
ํ๊ทธ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค!
import { useRouter } from "next/router";
import Link from "next/link";
export default function KakaoMapRoutingPage() {
// const router = useRouter();
// const onClickMoveToMap = () => {
// router.push("/29-03-kakao-map-routed");
// };
return (
<div>
{/* <button onClick={onClickMoveToMap}>๋งต์ผ๋ก ์ด๋ํ๊ธฐ !</button> */}
<Link href="/29-03-kakao-map-routed">
<a>๋งต์ผ๋ก ์ด๋ํ๊ธฐ !!</a>
</Link>
</div>
);
}
Link
์์ a ํ๊ทธ๋ฅผ ๋ฃ์ผ๋ฉด semantic ์์๋ฅผ ๊ฐ๊ณ ์๋ html ํ๊ทธ๋ก ๋ ๋๋ง ๋๋ค. ์๋ฏธ๊ฐ ์๋ semantic tag๋ ๊ฒ์ ๋
ธ์ถ์ด ์ฌ์์ง๋ค๋ ์ฅ์ ์ด ์๋ค. ๋ํ MPA์ธ a ํ๊ทธ๋ณด๋ค SPA์ธ Link ํ๊ทธ๊ฐ ์๋๋ ํจ์ฌ ๋น ๋ฅด๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๊ฐ๊ธ์ ์ด๋ฉด Link ํ๊ทธ๋ฅผ ์ฐ๋ ๊ฒ์ด ์ข๋ค.
๋ํ, ์ด๋ํ ํ์ด์ง์์ script ๋ค์ด๋ก๋๋ฅผ ์๋ฃํ๊ณ ์นด์นด์ค ๋งต ๋ก๋๋ ์๋ฃ๋ ํ์ ์ง๋๊ฐ ๋ถ๋ฌ์ ธ ์ค๋๋ก ํด์ค์ผ ํ๋ค.
useEffect(() => {
// ์ฌ๊ธฐ์ ์ง์ ๋ค์ด๋ก๋ ๋ฐ๊ณ , ๋ค ๋ฐ์๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๊ทธ๋ ค์ฃผ๊ธฐ!!
const script = document.createElement("script"); // html์ script๋ผ๋ ํ๊ทธ(Element)๋ฅผ ๋ง๋ ๋ค.
script.src =
"//dapi.kakao.com/v2/maps/sdk.js?appkey='JavaScript API Key'&autoload=false";
document.head.appendChild(script);
script.onload = () => {
window.kakao.maps.load(function () {
const container = document.getElementById("map");
const options = {
center: new window.kakao.maps.LatLng(33.450701, 126.570667),
level: 3,
};
const map = new window.kakao.maps.Map(container, options);
}
}
}
์ง๊ธ๊น์ง๋ ๋ฑ๋ก/์ญ์ ์ดํ refetch
๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์
๋ฐ์ดํธํด์๋ค. ํ์ง๋ง refetch๋ ๊ทธ๋ ๊ฒ ์ข์ ๋ฐฉ๋ฒ์ ์๋๋ค.
์๋ํ๋ฉด useQuery()๋ ์คํ๋ ํ cache-state์ ์ ์ฅ๋๋๋ฐ refetch
๋ฅผ ์ฌ์ฉํ๋ฉด api ์์ฒญ์ ๋ค์ ๋ฐ์์ค๊ธฐ ๋๋ฌธ์ด๋ค. ๋นํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ด๋ค.
๋ฐ๋ผ์ ์ด์ ๋ถํฐ๋ refetchํ์ง ์๊ณ , apollo-cache-state
๋ฅผ ์ง์ ์
๋ฐ์ดํธ ํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ๊ฒ์ด๋ค.
์บ์๋ฅผ ์ง์ ์์ ํ ๋์๋ update(){}
๋ฅผ ์ฌ์ฉํ๋ค. ์๋ refetch๋ฅผ ์ฌ์ฉํ๋ ๋ถ๋ถ์ update๋ก ๋ฐ๊พธ์๋ค.
// ์บ์์ ์ ์ฅ๋๋ ๋ฐ์ดํฐ์ ์์ฒญ ํ ๋ฐ์์ค๋ ๊ฐ์ด ์ผ์น๋์ด์ผ ํจ
const CREATE_BOARD = gql`
mutation createBoard($createBoardInput: CreateBoardInput!) {
createBoard(createBoardInput: $createBoardInput) {
_id
writer
title
contents
}
}
`;
export default function StaticRoutedPage() {
//์ญ์ ํจ์
const onClickDelete = (boardId: string) => () => {
void deleteBoard({
variables: { boardId },
update(cache, { data }) {
// ์บ์๋ฅผ ์์ ํ๋ค๋ ๋ป์ cache.modify
cache.modify({
// ์บ์์์๋ ์ด๋ค ํ๋๋ฅผ ์์ ํ ๊ฒ ์ธ์ง key-value ํํ๋ก ์ ์ด์ฃผ๊ธฐ
fields: {
fetchBoards: (prev, { readField }) => {
// prev: ์ด์ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
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>
</>
);
}
ํ์ง๋ง ๋ฌด์กฐ๊ฑด refetchQueries๋ฅผ ์ฐ์ง ๋ง๋ผ๋ ๊ฒ์ ์๋๋ค! ์ํฉ์ ๋ง๊ฒ ๊ฒฐ์ ํ๋ฉด ๋๋ค. ์์ ์๋น์ค์์๋ refetch
๋ฅผ ์ฐ๋ ๊ฒ์ด ๋ ๋์ ์๋ ์๋ค. ์ฝ๋๋ ํจ์ฌ ์งง๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์ ํฌ๊ฒ ๋ฐ์ง ํ์๊ฐ ์๋ ๊ฒฝ์ฐ์๋ refetch๊ฐ ๋์ ์๋ ์๋ค.