2026.09.28 · 3분 읽기 · 조회 0
데이터 페칭을 할 때 보통 try/catch 문을 많이 사용한다.
try {
await response = ...
} catch(error) {
return <div>에러...</div>
}이런 식으로 예외처리를 해주어도 좋으나, 모든 데이터 페칭 로직에 catch 내부 값을 따로 적어주는 것은 비효율적이고 코드가 복잡해질 수 있다. 이럴 때 error.tsx 파일을 사용한다.
같은 폴더 내에 error.tsx 파일을 만든다.
"use client"
export default function Error(){
return <div>에러 발생</div>
}다음과 같이 에러 발생 시 보여줄 값을 리턴해주면, catch 문 없이도 에러 발생 시 해당 에러 컴포넌트를 띄워줄 수 있다. error.tsx도 역시 하위 페이지의 오류까지 한 번에 처리할 수 있다.
당연히 브라우저에서 에러를 띄워줄 수 있어야 하기 때문에 "use client"로 클라이언트 컴포넌트로 만들어준다.
export default function Error({error} : {error : Error}){
return <div>에러 발생</div>
}error.tsx의 컴포넌트는 첫 번째 파라미터로 error 값을 받을 수 있으며, 해당 객체에는 오류의 내용이 들어있다. 자바스크립트의 기본 Error 타입이다.
error.message 로 에러 내용을 확인 가능하다.
export default function Error({reset} : {reset : () => void }){
return <div>에러 발생</div>
}두 번째 인자로 reset이라는 함수를 받을 수 있다. 타입은 () => void이다. 해당 함수는 에러가 발생한 페이지를 복구하기 위해, 다시 한 번 컴포넌트들을 렌더링 시켜보는 기능을 지닌다.
export default function Error({reset} : {reset : () => void }){
return
<>
<div>오류 발생</div>
<button onClick={() => reset}>다시시도</button>
</>
}이렇게 적으면 다시시도 버튼을 누르면 재렌더링 시도를 한다.
주의할 점은, 서버에 데이터 페칭을 다시 보내는 것이 아니라, 클라이언트 측에서 이미 서버에서 받은 데이터로 재렌더링 시도만 한다는 것이다.
<button onClick={() => window.location.reload()}>다시시도</button>차라리 window 객체를 이용해 새로고침을 시키는게 나을 수도 있다. 이러면 서버에 다시 페칭요청을 하니말이다. 하지만 이렇게 하면 state 정보가 다 날아갈 것이다.
좀 더 우아하게 새로고침을 시켜보자. 상태를 유지시키면서
import { useRouter } from "next/navigation";
const router = useRouter();라우터 훅을 next/navigation 에서 받아온다.
<button onClick={() => router.refresh()}>다시시도</button>재시도 버튼 클릭 시 router.refresh 메서드를 실행하게 만든다.
해당 메서드는 현재 페이지에 필요한 서버 컴포넌트를 다시 next 서버에서 렌더링시키는 역할을 한다.
당연히 데이터 페칭이 다시 일어난다.
<button
onClick={() => {
router.refresh();
reset();
}}
>
다시 시도
</button>그리고 이제 reset 함수를 호출해 브라우저 사이드를 재렌더링한다.
reset은 에러상태를 초기화하고, 컴포넌트들을 다시 렌더링하기 때문에 이것을 활용해 에러상태를 초기화해주어야 한다.
여기서 router.refresh()는 사실 비동기적으로 동작한다. 때문에 refresh 가 끝나기도 전에 reset이 실행되어 오류가 고쳐지지 않는다.
<button
onClick={async () => {
await router.refresh();
reset();
}}
>
다시 시도
</button>"그럼 그냥 async/await" 붙이면 되겠네? <- 안된다. refresh 함수의 리턴값은 프로미스가 아니라 그냥 void다. 그럼 어떻게 해결해야 할까?
startTransition이라는 메서드를 사용해야 한다.
startTransition(() => {});내부에는 콜백함수가 들어가는데, 콜백함수 내부에 "UI를 변경시키는 작업"을 일괄적으로(동시에) 처리해준다.
startTransition(() => {
router.refresh();
reset();
});이렇게 사용하면 두 개가 동시에 처리가 되기 때문에 잘 작동할 것이다.
앱과 웹을 만들고, 직접 운영하며 기록합니다.
giscus로 동작하며 GitHub Discussions에 저장됩니다.