til

Next.js입문 8일 차 @트러블 슈팅

fpzmfks 2024. 10. 7. 20:05

라우트 핸들러

원하는 response값이 아니라 request값만 불러와지는 문제

알고보니 라우트 핸들러는 서버 컴포넌트에서는 사용하면 안 되고 클라이언트 컴포넌트에서만 사용할 수 있었다. use client를 사용한 컴포넌트에서 불러오니 정상적으로 request값이 불러와졌다. 

 "use client"환경
 
 const [rotation, setRotation] = useState<Champion[]>([]);
  const getRotation = async () => {
    const { data }: { data: Champion[] } = await fetch("/api/lolAPI").then(
      (res) => res.json()
    );
    console.log(data);
    setRotation(data);
  };
  useEffect(() => {
    getRotation();
  }, []);

 

 

api 에러 핸들링

api 에러 핸들링을 하는데 return 타입 오류가 떴다. response.ok가 false이면

 

return {error:"챔피언 데이터 오류"}를 하는 로직을 추가했는데 이러한 return 값은 아래의 정상적인

 

return {data:championsData} 와 상충되기 때문에 일어난 문제였다. 

 

스스로는 이 문제를 어떻게 해결하면 좋을지 아이디어가 떠오르지 않아서 튜터님께 질문을 했는데, 아래와 같은 해답을 제시해주셨다. 두 개의 리턴 값을 아래와 같이 형식을 통일해주는 것이다. 

// 챔피언 가져오기
export const fetchChampionList = async () => {
  const version = await getVersion();
  const response = await fetch(
    `https://ddragon.leagueoflegends.com/cdn/${version.result}/data/ko_KR/champion.json`,
    {
      headers: { "Content-Type": "application/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 };
};

 

 

다크모드

자꾸만 쿠키가 존재하지 않는 최초 다크모드 클릭 시 mode쿠키에 light만 저장되는 오류

아래 코드에서 if문을 두 번 사용했는데 나의 의도는 최초 쿠키 세팅 시 위쪽 if문만 작동하는 것이었지만, 최초 세팅 시에 아래쪽 if문도 작동하기 때문에 항상 light가 세팅되는 것이었다.

export const cookieAction = () => {
  const cookieStore = cookies();
  if (!cookieStore.has("mode")) {
    cookieStore.set("mode", "dark");
  }

  const cookie = cookieStore.get("mode")?.value;
  if (cookie === "dark") {
    cookieStore.set("mode", "light");
  } else {
    cookieStore.set("mode", "dark");
  }
};

어차피 아래쪽 if문의 else문으로 쿠키가 없을 때의 처리도 가능하기 때문에 위쪽의 if문을 지웠다

 

다크모드를 기본모드로 정리한 코드

export const cookieAction = () => {
  const cookieStore = cookies();
  const cookie = cookieStore.get("mode")?.value;
  if (cookie === "light") {
    cookieStore.set("mode", "dark");
  } else {
    cookieStore.set("mode", "light");
  }
};

 

FoUC(Flash of Unstyled Content)(보류)

다크모드를 구현하기는 했지만 useEffect로 초기 렌더링을 일으키기 때문에 새로고침을 하면 스타일 설정이 반드시 초기화되어 항상 라이트 모드가 화면에 보이는 문제가 생겼다. 검색을 통해 찾아보니 이러한 문제를 FoUC라고 부르는데, 보통 html head에 script를 삽입해서 렌더링 전에 스타일을 적용해서 쉽게 해결할 수 있었다고 한다. 다만 next.js에는 html파일이 따로 없으니 더 방법을 강구해야 했다. 

 

찾아보니 두 가지 해결 방법이 있는 것 같다.

첫번째는 _document.tsx파일을 이용하는 방법이다. next.js 환경에서는 _document.tsx로 html 구조를 정의하면서 head에 script를 삽입하는 것으로 문제를 해결할 수 있었다고 한다. 

두번째는 _app.tsx파일을 이용하는 방법이다. 이 파일은 항상 가장 먼저 실행되기 때문에 이 파일에서 쿠키에 따른 스타일 설정을 해서 렌더링 전에 스타일을 지정할 수 있다면 직관적인 해결방법이 될 것이라고 생각한다. 

 

하지만 _app.tsx나 _document.tsx에서는

document.documentElement.classList.remove("dark")

와 같은 DOM요소를 사용할 수 없다고 한다.

 

다른 글을 보니 13버전 이후로는 최적화를 위해서 layout.tsx에서 불러들인다고 하는데 이건 이미 시도했다가 여기서도 DOM요소를 사용할 수 없다는 것을 확인했다. 

 

그런데 글을 잘 읽어보니 DOM요소를 직접적으로 선언하는 것은 안 되지만 백틱을 이용해 html요소를 문자열로 삽입해두는 것은 되는 것 같았다.

 

다만 이런 방법으로도 문제를 해결하지는 못했는데, next.js가 이러한 dom요소를 파싱하지 못하기 때문에 라이브러리를 설치해서 사용해야 하고, 또 보안 문제 때문에 이러한 방식을 사용하려면 라이브러리를 더 설치해야 한다고 한다. 

 

때문에 이 문제는 보류했다.

 

에러 메세지

에러 핸들링을 했는데 내가 원하는 커스텀 에러 메세지가 표시되지 않았다. 

튜터님께 상의해보니 내가 오류를 내는 방식이 잘못된 것이었다. 나는 이전까지 주로 오류 내는 방식을 URL 가장 앞의 http에서 h를 지우는 방식으로 했는데, 이건 fetch오류를 내기 때문에 내가 원하는 결과값이 나오지 않는 것이었다. 내가 원하는 메세지를 출력시키기 위해서는 version과 같은 pathname을 건들여서 api통신 오류를 내야 한다. 

또 tailwind, grid로 간단하게 목록에 반응형을 적용하여 이번 프로젝트를 마무리하였다. 

 

기타 기록들(90~93)

 

https://fpzmfks.tistory.com/90

 

Next.js입문 4일 차 @본격 시작, route handler

오늘은 모든 강의를 완강하고 본격적으로 개인 과제를 시작했다. 이번 과제는 lol 게임 정보 사이트를 만드는 것으로, 이전에 라우터 처리는 해두었기 때문에 오늘은 fetch에 집중했다.   첫번째

fpzmfks.tistory.com

https://fpzmfks.tistory.com/91

 

Next.js입문 5일 차 @개인 과제 55%

오늘은 개인과제에 집중해서 과제를 반 정도 해내었다. 3개의 데이터 목록을 완성하고, 1개의 상세페이지를 불러올 수 있게 되었으므로 이로써 3.5/6를 완성한 것이다. 앞으로 2개의 상세페이지

fpzmfks.tistory.com

https://fpzmfks.tistory.com/92

 

Next.js입문 6일 차 @개인 과제 100%+최적화

오늘은 무사히 과제 필수 요건을 완수하고 최적화를 어느 정도 진행했다.  다만 한 가지 아쉬웠던 것은 item 상세페이지를 구성할 때, API 요청 시 특정 아이템만 지정하는 방법을 끝내 찾지 못해

fpzmfks.tistory.com

https://fpzmfks.tistory.com/93

 

Next.js입문 7일 차 @개인 과제 100%+다크모드

오늘은 다크모드를 구현해보고(비록 디자인은 각이 안 나왔지만) 챌린지반 기술면접 시험을 보았다.  먼저 기술면접을 짚고 넘어가자면, 리액트 훅이나 useContext, zustand의 차이 같은 것들은 잘

fpzmfks.tistory.com