민희의 코딩일지

[Next] 기본파일구조, Data Fetching 본문

WEB FE/Next

[Next] 기본파일구조, Data Fetching

heehminh 2023. 3. 19. 21:33
반응형

1- Next.js 의 장점

React의 SSR(Server Side Rendering)을 쉽게 구현할 수 있게 도와주는 프레임워크이다. (*React는 라이브러리이다.) React로 개발할 때 SPA를 이용하여 CSR(Client Side Rendering)을 하기 때문에 좋은 점도 있지만, 검색엔진 최적화 부분에 취약하다. (SEO) CSR를 하면 첫페이지에서 빈 html을 가져와서 JS 파일을 해석하여 화면을 구성하기 때문에 포털 검색에 거의 노출될 일이 없다.

그러나, Next.js에서는 Pre-Rendering을 통해 페이지를 미리 렌더링하며 완성된 html을 가져오기때문에 사용자와 검색엔진 크롤러에게 바로 렌더링된 페이지를 전달할 수 있다.

원래 React의 방식 (4단계에 화면보임)

SSR (2단계부터 화면보임)

SSR (Server-Side-Rendering)

클라이언트 대신 서버에서 페이지를 준비하는 원리이다. 원래 리액트에서는 CSR을 하기 때문에 서버에 영향을 미치지 않고, 서버에서 클라이언트로 응답해서 보낸 html도 거의 비어있다.

⇒ 이 방식은 서버에서 데이터를 가져올 때 지연 시간 발생으로 UX 측면에서 좋지 않다. 검색 엔진에 검색 시 웹 크롤링이 동작할 때 내용을 제대로 가져와 읽을 수 없기 때문에 검색엔진 최적화에 문제가 된다.

Next.js에서는 SSR을 이용하므로 사용자와 검색 엔진 크롤러에게 바로 렌더링된 페이지를 전달할 수 있어서 검색엔진 최적화에 좋은 영향을 준다.

 

설치

npx create-next-app@latest

npx create-next-app@latest —typescript

2- Next.js 기본 파일 구조

  1. pages -  이 폴더 안에 페이지를 생성한다.
    • index.tsx가 처음 “/” 페이지가 된다.
    • app.tsx는 공통되는 레이아웃을 작성한다. 모든 페이지에 공통으로 들어가는 걸 넣어주려면 여기에 넣어준다. (url을 통해 특정 페이지에 진입하기 전 통과하는 인터셉트 페이지이다.)
    • 만약 about이라는 페이지를 만드려면 pages 폴더안에 about.tsx를 생성하면 된다.
  2. public - 이미지같은 static asset 을 보관한다.
  3. styles - 모듈 (module) css는 컴포넌트를 종속적으로 스타일링을 하기 위한것이며, 확장자 앞에 module을 붙여줘야 한다.
  4. next.config.js - Next.js는 웹팩을 기본 번들러로 사용한다. 그래서 웹팩에 관한 설정들을 이 파일에서 해준다.

3- Data Fetching

보통 react에서 데이터를 가져올 때 useEffect안에서 가져온다. 그러나 next에서는 애플리케이션의 사용 용도에 따라 다른 방법을 사용해준다.

a. getStaticProps

Static Generation으로 빌드할 때 데이터를 불러온다. (미리 만들어줌)

export async function getStaticProps(context) {
	return {
		props: {}, // will be passed to the page component as props
	}
}

getStaticProps 함수를 async으로 export하면, getStaticProps에서 리턴되는 props를 가지고 페이지를 pre-render한다. build time에 페이지를 렌더링한다.

// posts will be populated at build time by getStaticProps()
function Blog({ posts }) {
	return (
		<ul>
			{posts.map((post) => (
				<li>{post.title}</li>
			))}
		</ul>
	)
}
// This function gets called at build time on server-side
// It won't be called on client-side, so you can even do
// direct database queries
export async function getStaticProps() {
	// Call an external API endpoint to get posts 
	// You can use any data fetching Library
	const res = await fetch("https://.../posts")
	const posts = await res.json()

	// By returning { props: { posts } },
  // the Blog component will receive "posts" as a porop at build time 
	return {
		props: {
			posts,
		},
	}
}

