useAsyncData 캐싱 문제와 Key 동적 설정으로 해결하기

Nuxt 3: useAsyncData 캐싱 문제와 Key 동적 설정으로 해결하기

문제 상황: 동일 데이터 반복 출력

Nuxt 3 프로젝트에서 블로그 상세 페이지를 구현하던 중, 다음과 같은 문제가 발생했습니다:

  • 이슈:
    1. 블로그 1번 포스트를 클릭.
    2. 뒤로 가기(NuxtLink 사용).
    3. 블로그 2번 포스트를 클릭했으나 1번 포스트 내용이 그대로 출력.

이 문제는 URL이 변경됨에도 불구하고, 이전 포스트의 데이터가 계속 출력되는 캐싱 관련 문제로 확인되었습니다.


원인 분석: useAsyncData의 캐싱 메커니즘

Nuxt 3의 useAsyncData는 내부적으로 캐싱 메커니즘을 사용하여 불필요한 네트워크 요청을 줄이는 방식으로 동작합니다. 하지만 이 메커니즘이 문제를 유발할 수 있는 상황이 있습니다.

1. 기존 코드

const { data: post } = await useAsyncData(() => {
  return queryCollection("blog").path(route.path).first();
});

Key가 고정되어 있음

useAsyncData는 Key를 명시적으로 설정하지 않으면, 코드 블록 자체를 기준으로 Key를 생성합니다. 따라서 이 코드에서는 Key가 항상 동일하게 고정됩니다. Nuxt는 동일 Key를 가진 데이터 요청의 결과를 캐싱하여 재사용합니다.

문제 발생 흐름

  1. /blog/1로 이동하면 queryCollection("blog").path("/blog/1")의 결과가 Key에 저장됩니다.
  2. /blog/2로 이동해도 Key가 동일하므로 이전에 캐싱된 데이터를 반환합니다.

이로 인해 URL은 정상적으로 바뀌지만, 이전 블로그 포스트의 내용이 계속 출력되는 문제가 발생합니다.

2. 캐싱 메커니즘 요약

  • useAsyncData는 Key를 기준으로 데이터를 캐싱.
  • Key가 동일하면, 새로운 데이터를 요청하지 않고 캐시된 데이터를 반환.

해결 방법: Key를 동적으로 설정

문제를 해결하기 위해 Key를 URL 경로(route.path)에 따라 동적으로 설정했습니다.

1. 수정된 코드

const { data: post, error, refresh } = await useAsyncData(`blog-post-${route.path}`, () => {
  return queryCollection("blog").path(route.path).first();
});

2. 변경 사항

  • Key를 명시적으로 설정:
    • Key를 blog-post-${route.path}와 같이 경로마다 고유한 값으로 지정.
    • 경로가 변경될 때마다 Nuxt가 새로운 Key를 인식하고 데이터를 새로 요청.
  • 데이터 요청이 올바르게 매핑:
    • /blog/1 -> Key: blog-post-/blog/1
    • /blog/2 -> Key: blog-post-/blog/2

3. 결과

  • URL 변경 시 Key가 달라지므로, Nuxt는 캐싱된 데이터를 재활용하지 않고 새 데이터를 요청합니다.
  • 이전 블로그 내용이 출력되는 문제가 해결됩니다.

배포 환경에서의 동작

배포 환경에서는 Nuxt 3의 SSG(Static Site Generation) 또는 ISR(Incremental Static Regeneration) 방식이 추가적으로 적용됩니다. 따라서 JSON 캐싱과 HTML 프리렌더링이 문제 해결에 영향을 줄 수 있습니다.

1. 문제 발생 시 배포 파일 구조 (변경 전)

  • Key가 고정되어 있으므로 동일한 JSON 캐시 파일이 재활용.
  • 예:
    /_nuxt/data/blog.json  // 모든 경로에 대해 동일 파일 사용
    
  • 결과적으로 /blog/2 요청 시에도 /blog/1 데이터가 반환됩니다.

2. 문제 해결 후 배포 파일 구조

  • Key가 동적으로 설정되므로 경로마다 고유한 JSON 파일 생성.
  • 예:
    /_nuxt/data/blog-post-/blog/1.json
    /_nuxt/data/blog-post-/blog/2.json
    
  • 각 경로에 대해 고유한 JSON 파일이 매핑되어 올바른 데이터가 반환됩니다.

3. 배포 환경 확인 방법

  1. JSON 파일 확인:
    • 배포된 _nuxt/data/ 디렉토리에서 각 경로별 JSON 파일이 생성되었는지 확인.
    • 예:
      _nuxt/data/blog-post-/blog/1.json
      _nuxt/data/blog-post-/blog/2.json
      
  2. HTML 파일 확인:
    • /.output/public 디렉토리에서 각 경로별 프리렌더링된 HTML 파일이 생성되었는지 확인.
    • 예:
      .output/public/blog/1/index.html
      .output/public/blog/2/index.html
      
  3. Vercel 배포 환경 로그:
    • 배포된 프로젝트에서 요청 경로별로 올바른 JSON 파일 및 HTML이 반환되는지 확인.

결론

  1. 기존 코드에서 동일 데이터가 출력된 원인은 useAsyncData의 Key가 고정되어 있었기 때문입니다.
  2. Key를 URL 경로를 기준으로 동적으로 설정하여 Nuxt의 캐싱 메커니즘이 올바르게 동작하도록 수정했습니다.
  3. 배포 환경에서도 경로마다 고유한 JSON 파일과 HTML 파일이 생성되므로, 데이터 불일치 문제가 해결되었습니다.

이와 같은 Key 설정은 동적 데이터를 사용하는 모든 Nuxt 프로젝트에서 중요한 패턴이며, 특히 캐싱 문제가 발생할 수 있는 상황에서 반드시 고려해야 합니다.


참고