nextjs에서 서버쪽의 데이터를 가져와서(fetch) 이를 UI에 반영하는 방법을 살펴보겠습니다.
소스코드
https://github.com/egoing/nextapp/commit/81574894fc05a40e6a0308c54d5cb1ce17d27037
server component
nextjs의 컴포넌트는 크게 server component와 client component로 구분됩니다. 특별한 처리를 하지 않으면 nextjs에서 컴포넌트는 server component 입니다.
위의 그림을 보면 S가 server, C가 client component의 사용 사례를 보여줍니다.
서버 컴포넌트는 아래와 같은 경우에 사용합니다.
- 사용자와 상호작용하지 않는 경우
- 백엔드에 엑세스하면서 보안적으로 위험한 정보를 주고 받는 경우
클라이언트 컴포넌트는 아래와 같은 경우 사용합니다.
- 서버 컴포넌트로 해결되지 않는 경우
- 사용자와 상호작용하는 경우
- useEffect, useState, onClick, onChange와 같은 API를 사용해야 하는 경우
- useRouter, useParams와 같은 nextjs의 client component API를 사용하는 경우
아래는 nextjs의 구분법
1. app/layout.js를 아래와 같이 편집합니다.
server component에서는 fetch를 사용할 때 useEffect를 사용하지 않습니다. 또 fetch를 이용할 때 await를 사용합니다.
export default async function RootLayout({ children }) { const resp = await fetch('http://localhost:9999/topics/') const topics = await resp.json();
2. 글목록을 생성합니다.
{topics.map(topic=>{ return <li key={topic.id}><Link href={`/read/${topic.id}`}>{topic.title}</Link></li> })}
app/layout.js의 전체코드는 아래와 같습니다.
import Link from 'next/link' import './globals.css' export const metadata = { title: 'WEB tutorial', description: 'Generated by egoing', } export default async function RootLayout({ children }) { const resp = await fetch('http://localhost:9999/topics/') const topics = await resp.json(); return ( <html> <body> <h1><Link href="/">WEB</Link></h1> <ol> {topics.map(topic=>{ return <li key={topic.id}><Link href={`/read/${topic.id}`}>{topic.title}</Link></li> })} </ol> {children} <ul> <li><Link href="/create">create</Link></li> <li><Link href="/update/id">update</Link></li> <li><button>delete</button></li> </ul> </body> </html> ) }
실험
console.log를 이용해서 출력해보세요.
export default async function RootLayout({ children }) { const resp = await fetch('http://localhost:9999/topics/') const topics = await resp.json(); console.log('page/layout.js/topics', topics)
출력 결과가 개발자 도구의 콘솔에서는 나타나지 않고, 터미널에서만 출력 됩니다.
서버 컴포넌트는 모든 작업을 서버 쪽에서 처리하고, 그 결과인 html 코드만 클라이언트로 전송합니다. 이것을 서버쪽에서 랜더링을 한다고해서 server side rendering이라고 합니다.
좋은 점
- 간결한 코드: useEffect와 useState와 같은 훅을 사용하지 않아도 되므로, 코드가 더 간결하고 이해하기 쉬워집니다. 이로 인해 코드 유지 관리가 쉬워지고, 버그 발생 확률이 줄어들 수 있습니다.
- 빠른 데이터 엑세스: 데이터베이스와 같은 자원에 접근해야 하는 경우, 서버 컴포넌트는 서버와 데이터베이스가 가까운 위치에서 작동하므로, 더 빠른 속도로 필요한 데이터에 접근할 수 있습니다.
- 보안: 서버 컴포넌트는 클라이언트에 민감한 정보(예: 데이터베이스 비밀번호)를 전송하지 않습니다. 이로 인해, 필요한 작업을 안전하게 처리하면서 동시에 클라이언트의 보안을 유지할 수 있습니다.
- 향상된 성능: 서버 컴포넌트는 클라이언트로 JavaScript 코드를 전송하지 않습니다. 이는 전송되는 데이터의 양을 줄이고, 클라이언트의 부하를 줄임으로써 웹사이트의 전반적인 성능을 향상시키는데 도움이 됩니다.