1. Next.js란?
Next.js는 React 라이브러리의 프레임워크
+ React는 언제든지 가져와서 사용할 수 있는 라이브러리,
Nextjs는 이미 정해진 규칙에 따라 코드 작성시 알아서 작성시켜주는 프레임워크 라고 생각하면 편할 듯 하다.
- React의 동작방식
브라우저가 자바스크립트 코드를 가져와서 client-side의 자바스크립트가 모든 UI를 만들게 된다. (브라우저 렌더링 과정)
즉, 브라우저가 HTML을 가져올 때 비어있는 div를 가져오고
그다음 모든 JS를 요청해서 브라우저가 자바스크립트와 react.js를 실행시키고
그다음 앱이 유저에게 보여지게 된다.
js를 가져와야만 화면을 띄울 수 있기 때문에 네트워크 연결이 느리거나, 파일이 큰 경우 처음에 흰 화면만 보이고 천천히 화면이 로딩된다.
위의 과정을 거쳐 <div id='root'></div> 이것만을 유저가 보게되기 때문에 검색엔진(구글이나 네이버)이런 곳에서는 잘 검색이 되지 않을 수도 있다. SEO*가 좋지 않다는 것이다.(CSR의 단점으로도 볼수 있겠다.)
*SEO(Search Engine Optimization)
- Next.js의 동작방식
react.js를 백엔드에서 동작시켜서 이 페이지를 미리 만들게 되는데, 미리 만들어짐으로써 component들을 render시킨다.
렌더링이 끝났을 때, 그건 HTML이 되고 next.js는 그 HTML을 페이지의 소스코드에 넣어준다.
그렇기때문에 유저입장에서 자바스크립트나 react.js가 로딩되지 않더라도 콘텐츠를 볼수 있게 되며,
유저가 페이지를 요청했을 때 실제 HTML을 얻을 수 있다. (React에 비한 가장 큰 장점이라고 생각된다.)
그러므로 React와 비교했을 때, SEO가 아주 좋아진다.
이러한 과정들을 Rehydration이라고 한다.
다시한번 과정을 쉽게 말하자면,
next.js가 백엔드에서 react를 돌리고 있고,
페이지를 pre-generate(사전생성) 할거고 그것을 HTML로 만든다.
그렇게 되면, 유저가 웹사이트를 요청할 때 사전생성된 HTML을 확인하게 되기 때문에 백지화면 또는 로딩스테이지는 필요없어진다.
2. Next.js 시작하기
npx create-next-app@latest //최신버전
npx create-next-app@latest --typescript //타입스크립트
3. 필요한 styled-components 적용하기
$ npm i styled-components styled-normalize
$ npm i -D @types/styled-components
$ npm i -D babel-plugin-styled-components
+ babel-plugin을 설치하고 나서는
루트 디렉토리에 .babelrc 파일을 생성하고 아래와 같이 작성해 주어야 한다.
안하게 되면, 스타일 적용전에 렌더링이 되기 때문!
{
"presets": [
"next/babel"
],
"plugins": [
[
"styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": false
}
]
]
}
ssr : 만들어진 스타일이 server-side에서 동작하게 할 것인지를
displayName : 디버그 하기 쉬운 클래스 네임을 사용할것인지
preprocess : 전처리
_document.ts 세팅
컨텍스트를 렌더링 할 때 스타일을 안에 집어넣어서 내리는 과정이라고 보면 될것 같다
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
} from "next/document";
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
render() {
return (
<Html>
<Head>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}