서버 컴포넌트(Server Components)
어디에서 실행될까?
서버 컴포넌트는 Next.js 서버에서 실행된다. 여기서 Next.js 서버는 Node.js 환경에서 작동하는 서버이다. 이 서버는 사용자가 페이지를 요청할 때 페이지를 생성하고, 그 결과를 브라우저에 전달한다.
어떤 환경인가요?
서버 컴포넌트는 서버 환경에서 실행되기 때문에, 이 컴포넌트에서 실행되는 코드는 브라우저에서 실행되지 않는다. 즉, 클라이언트 측에서 사용할 수 있는 브라우저 API(예: window
, document
)에 접근할 수 없다.
클라이언트 컴포넌트(Client Components)
어디에서 실행되나요?
클라이언트 컴포넌트는 브라우저에서 실행된다. 사용자의 브라우저가 페이지를 로드한 후에 추가로 실행되는 js 코드이다.
어떤 환경인가요?
클라이언트 컴포넌트는 브라우저 환경에서 실행되기 때문에, 브라우저에서 제공하는 (document
, window
등)에 접근할 수 있다. 이 컴포넌트는 사용자의 브라우저에서 직접 렌더링되고, 브라우저가 제공하는 현재 URL과 도메인을 기반으로 동작한다.
// 서버 컴포넌트에서 실행되는 코드
export async function getData() {
const response = await fetch('http://localhost:3000/api/some-endpoint');
const data = await response.json();
return data;
}
// 클라이언트 컴포넌트에서 실행되는 코드
useEffect(() => {
fetch('/api/some-endpoint')
.then(response => response.json())
.then(data => console.log(data));
}, []);
그 이유는 서버와 클라이언트의 근본적인 역할의 차이점 때문이다. 클라이언트의 브라우저는 항상 현재 웹 페이지의 도메인과 URL 정보를 알고있다. 따라서 상대경로를 사용할 때 문제가 없다.
반면 서버의 역할은 클라이언트의 요청을 받아들이고 그 요청에 따라 응답을 전송한다. 이때 서버는 브라우저와 달리 현재 페이지의 도메인을 자동으로 알아내지 못한다. 이는 서버가 응답하는 시점에서 그 응답값이 실제로 어디에서 표시될지 모를 수 있기 때문이다.
때문에 서버 컴포넌트에서의 호출은 현재 클라이언트의 도메인을 정확히 모르기 때문에 절대경로를 사용하여 호출해야하며, 클라이언트 컴포넌트는 현재의 도메인을 정확히 알기 때문이 상대경로를 호출할 수 있는 것이다.
위와 비슷한 이유로, 서버 컴포넌트는 fetch
로 데이터 통신을 할 때 클라이언트 컴포넌트와 달리 현재 웹 페이지의 도메인과 관련된 headers
에 관한 정보를 자동으로 넘겨주지 않는다. 브라우저 환경이 아니기에 클라이언트의 세션이나 쿠키 정보를 가지고 있지 않기 때문이다. 따라서 서버사이드의 fetch
에서 현재 클라이언트의 쿠키, 인증 헤더 등의 headers
정보를 넘겨주어야할 경우에는 수동으로 넣어주어야 한다.
Next.js의 에서 제공하는 headers()
함수는 서버 컴포넌트에서 클라이언트가 보낸 HTTP 요청의 헤더 정보를 가져오는 기능을 한다. 이를 통해 클라이언트가 전송한 쿠키나 인증 정보를 서버 측에서 액세스할 수 있다.
import { headers } from 'next/headers';
export async function getData() {
const clientHeaders = await headers(); // 클라이언트가 보낸 헤더를 가져옴
const response = await fetch('https://external-api.com/data', {
method: 'GET',
headers: {
'Authorization': clientHeaders.get('Authorization'), // 클라이언트의 인증 헤더를 전달
'Cookie': clientHeaders.get('Cookie'), // 클라이언트의 쿠키를 전달
}
});
const data = await response.json();
return data;
}