
아니 프론트엔드 서버가 터져가지고 봤더니
아니 클라우드와치에 계속 이런 에러가 누적되어있었네?
아니 근디 찾아보니까 컴포넌트 내부에서 useEffect로 안감싸고 아래코드처럼 router.back()을 호출하니까 이런게 발생한거였네?
"use client";
import { useRouter } from "next/navigation";
export default function CheckupDetailModal() {
if (!specificItem) {
router.back(); <- 이부분 컴포넌트 렌더링 중 호출되는 부분이라 추정됨 여기가 문제임
return <></>;
}
return (
<div>어쩌고저쩌고..</div>
}
일단 현상과 원인 적고 깊은 원리는 천천히 알아볼 예정
나중에 까먹을까봐 일단 적음
정리된 원인부터 적자면 아래와 같다.
?? 아니 'use client'를 사용하는 컴포넌트인데 뭔 갑자기 서버에서 실행하다 window가 있네 없네 하는거여 ??
'use client' 사용하면 그냥 클라이언트 컴포넌트로서 클라이언트 사이드에서만 렌더링 하는거 아님?
아님 그게 아님.. 요즘 너무 공부를 안하고 있었던게 이렇게 탄로난다.
예전 Next.js 12버전 이전에 사용하던 개념이랑 헷갈렸던것 같다.
'use client'는 Next.js의 App Router에서 클라이언트 컴포넌트임을 선언하는 지시문이다.
클라이언트 컴포넌트는 클라이언트측에서 동작해야 하는 인터랙티브한 로직(useState, useEffect, useRouter 등..)을 포함할 수 있다.
그런데 'use client' 썻다고 서버사이드 렌더링이 완전히 배제되는것이 아니다!
AppRouter를 사용하는 Next.js는 기본적으로 서버에서 컴포넌트를 먼저 렌더링 한다.
그 후 클라이언트에서 하이드레이션 과정을 통해 컴포넌트를 인터렉티브하게 만든다..!
대략 순서대로 적으면 아래와 같다.
근데 하이드레이션(hydration)이 정확히 뭐임?
하이드레이션은 서버에서 생성된 HTML을 클라이언트(브라우저)에서 javascript로 활성화 하는 과정이다.
즉, 서버에서 미리 렌더링된 정적인 HTML에 React(Next.js)의 인터랙티브한 기능을 붙여서 사용자가 버튼 클릭이나 상태 변경 같은 동적인 동작을 할 수 있도록 만드는 과정이다.
하이드레이션 과정은 아래와 같다.
서버로부터 받은 Javascript 파일안에 React 코드와 이를 실행하기 위한 React 런타임, 그리고 Next.js의 클라이언트 측 로직이 포함되어있다.
그래서 컴포넌트 트리를 만들고 DOM 트리와 비교할 수 있는거임
- React 코드 : 'use client'로 선언된 컴포넌트의 javascript 코드(예: JSX를 변환한 코드, useEffect, useState 같은 훅, 이벤트 핸들러 등)가 포함됨. 이 코드는 컴포넌트의 구조와 동작을 정의
- React 런타임 : React가 브라우저에서 컴포넌트를 렌더링하고, 상태를 관리하며, 이벤트 리스너를 추가하는데 필요한 라이브러리 코드
- Next.js 관련 코드 : Next.js의 클라이언트 측 라우팅(useRouter같은 훅), 하이드레이션 로직, 그리고 페이지 간 전환을 처리하는 코드들
- 번들 : 이 모든 코드는 Next.js가 빌드 시 Webpack같은 도루고 번들링되어 최적화된 Javascript 파일로 브라우저에 전송됨.
"use client";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
export default function CheckupDetailModal({ specificItem }) {
const router = useRouter();
useEffect(() => {
if (!specificItem) {
router.back();
}
}, [specificItem, router]);
if (!specificItem) {
return null; // 또는 로딩 상태나 빈 프래그먼트를 반환
}
return <div>어쩌고저쩌고..</div>;
}
아주 간단하죵.?
그냥 router.bakc() 호출을 클라이언트 측에서만 실행되도록 강제하면 될일임.
이를 위해 useEffect를 사용해 클라이언트 렌더링이 완료된 후 해당 로직을 실행하도록 수정함.
애초에 기본도 모르고 작성한 코드가 문제였고 이제 이유 알았음.
재밋었다.