해결된 질문
23.12.22 13:49 작성
·
299
1
안녕하세요! revalidateTag
함수 관련 코드를 보다가 궁금한 점이 생겨서 질문 드립니다!
우선 fetch
를 통해 데이터를 받아오는 비동기 호출은 서버 컴포넌트에서만 호출할 수 있다고 해서 날씨API나 시간API를 서버 컴포넌트에서 fetch
를 이용해 받아오는 것 까지는 이해가 갔습니다.
그런데 아래와 같이 캐시를 비우는 버튼을 만들 때는 클라이언트 컴포넌트에서 fetch
가 사용되었습니다.
'use client'
type Props = {
tag : string
}
export default function RevalidateButton({tag} : Props) {
const handleClick = async () => {
const res = await fetch(`/api/revalidate?tag=${tag}`, {
method : 'POST'
})
console.log(res)
}
return <button onClick={handleClick}>캐시 비우기</button>
}
일단 이벤트 핸들러는 클라이언트 컴포넌트에서 사용 해야 되서 'use client'
를 작성하는 것도 이해가 갔습니다. 그리고 revalidateTag
함수는 서버 컴포넌트에서 호출되야 하니깐 'api요청을 보내야 되서 fetch
를 사용해야 한다' 라고 이해를 했는데요.. 그럼 혼란 스러운게..
'fetch
비동기 호출은 서버 컴포넌트에서 하라고 되어 있는데 revalidateTag
같이 서버 컴포넌트에서 동작하는 함수를 호출하기 위해서는 어쩔 수 없이 fetch
를 클라이언트 컴포넌트에서 사용해야한다' 라고 이해 하는게 맞을까요??
그리고 위의 코드에서 method : 'POST'
라고 세팅하여 주셨는데 보내는 방식은 POST
로 정해져 있는 것인지, 다른 메서드 (get, update, delete)로 사용하면 안되는 것인지 궁금합니다!
아래는 핸드북(3. Next.js 손에 익히기 / 7.날씨데이터 조회하기 / 데이터 재검증하기 )에 설명해주신 내용인데요!
revalidateTag
는 서버 사이드에서 호출 가능합니다. 하지만 캐시를 풀어달라는 요청은 클라이언트(브라우저)에서 만들어집니다. 때문에 API 형태로revalidateTag
를 호출할 수 있도록 만들어야 합니다. Next.js에서의 API는 라우트 핸들러를 통해 만들 수 있습니다.
"캐시를 풀어달라는 요청은 클라이언트(브라우저)에서 만들어집니다." 라는 말이 RevalidateButton
버튼을 클릭했을 때 handleClick
함수가 호출되는 때를 말씀하신 것인지 궁금합니다.
아래는 revalidateTag
가 호출되는 서버 컴포넌트 코드입니다.
import { revalidateTag } from "next/cache";
import { NextRequest, NextResponse } from "next/server";
export async function POST(req:NextRequest) {
const tag = req.nextUrl.searchParams.get('tag');
if(!tag) throw new Error('태그는 필수!!')
revalidateTag(tag)
return NextResponse.json({message : '재검증에 성공했습니다', tag})
}
revalidateTag
함수는 호출시 에러가 발생하는 경우는 없는건가요?? 제 생각에는 revalidateTag
도 제대로 작동을 안할 수도 있으니깐 try catch
문으로 감싸서 호출하는게 맞지 않을까? 생각이 들었는데 그렇게 안해도 되는 것인지 궁금합니다!
답변 1
1
2023. 12. 23. 16:26
dawn님, 안녕하세요. 질문 남겨주셔서 감사합니다! 하나씩 답변드릴게요.
fetch
호출을 클라이언트에서 사용하는 이유에 대해
fetch
비동기 호출은 서버 컴포넌트에서 하라고 되어 있는데revalidateTag
같이 서버 컴포넌트에서 동작하는 함수를 호출하기 위해서는 어쩔 수 없이fetch
를 클라이언트 컴포넌트에서 사용해야한다' 라고 이해 하는게 맞을까요??
우선 revalidateTag
는 말씀 주신 것처럼 서버 컴포넌트, 라우트 핸들러에서 호출이 가능합니다. 이 말은 Node.js 서버에서 동작하는 함수라는 의미입니다. 때문에 예제에서는 /api/revalidate/route.ts
파일에 라우트 핸들러 방식으로 구현해서 재검증 로직을 구현했습니다.
다른 방식으로는 Server actions를 이용하는 방법이 있지만 이는 강의에서 다루지 않았습니다. Server actions를 사용하지 않는 우리 강의에서는 API 호출을 사용하는 게 최선입니다. 때문에 예제에서와 같이 /api/revalidate
와 같은 API를 정의하고 이를 클라이언트 컴포넌트에서 사용한 것입니다.
결론: App Router에선 fetch
비동기 호출을 서버 컴포넌트에서 했을 때 유리한 점이 있는 게 사실이지만 지금과 같은 상황에서는 클라이언트에서의 비동기 호출, 기존의 Client Side Renering 방식에서 쓰던 비동기 호출 패턴을 적용해야 한다라고 이해해주시면 좋을 것 같습니다. 이 외에도 상황에 따라 클라이언트에서 fetch
호출을 사용하는 경우는 많을 수 있습니다.
재검증 API 메서드에 대해
그리고 위의 코드에서
method : 'POST'
라고 세팅하여 주셨는데 보내는 방식은POST
로 정해져 있는 것인지, 다른 메서드 (get, update, delete)로 사용하면 안되는 것인지 궁금합니다!
정해져있는 건 아닙니다. 공식 문서에서는 GET을 쓰고 있습니다. 답변을 달며 생각해보니 저도 더 깊게 고민하지 않고 예제에 POST를 쓴 것 같네요. 질문 주신 덕에 생각해볼 수 있었습니다. 감사합니다.
결론: 어떤 방식이건 용도에 맞는 메서드를 선택하시면 됩니다. 보통은 재검증만을 수행하기 보다 다른 동작 이후에 재검증을 함께 하는 경우가 많을 것 같아요. 그에 맞게 적절한 메서드를 사용하시고 재검증도 함께 수행해도 좋을 것 같습니다.
캐시 요청, 핸드북의 설명에 대해
"캐시를 풀어달라는 요청은 클라이언트(브라우저)에서 만들어집니다." 라는 말이
RevalidateButton
버튼을 클릭했을 때handleClick
함수가 호출되는 때를 말씀하신 것인지 궁금합니다.
네, 맞습니다! handleClick
함수로 API를 호출하고 그 호출의 반응해 revalidateTag
가 호출되기 때문에 요청은 클라이언트에서 만들어진다고 표현했습니다.
revalidateTag 함수의 에러 발생 케이스에 대해
revalidateTag
함수는 호출시 에러가 발생하는 경우는 없는건가요?? 제 생각에는revalidateTag
도 제대로 작동을 안할 수도 있으니깐try catch
문으로 감싸서 호출하는게 맞지 않을까? 생각이 들었는데 그렇게 안해도 되는 것인지 궁금합니다!
네! 맞습니다. 정확하게 체크하기 위해선 말씀주신 것처럼 revalidateTag
함수를 try catch로 감싸 에러에 대한 적절한 대응을 해주는 게 맞습니다. revalidateTag
함수를 소개하는 것에 집중하다보니 놓친 부분인데 말씀해주셔서 다시 생각해보게 됐습니다. 감사합니다.
dawn님, 질문 주셔서 너무 감사합니다.
덕분에 제가 가장 많이 배운 것 같습니다. 좋은 질문해주셔서 감사합니다.
혹시 도움 드릴 수 있는 부분이 있다면 언제든 또 질문 남겨주세요!