티스토리 뷰

이전 글을 `Quick-news` 프로젝트에서 CSR 방식으로 데이터를 가져오는 것을 SSR 방식으로 변경하려다 실패했다고 작성했었다. 그리고, 마지막으로 한 번만 더 시도해보고 안 되면 CSR 방식으로 두기로 결정했다. 이 시도는 옳았다. 이제서야 SSR 방식으로 데이터를 가져오는 방법을 제대로 깨우쳤다.

 

이전에 SSR 방식으로 데이터를 가져왔던 시도는 다음과 같았다.

export default function List({posts}: Props) {
	// posts 데이터 사용
}

export async function getServerSideProps() {
  const url = 'https://jsonplaceholder.typicode.com/posts';

  try {
    const response = await axios.get<Post[]>(url);

    return {
      props: {
        posts: response.data,
      },
    };
  } catch (error) {
    console.error('API 호출 에러: ', error);
    return {
      props: {
        posts: [],
      },
    };
  }
}

 

`getServerSideProps`로 가져온 데이터를 사용할 컴포넌트에서 바로 `getServerSideProps`를 선언하고, 데이터를 바로 사용하려고 했었다. "왜 이렇게 사용하려고 했을까?" 생각해보면 오래 전 `getServerSideProps` 관련 강의를 보고 아주 간단한 실습을 했을 때, 위 처럼 코드를 작성해서 처리한 적이 있었다.

 

그리고, Next.js 공식 사이트나 구글 검색을 통해 접했던 블로그 내용들을 보면 위 처럼 사용 예시가 나와 있었기 때문에 "이렇게 사용하면 되겠구나"라고 생각했었다.

 

그러나, 수 많은 시행착오를 겪고 나서 SSR 방식으로 데이터를 가져오지 못했던 것을 어제가 되어서야 제대로 사용하는 방식을 알게 됐고, 원하던 데이터도 가져와 사용할 수 있었다.

 

나는 페이지 컴포넌트의 하위 컴포넌트에서 화면에 나타내려는 목적의 컴포넌트에서 `getServerSideProps`를 선언해서 처리했었는데, 이것이 아니라 페이지 컴포넌트에서 `getServerSideProps`를 선언해서 데이터를 페이지 컴포넌트의 하위 컴포넌트로 전달해서 사용해야 한다는 것을 이번 시도를 통해 배웠다.

export default function Home({posts}: Props) {
	...
    
    return (
    	...
    	<List posts={posts}/>
    )
}

export async function getServerSideProps() {
  const url = 'https://jsonplaceholder.typicode.com/posts';

  try {
    const response = await axios.get<Post[]>(url);

    return {
      props: {
        posts: response.data,
      },
    };
  } catch (error) {
    console.error('API 호출 에러: ', error);
    return {
      props: {
        posts: [],
      },
    };
  }
}

 

우선, 페이지 컴포넌트에서 `getServerSideProps`를 사용해서 데이터를 가져오고, 페이지 컴포넌트의 하위 컴포넌트로 해당 데이터를 전달한다.

export default function List({posts}: Props) {
	// posts 데이터 사용
    return {posts.map(post => ...)}
}

 

하위 컴포넌트는 전달받은 데이터를 가지고 사용하면 된다.

 

위 처럼 사용하면, 데이터를 제대로 가져와서 사용할 수 있다. 나는 그 동안 페이지 컴포넌트의 하위 컴포넌트에서 직접 `getServerSideProps`를 선언해서 사용했었는데, 이는 잘못된 방식이었다. 이번에 여러 가지 시도를 하면서 SSR 방식으로 데이터를 가져오는 방법에 대한 이해도를 조금 더 키울 수 있었다.

 

그렇다면, 왜 ` getServerSideProps`를 하위 컴포넌트에서 직접 사용할 수 없는 이유가 무엇일까? 이는 Next.js 구조와 동작 방식에 관련이 있다. 이 구조는 SSR과 페이지 컴포넌트의 역할에 대한 정의를 보면 알 수 있다.

 

페이지 기반 구조

Next.js는 `페이지` 단위로 동작하는 프레임워크로 모든 라우트는 페이지 컴포넌트에 의해 처리된다. 기본적인 설계로 페이지가 서버에서 데이터를 가져와서 렌더링을 하는 방식으로 되어 있기 때문에 `getServerSideProps`는 페이지 레벨에서만 동작한다.

 

서버 사이드에서 동작하는 로직

`getServerSideProps`는 서버에서 동작하는 함수로 서버가 클라이언트 요청을 받을 때, 그 페이지에 필요한 데이터를 미리 가져와 페이지 컴포넌트에 전달한다. Next.js는 이 `페이지`라는 단위를 기준으로 서버 사이드 렌더링을 처리하기 때문에 페이지가 아닌 하위 컴포넌트에서는 서버 측 데이터 페칭을 처리하지 않는다.

 

여기서 `페이지 컴포넌트`는 Next.js가 서버로부터 데이터를 가져와 렌더링할 때, 기준이 되는 최상위 컴포넌트이다. 이 컴포넌트가 서버에서 데이터를 가져오는 모든 로직을 처리해야 한다.

 

`하위 컴포넌트`는 클라이언트 측에서만 렌더링이 되며, Next.js는 서버에서 하위 컴포넌트에 대한 정보가 필요하지 않아 하위 컴포넌트에서 서버 사이드 로직을 실행하지 않는다.

 

페이지 단위 데이터 페칭 중요성

`getServerSideProps`는 페이지 컴포넌트에서 데이터를 가져와 페이지 전체를 렌더링하기 위한 것이다. 이 데이터를 받아 하위 컴포넌트에 전달하는 방식으로 데이터가 흐른다. Next.js는 페이지 컴포넌트가 사용자에게 보여지는 최종 HTML을 만들기 때문에, 페이지 레벨에서만 이와 같은 데이터를 가져오는 작업을 처리한다.

 

하위 컴포넌트는 클라이언트 렌더링에 집중하고, 서버에서 데이터를 가져오고 관리하는 책임은 페이지 컴포넌트가 맡는다. 따라서, 하위 컴포넌트에서 직접 `getServerSideProps`를 사용할 수 없고, 상위 페이지 컴포넌트에서 데이터를 가져와 하위 컴포넌트로 전달해 사용해야 한다.