인프런 커뮤니티 질문&답변

dawn님의 프로필 이미지

작성한 질문수

손에 익는 Next.js - 공식 문서 훑어보기

비동기 호출, fetch, 라우트 핸들러 관련 질문입니다.

해결된 질문

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를 사용해야 한다' 라고 이해를 했는데요.. 그럼 혼란 스러운게..

  1. 'fetch비동기 호출은 서버 컴포넌트에서 하라고 되어 있는데 revalidateTag같이 서버 컴포넌트에서 동작하는 함수를 호출하기 위해서는 어쩔 수 없이 fetch를 클라이언트 컴포넌트에서 사용해야한다' 라고 이해 하는게 맞을까요??


  2. 그리고 위의 코드에서 method : 'POST' 라고 세팅하여 주셨는데 보내는 방식은 POST로 정해져 있는 것인지, 다른 메서드 (get, update, delete)로 사용하면 안되는 것인지 궁금합니다!

  3. 아래는 핸드북(3. Next.js 손에 익히기 / 7.날씨데이터 조회하기 / 데이터 재검증하기 )에 설명해주신 내용인데요!

    revalidateTag는 서버 사이드에서 호출 가능합니다. 하지만 캐시를 풀어달라는 요청은 클라이언트(브라우저)에서 만들어집니다. 때문에 API 형태로 revalidateTag를 호출할 수 있도록 만들어야 합니다. Next.js에서의 API는 라우트 핸들러를 통해 만들 수 있습니다.

    "캐시를 풀어달라는 요청은 클라이언트(브라우저)에서 만들어집니다." 라는 말이 RevalidateButton 버튼을 클릭했을 때 handleClick 함수가 호출되는 때를 말씀하신 것인지 궁금합니다.

  4. 아래는 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님, 안녕하세요. 질문 남겨주셔서 감사합니다! 하나씩 답변드릴게요.

 

  1. 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 호출을 사용하는 경우는 많을 수 있습니다.

 

 

  1. 재검증 API 메서드에 대해

그리고 위의 코드에서 method : 'POST' 라고 세팅하여 주셨는데 보내는 방식은 POST로 정해져 있는 것인지, 다른 메서드 (get, update, delete)로 사용하면 안되는 것인지 궁금합니다!

정해져있는 건 아닙니다. 공식 문서에서는 GET을 쓰고 있습니다. 답변을 달며 생각해보니 저도 더 깊게 고민하지 않고 예제에 POST를 쓴 것 같네요. 질문 주신 덕에 생각해볼 수 있었습니다. 감사합니다.

결론: 어떤 방식이건 용도에 맞는 메서드를 선택하시면 됩니다. 보통은 재검증만을 수행하기 보다 다른 동작 이후에 재검증을 함께 하는 경우가 많을 것 같아요. 그에 맞게 적절한 메서드를 사용하시고 재검증도 함께 수행해도 좋을 것 같습니다.

 

 

  1. 캐시 요청, 핸드북의 설명에 대해

"캐시를 풀어달라는 요청은 클라이언트(브라우저)에서 만들어집니다." 라는 말이 RevalidateButton 버튼을 클릭했을 때 handleClick 함수가 호출되는 때를 말씀하신 것인지 궁금합니다.

네, 맞습니다! handleClick 함수로 API를 호출하고 그 호출의 반응해 revalidateTag가 호출되기 때문에 요청은 클라이언트에서 만들어진다고 표현했습니다.

 

 

  1. revalidateTag 함수의 에러 발생 케이스에 대해

revalidateTag 함수는 호출시 에러가 발생하는 경우는 없는건가요?? 제 생각에는 revalidateTag도 제대로 작동을 안할 수도 있으니깐 try catch 문으로 감싸서 호출하는게 맞지 않을까? 생각이 들었는데 그렇게 안해도 되는 것인지 궁금합니다!

네! 맞습니다. 정확하게 체크하기 위해선 말씀주신 것처럼 revalidateTag 함수를 try catch로 감싸 에러에 대한 적절한 대응을 해주는 게 맞습니다. revalidateTag 함수를 소개하는 것에 집중하다보니 놓친 부분인데 말씀해주셔서 다시 생각해보게 됐습니다. 감사합니다.

 

 

dawn님, 질문 주셔서 너무 감사합니다.
덕분에 제가 가장 많이 배운 것 같습니다. 좋은 질문해주셔서 감사합니다.

혹시 도움 드릴 수 있는 부분이 있다면 언제든 또 질문 남겨주세요!

dawn님의 프로필 이미지

작성한 질문수

질문하기