Next.js 공식 문서에서는 Next.js를 이렇게 표현하고 있다.
The React Framework for Production(생산을 위한 리액트 프레임워크)
라이브러리와 프레임워크의 주요 차이점은 ‘Inversion of control’(통제의 역전)이다.
library는 메서드를 호출하여 사용자가 제어할 수 있고
framework는 제어가 역전되어 프레임워크가 사용자를 호출한다.
library - 사용자가 파일 이름이나 구조를 정하고 결정을 내린다.
framework - 파일 이름이나 구조를 정해진 규칙에 따라 만든다.
React에서는 라우팅을 위한 패키지를 설치해야하고 라우트를 추가할 때 마다 코드를 작성해야한다.
Next.js에서는 파일명과 위치에 따라 라우팅이 된다.
페이지는 파일 경로와 이름에 따라 연결된다.
중첩된 폴더 구조의 파일은 URL에서 동일한 방식으로 라우팅된다.
페이지 이름(파일 이름)을 대괄호로 감싸주면 만들 수 있다.
대괄호 안에 점 3개를 추가하여 만든다.
동일한 페이지 레이아웃에 대해 서로 다른 URL을 원하는 경우나 일부 경로 매개변수가 선택적인 페이지를 작업할 때 유용하다.
export default function detail() {
return 'detail page';
}
index.js → home page로 연결된다.
react.js를 import 할 필요가 없이 jsx를 사용할 수 있다.
잘못된 경로를 입력하면 만들어져 있는 404페이지가 나온다. (커스텀 가능)
Client side의 javascript에서 모든 작업을 수행하지 않고 각 페이지의 html을 미리 생성한다.
<div id=root></div>
만 존재하는 것을 볼 수 있다.💡 create react app (CRA)과 next.js의 차이점은 렌더링 방식에 있다.
SEO는 언제나 옳다.
Next.js 는 두 형태의 pre-rendering을 지원한다.
예) 블로그 페이지, 전자상거래 제품 페이지, 문서 및 마케팅 페이지
Next JS는 기본적으로 모든 페이지를 pre-render 한다.
페이지에 모든 정적 HTML 태그가 자동적으로 생성된다.
Next.js Server에서는 Pre-rendering된 웹 페이지를 클라이언트에게 보내고 나서, 바로 리액트가 번들링 된 자바스크립트 코드들을 클라이언트에게 전송한다.
네트워크 탭을 보면, 맨 처음 응답받는 요소가 document Type의 파일이고, 이후에 React 코드들이 렌더링 된 JS 파일들이 Chunk 단위로 다운로드되는 것을 확인할 수 있다.
그리고 이 자바스크립트 코드들이 이전에 보내진 HTML DOM 요소 위에서 한번 더 렌더링을 하면서, 각자 자기 자리를 찾아가며 매칭이 된다.
이 과정을 Hydrate라고 부른다.
이것은 마치 자바스크립트 코드들이 DOM 요소 위에 물을 채우 듯 필요로 하던 요소들을 채운다 하여 Hydrate(수화)라는 용어를 쓴다고 한다.
next.js는 react.js를 백엔드에서 동작하여 페이지를 미리 생성하고 컴포넌트들을 렌더링한다.
렌더링이 끝나면 HTML이 되고 초기 상태를 페이지의 소스코드에 넣어준다.
그렇게 되면 유저는 js와 react.js가 로딩되지 않더라도 콘텐츠를 볼 수 있다.
react.js가 로딩되면 이미 존재하는 HTML과 연결되어 일반적인 react.js 앱이 된다.
💡 HTML이 존재하기 때문에 SEO에 도움이 된다!
Next.js는 빌드 타임에 pre-render 하는 것 뿐만 아니라 요청 타임에도 pre-rendering이 가능하다.
HTML은 들어오는 요청을 위해 생성된다.
getServerSideProps
는 서버 측에서만 작동한다.getServerSideProps
내부에 작성한 코드는 JS 번들에 포함되지 않기 때문에 브라우저로 보내지지 않는다.getServerSideProps
내부에 server 측 코드를 작성할 수 있다.getServerSideProps
내부에서 파일 시스템에 접근하거나 데이터베이스 쿼리를 할 수 있다.getServerSideProps
내부에서 API 키를 사용해도 브라우저에 노출되지 않는다.getServerSideProps
는 페이지와 일반 컴포넌트 파일에서만 사용할 수 있다.getServerSideProps
는 props 키를 가진 객체를 반환해야 한다.getServerSideProps
요청 타임에 실행된다.API를 만들 수 있다.
Full stack framework로 볼 수 있다.
pages
폴더에 api
이름의 폴더를 생성해야한다.api
폴더에는 어플리케이션의 api를 정의할 수 있다.handler
라는 이름으로 생성하여 사용한다.export default function handler(req, res) {
res.status(200).json({ name: 'Home API route' });
}
Dynamic Routes 와 동일하게 폴더 안에 대괄호([])로 파일을 만들어주면 해당 파일 이름으로 접근 할 수 있다.
import { comments } from '../../../data/comments';
export default function handler(req, res) {
const { commentId } = req.query;
const comment = comments.find(
(comment) => comment.id === parseInt(commentId)
);
res.status(200).json(comment);
}
Catch-all 또한 이전에 사용했던 폴더 구조와 파일명([...params].js
)을 api 폴더에서 사용하면 된다.
export default function handler(req, res) {
const params = req.query.params;
console.log(params);
res.status(200).json(params);
}
API 라우팅은 페이지 라우팅과 방식이 흡사하다.
API들은 파일 구조를 따른다.
모든 API 라우트는 handler
함수로 export 된다.
handler
함수는 인자로 request
와 response
를 받는다.
GET
, POST
등 요청을 req.method
를 사용하여 수용한다.
동적 API 라우트는 파일 구조로 생성한다. [파일명]
Catch All API 라우트는 파일 구조로 생성한다. […params]
Tailwind CSS 같은 css framework를 사용할 수 있다.
Styled-component 같은 css in js library를 사용할 수 있다.
기본적으로 아주 좋은 CSS module을 지원한다.
{name}.module.css 형식으로 만든 css 파일을 자바스크립트 오브젝트로 import 하여 스타일을 적용하는 방식이다.
.nav {
background-color: red;
}
import Link from 'next/link';
import { useRouter } from 'next/router';
import styles from './NavBar.module.css';
export default function NavBar() {
const router = useRouter();
return (
<nav className={styles.nav}>
<Link href="/">
<a style={{ color: router.pathname === '/' ? 'red' : 'blue' }}>Home</a>
</Link>
<Link href="/about">
<a style={{ color: router.pathname === '/about' ? 'red' : 'blue' }}>
About
</a>
</Link>
</nav>
);
}
장단점
장점
단점
styled jsx 방식으로 스타일을 적용하기 위해서는 style
태그에 jsx
속성을 추가하고 그 안에 CSS를 작성하면 된다.
<style jsx>{`
nav {
background-color: tomato;
}
a {
text-decoration: none;
}
.active {
color: red;
}
`}</style>
이렇게 작성하면 실제 클래스명은 무작위 텍스트로 입력되고 그 클래스는 해당 style 태그가 작성된 컴포넌트에만 적용된다.
같은 이름을 사용할지라도 해당 컴포넌트에만 격리되어 적용된다.
컴포넌트의 Prop 가져오기
<style jsx>{`
nav {
background-color: tomato;
}
a {
text-decoration: none;
}
.active {
color: ${props.color};
}
`}</style>
단순히 js 문자열이므로 ${} 를 사용하여 객체를 가져올 수 있다.
Next.js는 App 컴포넌트를 사용하여 페이지를 초기화한다.
_app.js 파일
pages 폴더에 _app.js
파일을 만들고 App 컴포넌트를 생성한다.
import { AppProps } from 'next/app';
export default function App({ Component, pageProps }: AppProps) {
return (
<Component {...pageProps} />
);
}
Next.js는 컴포넌트(Component)와 속성(pageProps)을 가져와서 렌더링한다.
그렇기 때문에 렌더링 할 페이지 이외의 컴포넌트를 작성하면 모든 페이지에 그 컴포넌트가 렌더링된다.
import { AppProps } from 'next/app';
import NavBar from '../components/NavBar';
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<NavBar />
<Component {...pageProps} />
</>
);
}
이렇게 NavBar
컴포넌트를 포함하면 모든 페이지에 같이 렌더링된다.
같은 방법으로 Global style을 적용할 수 있다.
import { AppProps } from 'next/app';
import NavBar from '../components/NavBar';
import '../styles/globals.css';
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<NavBar />
<Component {...pageProps} />
<style jsx global>
{`
a {
color: green;
}
`}
</style>
</>
);
}
여러 케이스에 맞는 다중 인증을 지원한다.
Dev 와 Prod 빌드를 따로 할 수 있다.