Skip to content
문서
미들웨어

미들웨어

💡

이 기능을 사용하시려면 최신 버전(≥ 1.0.0)으로 업그레이드하세요.

미들웨어 기능은 SWR 1.0에 새롭게 추가되었으며 SWR hook의 전후에 로직을 실행할 수 있도록 해줍니다.

사용법

미들웨어는 SWR hook을 받고 hook의 실행 전후에 로직을 실행할 수 있습니다. 여러 미들웨어가 존재한다면, 각 미들웨어는 다음 미들웨어를 감쌉니다. 리스트의 마지막 미들웨어가 원본 SWR hook useSWR을 받습니다.

API

노트: 함수 이름을 대문자로 시작하면 안됩니다(예, MyMiddleware 대신에 myMiddleware). 그렇지 않으면 React lint 규칙이 Rules of Hook 에러를 던집니다

TypeScript (opens in a new tab)

function myMiddleware (useSWRNext) {
  return (key, fetcher, config) => {
    // hook을 실행하기 전...
    
    // 다음 미들웨어를 처리하거나, 마지막인 경우 `useSWR` hook을 처리합니다.
    const swr = useSWRNext(key, fetcher, config)
 
    // hook을 실행한 후...
    return swr
  }
}

SWRConfig 또는 useSWR에 옵션으로 미들웨어 배열을 전달할 수 있습니다.

<SWRConfig value={{ use: [myMiddleware] }}>
 
// 또는...
 
useSWR(key, fetcher, { use: [myMiddleware] })

확장하기

일반 옵션과 마찬가지로 미들웨어를 확장할 수 있습니다. 예를 들면:

function Bar () {
  useSWR(key, fetcher, { use: [c] })
  // ...
}
 
function Foo() {
  return (
    <SWRConfig value={{ use: [a] }}>
      <SWRConfig value={{ use: [b] }}>
        <Bar/>
      </SWRConfig>
    </SWRConfig>
  )
}

다음과 동일합니다.

useSWR(key, fetcher, { use: [a, b, c] })

다중 미들웨어

각 미들웨어는 다음 미들웨어를 감싸며, 마지막 미들웨어는 SWR hook을 감쌉니다. 예를 들면:

useSWR(key, fetcher, { use: [a, b, c] })

미들웨어의 실행 순서는 아래에서 보시다시피 a → b → c입니다.

enter a
  enter b
    enter c
      useSWR()
    exit  c
  exit  b
exit  a

예시

Request Logger

예시로 간단한 request logger 미들웨어를 만들어봅시다. 이 SWR hook으로부터 전송된 모든 가져오기 요청을 출력합니다. 이 미들웨어를 SWRConfig에 추가하여 모든 SWR hook에 대해 사용할 수도 있습니다.

function logger(useSWRNext) {
  return (key, fetcher, config) => {
    // 원본 fetcher에 logger를 추가합니다.
    const extendedFetcher = (...args) => {
      console.log('SWR Request:', key)
      return fetcher(...args)
    }
 
    // 새로운 fetcher로 hook을 실행합니다.
    return useSWRNext(key, extendedFetcher, config)
  }
}
 
// ... 여러분의 컴포넌트 내부
useSWR(key, fetcher, { use: [logger] })

요청이 발생할 때마다, SWR 키가 콘솔에 출력됩니다.

SWR Request: /api/user1
SWR Request: /api/user2

이전 결과 유지하기

때때로 useSWR이 반환한 데이터가 "지연"되길 원합니다. 키가 변경되었더라도, 새로운 데이터가 로드되기 전까지는 여전히 이전 결과를 반환하길 원합니다.

이는 useRef를 함께 사용하여 지연 미들웨어로 구축할 수 있습니다. 이 예시에서는 또한 useSWR hook이 반환한 객체를 확장합니다.

import { useRef, useEffect, useCallback } from 'react'
 
// 키가 변경되더라도 데이터를 유지하기 위한 SWR 미들웨어입니다.
function laggy(useSWRNext) {
  return (key, fetcher, config) => {
    // 이전에 반환된 데이터를 저장하기 위해 ref를 사용합니다.
    const laggyDataRef = useRef()
 
    // 실제 SWR hook.
    const swr = useSWRNext(key, fetcher, config)
 
    useEffect(() => {
      // 데이터가 undefined가 아니면 ref를 업데이트합니다.
      if (swr.data !== undefined) {
        laggyDataRef.current = swr.data
      }
    }, [swr.data])
 
    // 지연 데이터가 존재할 경우 이를 제거하기 위한 메서드를 노출합니다.
    const resetLaggy = useCallback(() => {
      laggyDataRef.current = undefined
    }, [])
 
    // 현재 데이터가 undefined인 경우에 이전 데이터로 폴백
    const dataOrLaggyData = swr.data === undefined ? laggyDataRef.current : swr.data
 
    // 이전 데이터를 보여주고 있나요?
    const isLagging = swr.data === undefined && laggyDataRef.current !== undefined
 
    // `isLagging` 필드 또한 SWR에 추가합니다.
    return Object.assign({}, swr, {
      data: dataOrLaggyData,
      isLagging,
      resetLaggy,
    })
  }
}

SWR hook이 지연될 필요가 있을 때, 이 미들웨어를 사용하면 됩니다.

const { data, isLagging, resetLaggy } = useSWR(key, fetcher, { use: [laggy] })

객체 키 직렬화하기

💡

SWR 1.1.0부터, 유사 객체 키들은 내부에서 자동으로 직렬화됩니다.

⚠️

이전 버전(< 1.1.0)에서는, SWR은 렌더링할 때마다 인자들을 얕게 비교하며, 변경이 있으면 갱신을 트리거합니다. 직렬화 가능한 객체를 키로 전달하는 경우, 객체 키를 직렬화하여 안정성을 보장할 수 있으며, 간단한 미들웨어가 이를 도울 수 있습니다.

function serialize(useSWRNext) {
  return (key, fetcher, config) => {
    // 키 직렬화하기.
    const serializedKey = Array.isArray(key) ? JSON.stringify(key) : key
 
    // 직렬화된 키를 전달하고 fetcher에서 직렬화 해제하기.
    return useSWRNext(serializedKey, (k) => fetcher(...JSON.parse(k)), config)
  }
}
 
// ...
useSWR(['/api/user', { id: '73' }], fetcher, { use: [serialize] })
 
// ... 또는 전역으로 활성화
<SWRConfig value={{ use: [serialize] }}>

객체가 렌더링 사이에 변경될 수도 있다는 점에 대해 걱정할 필요가 없습니다. 항상 동일한 문자열로 직렬화되며 fetcher는 여전히 해당 객체 인자를 받습니다.

💡

더 나아가 JSON.stringify 대신에 fast-json-stable-stringify (opens in a new tab)와 같은 라이브러리를 사용하면 더 빠르고 더 안정적입니다.