현재 React + Javascript로 구성된 애플리케이션에 Next.js를 도입해보려한다! 처음해보는거라 신난다 😁
1. next 설치
원래 react, react-dom, next 설치가 필요한데 이미 react, react-dom은 설치되어 있던 상황이라 추가로 next만 설치했다.
$ yarn add next
2. pages/ + pages/index.js 생성
Next.js는 pages라는 폴더를 꼭 필요로 한다! 그래서 최상위 디렉토리에 pages 폴더를 만들고, 첫 화면을 보여주는 index.js를 생성했다.
// pages/index.js
import React from 'react';
const Index = () => {
return <div>첫 화면</div>;
};
export default Index;
3. next 실행을 위해 package.json의 script 수정
// package.json
"scripts": {
"build": "webpack --mode=production --node-env=production",
"build:dev": "webpack --mode=development",
"start": "webpack serve",
"next": "next" // 추가 부분
}
4. next 실행
$ yarn next
위 명령어로 next를 실행했더니
짜잔 이런게 뜬다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 역시...한번에 안되는군 ㅡㅡ
해결법
@babel/runtime과 @babel/plugin-transform-runtime을 설치해 regenerator-runtime을 추가하는 방식으로 해결했다.
1. @babel/runtime 설치
$ yarn add @babel/runtime
2. @babel/plugin-transform-runtime 설치
$ yarn add -D @babel/plugin-transform-runtime
3. .babelrc plugins에 "@babel/plugin-transform-runtime" 추가
// .babelrc
{
"plugins": ["@babel/syntax-dynamic-import", "@babel/plugin-transform-runtime"],
"presets": [
"@babel/preset-react",
[
"@babel/preset-env",
{
"modules": "auto"
}
]
]
}
요로코롬 하고 다시 실행했더니 아주 휑---한 원하던 첫화면이 나왔당 ㅎㅎㅎ
나는 현재 src/components/SpinButton/SpinButton 컴포넌트를 제일 첫 화면으로 보여주고 싶은 상황이다. 이어서 해보겠다.
5. pages/_document.js 작성
_document.js는 전체 페이지에 관여하는 컴포넌트로 HTML, head, body를 담당한다고 볼 수 있다. 이 문서 작성에는 몇 가지 규칙이 있다.
1. _document를 작성할 때는 Document 클래스를 상속받는 클래스 컴포넌트로 작성해야만 하며, 렌더 함수는 꼭 <Html>, <Head>, <Main>, <NextScript> 요소를 리턴해줘야한다.
2. _document에서 사용하는 <Head> 태그는 next/head가 아닌 next/document 모듈에서 불러와야 한다. _document의 <Head> 태그에는 모든 문서에 공통적으로 적용될 내용(Ex. charset 등)이 들어가야 한다.
3. _document는 서버에서 실행되므로 브라우저 api 또는 이벤트 핸들러 등을 포함하지 않아야 한다.
4. <Main /> 부분을 제외한 부분은 브라우저에서 실행되지 않으므로 비즈니스 로직을 추가해서는 안된다.
나의 경우에는 CSR → SSR로 바꾸는 과정이었다. 따라서 이미 public/index.html에 작성된 내용을 참고로 옮겼다.
+추가)
이렇게 _document.js를 작성하니 나중에 next 실행 시 다음과 같은 warning이 났다.
Adding <title> in pages/_document.js will lead to unexpected results with next/head since _document.js is only rendered on the initial pre-render.
출처 https://nextjs.org/docs/messages/no-document-title
그래서 공식문서 를 참고해서 _app.js와 _document.js를 수정했다.
변경된 _document.js
import React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
export default class CustomDocument extends Document {
render() {
return (
<Html lang="ko">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
변경된 _app.js
import React from 'react';
import Head from 'next/head';
const App = ({ Component, pageProps }) => (
<>
<Head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="엘라의 항공사 웹사이트의 컴포넌트 접근성 높이기 미션" />
<title>Ella's airline</title>
</Head>
<Component {...pageProps} />
</>
);
export default App;
6. pages/_app.js 작성
_app.js에서 렌더링하는 값은 모든 페이지에 영향을 준다. _app.js는 클라이언트에서 띄우길 바라는 전체 컴포넌트의 공통 레이아웃이다. 전체 페이지를 감싸고 있는 root 페이지라고 볼 수 있다.
****이 _app.js는 구버전입니다. 바로 위 변경된 _app.js와 _documnet.js를 확인해주세요****
// pages/_app.js
import React from 'react';
const App = ({ Component, pageProps }) => <Component {...pageProps} />;
export default App;
여기서 props로 받은 Component는 요청한 페이지이다. GET/ 요청을 보내면, Component에는 pages/index.js 파일이 props로 내려온다. pageProps는 페이지 getInitialProps를 통해 내려 받은 props들을 말한다.
_app.js 실행 후 _document.js가 실행된다.
7. pages/index.js 수정
난 일단 별다른 페이지 없이 SpinButton 컴포넌트만 첫 화면에 띄울 예정이다. 따라서 첫 화면을 담당하는 pages/index.js 를 수정한다.
import React from 'react';
import { SpinButton } from '../src/components';
const Index = () => {
return <SpinButton />;
};
export default Index;
이렇게 하니 원하던 화면이 첫 화면으로 나왔다 ㅎㅎ
여기까지 오니 페이지 이동도 한 번 해보고 싶어졌따! 그래서 도전!!
next.js에서는 pages/ 안의 내용을 참고로 url이 설정된다. 예를들면 다음과 같다.
pages/index.js → '/'
pages/carousel.js → '/carousel'
8. pages/carousel.js 추가
import React from 'react';
const Carousel = () => (
<div>
🎯 미션2 Carousel: 지금 떠나기 좋은 여행이 담겨있었어야 할 페이지
</div>
);
export default Carousel;
9. carousel.js로 갈 수 있는 a태그 및 Link 추가
// pages/index.js
import React from 'react';
import { SpinButton } from '../src/components';
import Link from 'next/link';
const Index = () => {
return (
<>
<SpinButton />
<Link href="/carousel">
<a>Carousel 페이지로 가기</a>
</Link>
</>
);
};
export default Index;
요로코롬하고 라우터가 잘 동작하는지 확인해봤다. 아주 잘 동작한다.
추가로 SSR이 잘 적용됐나 궁금해서 개발자 도구로 열어보니 이렇게 이미 완성된 index.html이 응답으로 온당! 신기하다!!!
SSR이 적용된 응답
CSR일 때 응답
출처
https://merrily-code.tistory.com/154
https://kyounghwan01.github.io/blog/React/next/basic/#동적-url
'Development' 카테고리의 다른 글
Next.js + React를 AWS EC2로 배포하기(2) - 어플리케이션 무중단 배포 (1) | 2021.10.04 |
---|---|
Next.js + React를 AWS EC2로 배포하기(1) - EC2 인스턴스 생성 (0) | 2021.10.04 |
웹에서 렌더링은 어떻게 발전하고 있을까? (2) | 2021.10.02 |
Babel과 Babel polyfill (0) | 2021.09.25 |
React 앱을 S3+CloudFront로 배포하기(3) - 도메인 연결 (0) | 2021.09.22 |