til

Next.js입문 9일 차(完) @보완 지식들

fpzmfks 2024. 10. 8. 20:34

오늘은 과제 풀이 영상과 함께 개인과제 재제출 기간이 찾아왔다. 재제출을 하지는 않겠지만 이왕 시간이 난 김에 내가 한 과제와 영상을 비교하며 코드를 더 살펴보았는데, 몇 가지 기록해둘 만하다고 생각한 것들이 있어서 오늘의 TIL로 남기기로 했다. 

 

첫번째는 use client를 사용한 클라이언트 컴포넌트가 static으로 빌드된 것이다.

기존에는 아래와 같이 직접적으로 페이지에 use client를 쓰지 않고 하위 클라이언트 컴포넌트를 만들어서 가져왔기 때문에 어련히 기본 모드인 ssg로 빌드되었겠거니 했는데, 아래와 같이 페이지에 직접적으로 use clinet를 사용해도 static으로 빌드된 모습을 확인할 수 있었다. 

튜터님께 문의해보니 이게 의아하게 느껴지는 것은 서버 컴포넌트와 서버사이드렌더링을 동일시 하는 인지오류가 있기 때문이라고 한다.

 

서버사이드렌더링 =/= 서버 컴포넌트이기 때문에

동적렌더링=/=클라이언트 컴포넌트

 

라는 것이다. next.js의 클라이언트 컴포넌트는 명칭은 이렇지만 여전히 서버사이드 렌더링에 포함되기 때문에 build 시 static으로 되는 것이다. 

 

다만 이러한 클라이언트 컴포넌트가 다른 ssg나 isr과 같이 그려지는 것은 아니고, 필요한 만큼 동적으로 페이지가 그려진다.

 

사실 아주 정확하게는 잘 모르겠지만 ssg와 isr로 구성한 챔피언, 아이템 페이지는 클릭하면 잠시 뒤 목록이 다 그려진 상태로 페이지를 보여주는데, 'use clinet'로 구성한 챔피언 로테이션 페이지는 먼저 페이지에 들어간 다음 목록이 그려지는 모습을 볼 수 있었다. 

 

이런식으로 먼저 정적으로 초기 렌더링을 하고 나중에 js 같은 요소를 집어넣는 것hydration이라고 하는데, js뿐만 아니라 이러한 목록 그리기에도 hydration이 적용되고 있는 것 같다. 

 

 

두번째는 API에서의 type에 대한 것이다.

나는 이번 개인과제를 진행할 때 serverAPI를 작성하면서 주로 아래와 같은 방식으로 타입을 선언했다. 함수 내부에서 선언한 변수에 타입을 적용하고 이후 관련 변수들과 리턴값의 타입을 추론하게 하는 것이다. 아무래도 아직 타입스크립트에 익숙하지 않은 입장에서 모든 타입을 핸들링하는 것은 부담이 되었던 것이다. 

// 챔피언 가져오기
export const fetchChampionList = async () => {
  const version = await getVersion();
  const response = await fetch(
    `https://ddragon.leagueoflegends.com/cdn/${version.result}/data/ko_KR/champion.json`,
    {
      next: { revalidate: 86400 },
    }
  );
  if (!response.ok) {
    return { error: "챔피언 데이터 오류", result: null };
  }
  const { data } = await response.json();
  const championsData: Champion[] = Object.values(data);

  return { error: null, result: championsData };
};

 

다만 개인과제 해설 영상에서는 다음과 비슷하게 더 꼼꼼하게 타입을 적용하기도 했다. 아래는 비교적 리턴 구조가 간단한 버전 가져오기에 시범적으로 꼼꼼한 타입적용을 해본 것이다. 

// 버전 가져오기
export const getVersion = async (): Promise<{
  error: string | null;
  result: string | null;
}> => {
  const response: Response = await fetch(
    "https://ddragon.leagueoflegends.com/api/versions.json"
  );
  if (!response.ok) {
    return { error: "버전 데이터 오류", result: null };
  }
  const data: string[] = await response.json();
  return { error: null, result: data[0] };
};

 

편하기로는 전자가 더 편하기는 하지만, 이전에 에러 핸들링 때, 리턴 타입으로 헤매던 것을 생각하면 이런 식으로 리턴 타입을 어떻게 줄지 더 고민해보는 것도 중요한 것 같긴 하다.