https://apis.map.kakao.com/web/guide/
import Script from "next/script"
을 사용하면 next 에서 script 태그 사용이 가능하다.
import Head from "next/head";
import { useEffect } from "react";
// import Script from "next/script";
declare const window: typeof globalThis & {
kakao: any;
};
export default function KakaoMapPage() {
useEffect(() => {
const container = document.getElementById("map"); // 지도를 담을 영역의 DOM 레퍼런스
const options = {
// 지도를 생성할 때 필요한 기본 옵션
center: new window.kakao.maps.LatLng(33.450701, 126.570667), // 지도의 중심좌표.
level: 3, // 지도의 레벨(확대, 축소 정도)
};
// map 으로 담아도 되고 안 담아도 됨
const map = new window.kakao.maps.Map(container, options); // 지도 생성 및 객체 리턴
});
return (
<div>
<Head>
<script
type="text/javascript"
src="//dapi.kakao.com/v2/maps/sdk.js?appkey=발급받은키"
></script>
</Head>
<div id="map" style={{ width: "500px", height: "400px" }}></div>
</div>
);
}
페이지를 두 개로 나누어서 한 쪽에는 지도로 이동하는(router) 버튼에 router.push 를 줘서 지도가 있는 페이지(routing)를 연결해 줬을 때 지도를 불러오는 걸 실패한다.하지만 지도가 있는 페이지를 새로고침하면 잘 받아와진다.
이 오류를 해결하기 위해선 지도로 이동하는 방법을 버튼이 아닌 a 태그로 바꾸면 된다.
그렇다면 왜 이런 일이 일어날까?
브라우저에서 페이지를 이동할 때마다 프론트엔드에서 새롭게 html,css,js 를 받아온다.
단일 페이지만
으로 사이트를 동작시키는 방법이다. 페이지들의 html, css, js를 한 번에 받아서 오기 때문에 처음엔 속도가 느리고 상세 페이지의 결과를 보여줄 수 없기 때문에 SEO(검색엔진최적화) 검색 불가능하다. 하지만 새로운 페이지를 출력하기 위한 요청과 응답이 발생하지 않기 때문에 부드럽고 자연스럽게 페이지가 바뀐다.
위에서 페이지를 이동할 때 오류가 난 이유도 이와 관련이 있다. router.push 는 싱글 페이지에서 Client Side Rendering 을 하게 된다. 즉, Head 와 Script 태그가 그려지기 전에 이동하기 때문에 map 을 그릴 수가 없다. 반면 a 태그는 서버에 접속(server side rendering)해서 새로 다운로드 받는다.
SPA를 포함하는 개념으로 서버에 요청하지 않고 브라우저 안에서 렌더링을 하는 것을 말한다.
서버에서 브라우저 페이지를 모두 렌더링 한 뒤에 사용자에게 보여준다. SEO 문제를 해결할 수 있다.
router.push 와 같은 역할을 한다.
import Link from 'next/link
router.push 보다 link 가 더 좋다
태그를 만든 다음 태그 언어들만의 기능
<Link><a>이동하기</a></Link>
이때 a 태그는 큰 의미는 없지만 써주도록 한다. 게시물 등록 후 페이지 이동과 같은 경우는 router.push 를 그대로 사용할 것!
시멘틱 요소는 태그 자체에 의미가 있는 걸 말한다. 즉, 브라우저, 검색엔진, 개발자 모두에게 콘텐츠의 의미를 명확히 설명하는 역할을 갖고 있다. 따라서 div와 span 이 아닌 header, h1, img 와 같은 태그들을 활용하는 것이 중요하다.
그중 가장 큰 이유는 SEO 와도 관련이 있다. 검색 엔진은 로봇을 이용하여 정보를 수집하게 되는데, 이때 검색 엔진은 HTML 코드 만으로 그 의미를 인지해야 하기 때문이다. 만약 같은 문장을 각각 div 와 h1 태그를 사용했을 때, 검색 엔진은 h1을 더 중요한 요소라고 판단할 것이다.
함수의 인자로 들어가는 함수
를 콜백함수라고 한다.
function aaa(qqqq){
}
aaa(function(){})
aaa(() => {})
functino outerFunc(innerFunc) {
// 외부 API 에 데이터 요청하는 로직
const result = "요청으로 받아온 데이터 결과값"
innerFunc(result)
}
outerFunc((result) => {
console.log("결과: result")
}
외부 데이터를 보낼 때 사용한다. 콜백함수가 function 안에서 실행됨으로써 비동기적인 작업을 동기화 해준다. 지금은 await 를 사용해서 동기화 처리를 해주지만 await가 없었을 때는 콜백 함수를 사용했다.
const onClickCallback = () => {
const aaa = new XMLHttpRequest();
aaa.open("get", "api주소");
aaa.send(); // 요청
aaa.addEventListener("load", (res) => {
const result = // api에서 가져오고 싶은 데이터
const bbb = new XMLHttpRequest();
bbb.open("get", "result를 사용할 api" );
bbb.send();
bbb.addEventListener("load", (res) => {
const result2 = // api에서 가져오고 싶은 데이터
const ccc = new XMLHttpRequest();
ccc.open("get", "result2f를 사용할 api" );
ccc.send();
ccc.addEventListener("load", (res) => {
console.log(res); // 최종결과값
});
});
});
};
하지만 이렇게 끊임 없이 밑으로 내려가는 콜백 지옥이 탄생한다.
콜백 지옥을 해결하기 위해 등장했다.
const onClickPromise = () => {
console.log("여기는 1번 입니다");
axios
.get("api주소")
.then((res) => {
console.log("여기는 2번 입니다");
return axios.get(api);
}) // return 하면 값이 다음 then 으로 들어간다
.then((res) => {
console.log("여기는 3번 입니다");
return axios.get(api);
})
.then((res) => {
console.log("여기는 4번 입니다");
});
console.log("여기는 5번 입니다");
함수 실행 결과
promise 성공시의 로직이 then()에 들어가기 때문에 promise().then()
로 많이 명시한다. 콜백처럼 밑으로 파고 내려가는 지옥은 없지만 위에서부터 순서대로 실행되지 못하기 때문에 직관적이지 못하다. 이걸 해결하기 위해 나온 게 async/await
다.
const onClickAsyncawait = async () => {
const aaa = await axios.get("api주소");
const bbb = await axios.get("api주소");
const ccc = await axios.get("api주소");
};
await 는 프로미스를 await 한다. 다시 말해 await 를 사용하려면 뒤에 프로미스가 와야하기 때문에 아무 곳에나 await를 사용할 수 없다. axios.get() 은 리턴값이 promise 이기 때문에 await와 사용이 가능하다.
queue는 하나만 존재하는 것이 아니라 세분화되어 나뉘어져 있다. 그중 대표적인 것들이 Macro Task Queue
와 Micro Task Queue
다.
실행 순서는 마이크로가 먼저 실행되고, 마이크로가 모두 실행된 후에 매크로가 실행된다.