반응형
튜토리얼 완성본 구경하기 (해당 페이지는 홈이 아닌 404로 연결하게 해둠)
404 not found (nextjs-emotion-typescript-blog.vercel.app)
리액트를 사용하여 웹 애플리케이션을 만들려면 고려할 사항들
- 컴파일러 / 번들러
- 코드 스플리팅
- 프리렌더링 / SSG / SEO / SSR or CSR
- API
With Next.js
- 페이지 기반 라우팅 시스템
- 프리 렌더링 / SSG / SSR / CSR
- 자동 코드 분할
- 내장 CSS/ SaSS 지원. CSS-in-JS 라이브러리 지원
- Fest Refresh 지원
- API 호출 가능 (노드임)
- 완전히 확장 가능
타입스크립트와 함께 사용하기
import { GetStaticProps, GetStaticPaths, GetServerSideProps } from 'next'
export const getStaticProps: GetStaticProps = async context => {
// ...
}
export const getStaticPaths: GetStaticPaths = async () => {
// ...
}
export const getServerSideProps: GetServerSideProps = async context => {
// ...
}
import { NextApiRequest, NextApiResponse } from 'next'
export default (req: NextApiRequest, res: NextApiResponse) => {
// ...
}
import { AppProps } from 'next/app'
function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
export default App
<a>
tag를<Link>
tag로 감싸면 클라이언트 사이드 라우팅이 가능함- 또한 Next.js의 프로덕션 빌드에서 Link 구성 요소가 브라우저의 뷰포트에 나타날 때마다 Next.js는 백그라운드에서 연결된 페이지의 코드를 자동으로 프리 페치합니다.
- 참고 : Next.js 앱 외부의 외부 페이지에 연결해야하는 경우 Link없이 태그를 사용하면됩니다.
import Link from 'next/link'
<h1 className="title">
Learn <a href="https://nextjs.org">Next.js!</a>
</h1>
// >>>
<h1 className="title">
Read{' '}
<Link href="/posts/first-post">
<a>this page!</a>
</Link>
</h1>
next/image
는 Resizing & optimizing 을 간소화해줌
import Image from 'next/image'
const YourComponent = () => (
<Image
src="/images/profile.jpg" // Route of the image file
height={144} // Desired size with correct aspect ratio
width={144} // Desired size with correct aspect ratio
alt="Your Name"
/>
)
- 레이아웃 컴포넌트
children
을 감쌈
import Head from 'next/head'
import Link from 'next/link'
import Layout from '../../components/layout'
export default function FirstPost() {
return (
<Layout>
<Head>
<title>First Post</title>
</Head>
<h1>First Post</h1>
<h2>
<Link href="/">
<a>Back to home</a>
</Link>
</h2>
</Layout>
)
}
const Container = styled.div`
max-width: 36rem;
padding: 0 1 rem;
margin: 3rem auto 6rem;
`;
- Next.js는 styled-jsx 지원 내장.
styled-component
와emotion
미지원.babelrc
설정 필요
- 글로벌 스타일
pages/_app.js
파일을 만든다.- 전역 스타일은 여기서만 적용 가능하다.
- 해당 프로젝트는
emotion
을 사용하여 글로벌 스타일을 설정한다.
import { AppProps } from 'next/app';
import { globalStyles } from '../shared';
export default function App({ Component, pageProps }: AppProps) {
return (
<>
{globalStyles}
<Component {...pageProps} />
</>
);
toggle class에
classnames 활용하기- 좋은지 모르겠음. 난 그냥 emotion 쓰고싶음
import styles from './alert.module.css'
import cn from 'classnames'
export default function Alert({ children, type }) {
return (
<div
className={cn({
[styles.success]: type === 'success',
[styles.error]: type === 'error'
})}
>
{children}
</div>
)
}
css`
.success {
color: green;
}
.error {
color: red;
}
`
- 프리렌더링
- 미리 페이지를 그려 클라이언트에 제공함
- 클라이언트 사이드 렌더링과 달리 만들어진 페이지가 제공됨.
- SEO와 성능에 좋음
- 코드 스플리팅
- 각각의 페이지는 해당 페이지에 딱 필요한 최소 자바스크립트 코드와 같이 전달됨.
- 브라우저에서 페이지를 로드하면 해당 JavaScript 코드가 실행되고 페이지가 인터랙티브 하게 됨. (이 과정을 수화라고 함.)
- 코드 스플리팅
- 프리렌더링의 종류
- 스태틱 사이트 제너레이션
- 빌드 타임에 페이지를 HTML로 만들어 계속 재사용함
- 딱봐도 성능에 좋을것같음
- 빌드 타임에 페이지를 HTML로 만들어 계속 재사용함
- 서버사이드 렌더링
- 매 요청마다 페이지를 만들어서 HTML로 클라이언트에 넘겨줌
- SEO에는 좋은데 CSR보다 성능에는 안좋다함.
- 꼭 필요한 부분만 해주는게 좋음
- 매 요청마다 페이지를 만들어서 HTML로 클라이언트에 넘겨줌
- 스태틱 사이트 제너레이션
You can use Static Generation for many types of pages, including:
- Marketing pages
- Blog posts
- E-commerce product listings
- Help and documentation
사용자 요청 전에 페이지를 미리 만들어 둘 수 있으면 스태틱 제너레이션
이 좋음
항상 최신이어야 하면 CSR / SSR 사용
- nextjs도 노드라서 외부에서 data fetch 해오기 가능
- 직접 디비에서 쿼리하는것도 가능함
getStaticProps
은 오직 서버에서만 동작함
// 서버에서 데이터 떙겨오기
export async function getSortedPostsData() {
// Instead of the file system,
// fetch post data from an external API endpoint
// Next.js polyfills fetch() on both the client and server. You don't need to import it.
const res = await fetch('..')
return res.json()
}
// 디비에서 직접 쿼리 가능
import someDatabaseSDK from 'someDatabaseSDK'
const databaseClient = someDatabaseSDK.createClient(...)
export async function getSortedPostsData() {
// Instead of the file system,
// fetch post data from a database
return databaseClient.query('SELECT posts...')
}
- 요청 전에 미리 만들어 재사용이 불가능하면
SSR
을 사용하면 됨
export async function getServerSideProps(context) {
return {
props: {
// props for your component
}
}
}
- CSR을 언제 쓰나요?
- SEO와 관계없는 비공개 사적인 유저 페이지 (dashboard)
- 다이나믹 라우팅
- /posts/ 경로에 각각 페이지 포스팅
- id는 마크다운 파일명
- 정리
- getStaticPaths로 params.id를 만들어준다.
- getStaticProps로 parameter를 받아 해당 경로 컨텐츠를 정적 생성한다.
getStaticProps
를 사용하여 ID가 지정된 특정 게시물을 가져오고getStaticPaths
를 사용하여 가능한 모든 블로그 게시물을 가져옵니다.
import Layout from '../../components/layout'
export default function Post() {
return <Layout>...</Layout>
}
// 해당 페이지 경로(id) 지정하기
export async function getStaticPaths() {
// Return a list of possible value for id
}
// 딱 한번 만들어 정적으로 사용할 데이터 만들기
export async function getStaticProps({ params }) {
// Fetch necessary data for the blog post using params.id
}
// getStaticPath를 쓰려면 아래와 같은 형태로 배열을 제공해야 함.
export function getAllPostIds(): { params: { id: string } }[] {
const fileNames = fs.readdirSync(postsDirectory);
// Returns an array that looks like this:
// [
// {
// params: {
// id: 'ssg-ssr'
// }
// },
// {
// params: {
// id: 'pre-rendering'
// }
// }
// ]
return f
return fileNames.map(fileName => {
return {
params: {
id: fileName.replace(/\.md$/, ''),
},
};
});
}
// 사용은 다음과 같이 한다.
export async function getStaticPaths() {
const paths = getAllPostIds()
return {
paths,
fallback: false // false면 404페이지로 보낸다. true면 최신 버전 빌드 성공시 까지 다른 버전을 보여준다.
} // blocking이면 서버사이드 렌더링을 하고 캐시되어 계속 같은것을 제공함
}
- 모든 라우팅에 대해 하나의 파일로 처리하기
[...id].js
// pages/posts/[...id].js matches /posts/a, but also /posts/a/b, /posts/a/b/c and so on.
//getStaticPaths
return [
{
params: {
// Statically Generates /posts/a/b/c
id: ['a', 'b', 'c']
}
}
//...
]
export async function getStaticProps({ params }) {
// params.id will be like ['a', 'b', 'c']
}
- API Routes
// You can do so by creating a function inside the pages/api directory that has the following format:
// req = HTTP incoming message, res = HTTP server response
// Try accessing it at http://localhost:3000/api/hello. You should see {"text":"Hello"}. Note that:
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json({ text: 'Hello' });
}
- API를 getStaticProps나 getStaticPath에서 쓸 필요 없음
- NextJS 앱은 그냥 노드라서 그냥 거기에서 DB 접근도 가능함
- 서버코드는 그냥 여기에서 써라
- Good Use Case : 인풋 핸들링 (폼의 POST)
export default function handler(req, res) {
const email = req.body.email
// Then save email to your database, etc...
}
추가로 보기
- Dynamic API Route
커스텀 404 페이지 만들기
- pages/404.tsx 파일 만들기
구경하기
404 not found (nextjs-emotion-typescript-blog.vercel.app)
반응형