GraphQL에서 캐시 규범화를 반대하는 사례

10658 단어
본고에서 우리는 규범화된 캐시로 이루어진 부GraphQL 클라이언트와 HTTP 캐시에 의존하는 WunderGraph 클라이언트를 비교할 것이다.
이미 발견한 바와 같이, WunderGraph는 기본적으로 지속적인 검색을 사용합니다.
WunderGraph 코드 생성기 WunderGen ((https://github.com/wundergraph/wundergen) 을 사용하면 이전에 등록된 동작을 어떻게 호출하는지 정확하게 알 수 있는 클라이언트를 생성할 수 있습니다.@cache 명령을 사용하면 서버와 클라이언트가 응답을 캐시해야 한다고 설정할 수 있습니다.
캐시 제어 헤드는 Etag을 포함하여 적절하게 설정됩니다.이 메커니즘은 모든 주요 브라우저와 CDN과 완전히 호환되며 CDN은 HTTP Caching RFC에 따라 캐시를 실현한다.
이 점을 더욱 잘 설명하기 위해서, 나는 두 개의 예시 조회를 소개하고 싶다.
첫 번째는 친구 리스트.
두 번째는 이 친구들에 대한 세부 사항이다.
한 번 생각해 봅시다. 우리는 친구 목록을 보여주고 싶습니다.
query Friends {
    friends {
        id
        name
        age
        avatarURL
    }
}
각 친구에 대해 목록에서 친구를 클릭하고 세부내용 페이지를 열려면 합니다.
query FriendByID {
    friend(id: 123) {
        id
        name
        age
        avatarURL
    }
}
자세한 정보 페이지의 모든 데이터를 가지고 있음을 알게 될 것입니다.
따라서 이상적인 상황에서 클라이언트는 다른 요청을 할 필요가 없다.
캐시가 규범화되었기 때문에, 이것은 가능하다.
스마트 규범화 캐시는 친구의 실체를 식별하고'FriendByID'조회를 식별할 수 있으며 우리가 실행한'Friends'조회의 데이터를 사용하여 실현할 수 있다.
이 개념의 장점은 무엇입니까?
  • 친구의 세부 정보 페이지로 이동하는 것은 네트워크 요청이 필요하지 않으므로 즉각적입니다
  • .
  • 클라이언트는 대역폭을 절약하고 사용자 체험을 원활하게 할 수 있다
  • 우리가 뒤로 이동하면 규범화된 캐시
  • 에서 친구 목록을 즉시 꺼낼 수 있습니다.
    이런 상황이 어떻게 까다로워질 수 있습니까?
    세 번째 조작을 추가합니다.사용자 세부내용 페이지에서 동료의 친구 관계를 해제하고 싶습니다.
    mutation Unfriend {
        unfriend(id: 123) {
            id
        }
    }
    
    unfriend 돌변은 어떻게 상황을 복잡하게 합니까?
    규범화 캐시에서 '친구' 와 '친구' 실체를 실효시키거나 업데이트해야 합니다.
    친구 목록에서 id가 123인 사용자를 삭제해야 합니다.Friends에 대해서는 id가 123인 친구를 다시 돌아오지 않도록 해야 합니다.
    규범화 캐시는 어떻게 unfriend 돌연변이와 friendfriends 조회 사이에 경계를 분명히 긋습니까?
    전방 개발자로서 캐시를 프로그래밍해야만 이 점을 할 수 있습니다.
    돌변 후, 이 변경 사항을 캐시에 알려야 합니다.
    다음은 캐시를 규범화하는 단점에 대해 살펴보겠습니다.
  • 규범화된 캐시를 갖춘 포괄적인 GraphQL 클라이언트의 구축과 유지보수는 매우 복잡하다
  • 브라우저의javascript 가상기에서 실행되기 때문에 브라우저 캐시
  • 보다 효율이 훨씬 낮다
  • 캐시 상태를 올바르게 유지하는 논리가 복잡해질 수 있음
  • 프런트엔드 개발자는 불필요한 행동을 피하기 위해 도메인을 이해하고 캐시를 정확하게 프로그래밍해야 합니다
  • 프런트엔드 개발자는 캐시 디스테이징을 위한 사용자 정의 규칙을 구현해야 함
  • 나는 명세서 외에 한 가지 일을 명확하게 언급하고 싶다.

    이런 상황에서 업무 대상은 단일한 진실한 출처가 없다.
    전방 개발자는 의외로 사용자 인터페이스에 친구 목록에 있는 친구를 표시할 수 있습니다. 설령 당신이 이전에 이 친구와 친구 관계가 없었더라도.
    이런 실수는 발견하기 어렵다.이러한 상황에서 우리는 전방 개발자에게 캐시를 정확하게 할 수 있도록 큰 책임을 부여한다고 생각한다.
    만약 데이터가 유행이 지났다면, 전방 개발자들은 정말 걱정해야 합니까?프런트엔드 개발자는 UI를 주목하고 데이터 계층을 신뢰해야 하지 않습니까?성능이 좋은 부유한 응용 프로그램을 구축하는 데 정말 이렇게 복잡해야 합니까?
    나는 어떤 응용 프로그램에서 이러한 복잡성을 가지는 것이 절대적으로 가치가 있다고 믿는다.
    다른 한편, 뉴스 사이트와 같은 많은 용례를 보았는데 그 중에서 HTTP 캐시에 의존하는 RFC는 훨씬 간단하고 효율도 높다.

    WunderGraph 캐시 입력:
    WunderGraph를 사용하면 등록된 모든 조회가 하나의 단점이 되며 캐시 규칙을 따로 적용할 수 있습니다.
    위에서 이 예를 다시 한 번 살펴보자.
    query FriendByID @cache(maxAge: 5){
        friend(id: 123) {
            id
            name
            age
            avatarURL
        }
    }
    
    이 질의는 WunderGraph 노드에서 다음 끝점이 됩니다.
    /application-id/FriendByID?variables={"id":123}
    
    이 장면에서 우리는 @cache 명령을 사용하여 친구 대상을 5초 동안 캐시하기로 결정했다.
    5초 후 클라이언트는 다시 사용자를 요청하고 요청과 함께 If-None-Match 헤더를 보냅니다.
    이전 응답이 유효하면 서버는 304 (Not Modified) http 상태 코드를 사용하여 응답합니다.
    같은 논리도 Friends 조회에 응용할 수 있다.
    당신이 해야 할 일은 조작 명령을 사용하여 필요한 행동을 정의하는 것입니다.
    이런 방법의 장점은 무엇입니까?
  • 진실은 단지 하나의 출처일 뿐이다. 조작 정의
  • 캐시는 사용하기 쉽고 이해하기 쉬운 브라우저가 자동으로 처리
  • 캐시 요청을 복잡한 도구로 이해할 필요가 없고 브라우저에 우수한 디버거가 있다
  • 캐시 상태를 동기화하기 위해 자바스크립트 코드를 작성할 필요가 없음
  • 서비스 직원이 있으면 표준 캐시 기술
  • 을 사용하여 오프라인 응용 프로그램을 쉽게 구축할 수 있습니다.
  • 브라우저가 실행하는javascript 코드가 더 적음
  • 프런트엔드 개발자가 사용자 인터페이스에 관심을 가지기 시작하면서 데이터 취득과 캐시 논리에 대해 더 이상 걱정하지 않는다
  • GraphQL 쿼리에 사용되는 HTTP 캐시의 단점은 무엇입니까?
  • 클라이언트는 표준화된 캐시
  • 에 비해 더 많은 요청을 해야 합니다.
  • 더 많은 요청으로 더 많은 대역폭 사용
  • 캐시를 즉시 무효화하는 간단한 방법이 없음

  • 표준화된 캐시가 우리가 더 많은 요청을 실행하는 것을 막을 수 있습니까?
    이 장면을 좀 더 현실적으로 만들어 봅시다.친구 상세 정보 페이지에서도 친구의 이력서를 보고 싶습니다.
      query FriendByID {
        friend(id: 123) {
            id
            name
            age
            avatarURL
            bio
        }
    }
    
    비록 대부분의 데이터를 가지고 있지만, 표준화된 캐시를 사용하여 이 필드를 추가하더라도, 우리는 모든 단독 친구들을 다시 새겨야 한다.
    하루가 끝날 때, 표준화된 캐시가 응용 프로그램에 많은 복잡성을 가져다 줄 수 있지만, 좋은 점은 당신이 예상한 것만큼 크지 않다.
    마지막 예시에서, 모든 사용자의 상세한 정보 페이지에 비교적 적은 필드를 전송할 수 있도록 저장할 수 있지만, 그 대가로 복잡한 GraphQL 클라이언트를 사용하면, 이 클라이언트는 실체에 어떤 필드가 부족한지 알 수 있다.

    캐시 실패
    앞에서 말한 바와 같이 규범화 캐시는 효력을 잃기 쉽다.
    이것은 캐시 코드를 실현하고 유지하며 언제 어떤 대상을 무효화시킬 것인지를 정의하는 논리를 대가로 한다.
    HTTP 캐시를 사용하는 것은 결코 쉽지 않다.
    타임 스탬프와 같은 동적 매개 변수를 질의에 추가할 수 있습니다.
    이것은 캐시가 효력을 상실하는 것을 허용하지만, 가능한 캐시 명중을 줄일 수도 있다.

    여러 클라이언트가 있을 수 있음
    사용자가 여러 탭, 네이티브 응용 프로그램 등에서 응용 프로그램을 열 수 있습니까?
    만약 그렇다면, 한 옵션에서 한 사용자의 친구 관계를 해제하고, 다른 옵션을 열었다면, 무슨 일이 일어날까요?
    이 때 표준화 캐시에서 데이터가 유행이 지났는지 확인할 수 없습니다. 옵션을 바꾸면 네트워크 호출이 필요합니다.

    캐시를 해야 합니까?
    우리는 정확한 차원에서 문제를 해결합니까, 아니면 새로운, 심지어 더 복잡한 문제를 창조합니까?
    만약 이 예의 데이터가 언제든지 클릭(친구 추가/친구 취소)에서 변경될 수 있다면 클라이언트나 전송 단계에서 이 데이터를 캐시해야 합니까?
    데이터베이스에 직접 접근하는 것이 성능 병목이라면, 왜 백엔드에서 응용 프로그램 캐시를 사용하지 않습니까? 예를 들어 Redis나 Memcached?
    이런 상황에서 전송 레벨 캐시든 규범화된 클라이언트 캐시든 모두 적합한 해결 방안이 아니다.

    캐시 시간
    캐시는 자주 변경되지 않는 공공 사용 가능한 데이터에 의미가 있습니다.
    예를 들어 뉴스 사이트에서 매 문장의 내용을 몇 초(예를 들어 5초) 동안 캐시하는 것은 전혀 문제가 없다.
    이것은 5초당 자원에 대한 요청량을 수천 개에서 하나로 줄일 것이다.
    만약 데이터가 고주파로 바뀔 수 있다면, 특히 사용자와 응용 프로그램이 상호작용한 후에 캐시는 응용 프로그램 층에서 발생해야 한다.

    요약
    클라이언트에서 규범화된 캐시를 사용해야 한다고 생각할 때, 먼저 응용 프로그램 수준의 캐시를 고려해야 합니다.
    규범화 캐시가 앞부분에 두 번째로 지켜야 할 진실의 출처를 도입했다.
    낙관론자들은 응용 프로그램의 마지막 성능을 이용하여 복잡성을 추가로 대가로 95%에서 98%의 사용자 체험을 얻을 수 있다.
    대부분의 경우, 너는 이런 복잡성을 필요로 하지 않고, 그것을 피해야 한다.
    간단하게 업무 문제를 해결하고 기술 채무를 끌어들이지 마라.
    WunderGraph는 전송 기반 캐시를 사용하는 간단하고 강력한 방법을 제공합니다.
    99퍼센트의 다른 용례에 대해 성능에 문제가 있으면 응용 프로그램 수준의 캐시를 추가하는 것을 고려해야 합니다.

    좋은 웹페이지 즐겨찾기