본문으로 건너뛰기
개발 머꼬
개발 노트Nuxt.js
hohyeon.dev17

같은 API를 두 컴포넌트에서 부르니 요청도 두 번 나간 이유

  • #Engineering Note
  • #Nuxt.js
  • #Performance

문제 발생

헤더와 사이드바가 같은 프로필 API를 각각 불렀습니다.

<!-- AppHeader.vue -->
<script setup>
const { data: me } = await useFetch("/api/me");
</script>

<!-- AppSidebar.vue -->
<script setup>
const { data: me } = await useFetch("/api/me");
</script>

URL이 같은데도 네트워크 탭에는 요청이 두 번 찍혔고, 한쪽에서 refresh()를 불러도 다른 쪽 값은 그대로였습니다.

원인 분석

키가 다르기 때문입니다. Nuxt 문서는 키 생성 방식을 이렇게 설명합니다 — useFetchURL, fetch 옵션, 그리고 호출 위치로 키를 만들고, useAsyncData는 첫 인자가 문자열이면 그것을 키로 쓰고 아니면 호출 위치로 만듭니다.

호출 위치가 키에 들어가므로 파일이 다르면 URL이 같아도 다른 키가 됩니다. 그래서 캐시가 공유되지 않고 각자 요청합니다.

문서의 해법도 한 줄입니다 — 여러 컴포넌트에서 같은 데이터를 공유하려면 같은 명시적 key를 주라는 것입니다. 그렇게 하면 useNuxtData로 그 키의 데이터를 다른 곳에서 읽거나 갱신할 수도 있습니다.

해결 방안

  1. 키를 명시합니다. 두 컴포넌트가 같은 캐시 항목을 봅니다.
const { data: me } = await useFetch("/api/me", { key: "me" });
  1. 더 나은 방법은 컴포저블 하나로 감싸는 것입니다. 키와 옵션이 한 곳에만 있으면 어긋날 일이 없습니다.
// composables/useMe.ts
export function useMe() {
  return useFetch("/api/me", { key: "me" });
}
  1. URL이 반응형이면 콜백으로 넘깁니다. 문서 설명대로 URL 문자열을 반환하는 computed getter 형태의 콜백을 쓰면 의존하는 값이 바뀔 때마다 다시 가져옵니다. 문자열 템플릿으로 한 번 평가된 값을 넘기면 그 뒤로 갱신되지 않습니다.
const { data } = await useFetch(() => `/api/posts/${id.value}`);
  1. $fetch를 setup에서 직접 부르지 않습니다. 문서가 지적하는 그대로 — setup 함수 안에서 $fetch로 데이터를 가져오면 서버에서 HTML을 만들 때 한 번, 클라이언트에서 다시 한 번, 두 번 요청될 수 있습니다. 컴포저블은 서버에서 가져온 데이터를 payload로 클라이언트에 넘겨 이 중복을 막습니다.

  2. 다른 곳에서 이미 받은 값을 다시 읽을 때는 useNuxtData입니다. 새 요청 없이 캐시된 값에 접근합니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.