export default Blog

getStaticProps는

  • 페이지를 렌더링하는데 필요한 데이터 - 사용자의 요청보다 먼저 build 시간에 필요한 데이터를 가져올 때
  • 데이터는 Headless CMS에서 데이터를 가져올 때
  • 데이터를 공개적으로 캐시할 수 있을 때 (사용자별 X)
  • 페이지는 미리 렌더링되어야 하고 (SEO의 경우) 매우 빨라야할 때 (getStaticProps는 성능을 위해 CDN에서 캐시할 수 있는 HTML 및 JSON 파일을 생성한다.)

경우에 사용한다.

export async function getStaticProps() {
	return {
		paths: [
			{ params : { ... } }
		],
		fallback: true // false or "blocking"
	};
}

b. getStaticPaths

동적 라우팅이 필요할 때 getStaticPaths 로 경로 리스트를 정의하고, HTML에 build 시간에 렌더링된다. Next.js는 pre-render에서 정적으로 getStaticPaths 에서 호출하는 경로들을 가져온다.

 

paths

만약 pages/posts/[id].js 라는 이름의 동적 라우팅을 사용하는 페이지가 있다면 빌드하는 동안 /posts/1 과 /posts/2 를 생성한다.

return { paths: [ { params: { id: "1" } }, { params: { id: "2" } } ], fallback: ... }

어떠한 경로가 pre-render 될지 결정

 

params

페이지 이름이 pages/posts/[postsId]/[commentId] 라면, params는 postId와 commentId 이다. 만약 페이지 이름이 pages/[…slug]와 같이 모든 경로를 사용한다면, params는 slug가 담긴 배열이어야 한다. [”postId”, “commentId”]

 

fallback

true라면 getStaticPaths 로 리턴되지 않는 것은 404로 뜨지 않고, fallback 페이지가 뜬다.

false라면 getStaticPaths 로 리턴되지 않는 것은 모두 404 페이지가 뜬다.

// If the page is not yet generated, this wiil be displayed 
// 페이지가 아직 생성되지 않은 경우 표시되는 내용 
if (router.isFallback) {
	return <div>Loading...</div>
}

 

pages/posts/[id].js

function Posts({ post }) {
	// Render post ...
}

getStaticPaths()

// This function gets called at build time 
export async function getStaticPaths() {
	// Call an external API endpoint to get posts 
	const res = await fetch("https://.../posts")
	const posts = await res.json()
	
	// Get the paths we want to pre-render based on posts 
	const paths = posts.map((post) => ({
		params: { id: post.id},
	}))
	
	// We'll pre-render only these paths at build time.
	// { fallback: false } means other routes should 404
	return { paths, fallback: false }
}

getStaticProps()

// This also gets called at build time
export async function getStaticProps({ **params** }) {
	// params contains the post `id`.
	// If the route is like /posts/1, then params.id is 1
	const res = await fetch(`https://.../posts/${params.id}`)
	const post = await res.json()
	
	// Pass post data to the page via props
	return { props: { post } }
}

c. getServerSideProps

Server Side Rendering으로 요청이 있을 때 데이터를 불러온다.

export async function getServerSideProps(context) {
	return {
		props: {}, // will be passed to the page component as props
	}
}

getServerSideProps 함수를 async 으로 export 하면, Next 는 각 요청마다 리턴되는 데이터를 getServerSideProps 로 pre-render 한다.

function Page({ data }) {
	// Render data...
}

// This get called on every request 
export async function getServerSideProps() {
	// Fetch data from external API 
	const res = await fetch(`https://.../data`)
	const data = await res.json()
	
	// Pass data to the page via props
	return { props : { data } }
}

export default Page 

getServerSideProps 는

  • 요청할 때 데이터를 가져와야하는 페이지를 미리 렌더해야 할 때 사용한다. 서버가 모든 요청에 대한 결과를 계산하고, 추가 구성없이 CDN에 의해 결과를 캐시할 수 없기 때문에 첫번째 바이트까지의 시간은 getStaticProps 보다 느리다.
반응형
Comments