부분캐싱(partial-caching)

Steve·2022년 10월 12일
0

내일 질문 올려봐야지
전과 후의 퍼포먼스 차이를 어떻게 확인할 수 있는가?
10.5(수)
Partial Caching with PageBuilder Engine
How does PageBuilder Engine content caching work

위 2개에 대하여 읽어보고 정리

어떻게 기존에 작동을 하고 있었는지,
앞으로 어떻게 바뀔건지,
바뀐 뒤의 원하는 결과치는 무엇인지,

사실 모양 흉내내면서 코드 수정은 금방 하지 않을까 싶다.
문제는 내가 뭔 코드를 짜고 있는거고 왜하는거고 한 줄 한 줄이 어떤 영향을 미치는지 알아야 하는거지.
한마디로 내가 짜고 있는 코드에 책임을 지고 싶다.

axios.create을 이용해서 Instance 만드는 장점
1. 통신을 하는 모든 파일에서 axios를 import 안해도됨.
2. baseURL이나 header같은 설정을 하나의 파일에서 할 수 있다.
3. 코드 가독성.

Resolve Content Source
HTTP calls를 안한다. 그래서 partial caching은 fetch content source에서만 한다.
캐시 키는 resolve function으로 부터 반환되는 스트링으로 만들어짐
deployment "내" 또는 넘나들면서 여러개의 컨텐츠 소스를 서빙하면서 똑같은 캐시키를 갖을 수 있음.

Fetch Content Source
캐시 키는 content source name과 그리고 함께 불려지는 인자로 만들어짐.
여러개의 컨텐츠 소스에서 같은 캐시키를 가질 수 없다.
deployment를 넘나들면서 불려지는 파라미터와 source name이 똑같이 남아있다면
그 캐시는 계속 사용될 수 있다.

더 복잡한 컨텐츠 fetching을 위해 fetch가 개발자들에게 더 유연하게 사용될 수 있다.
JSON형식이 아니면 엔진에 의해 캐시가 안될것임을 명심하라.

data size가 1mb 이상이면 캐싱은 실패할것이다.
만약 반환되는 데이터가 6mb 이상이면 컨텐츠 소스의 실패를 야기한다.
만약 컨텐츠 소스가 global content로 사용된다면 페이지 에러가 난다.
querying large number of articles in a feed를 할 때 자주 보는 현상이다.

resolve content source에 대해서, 200번대의 응답은 모드 성공이다.
fetch content source에 대해서, resolves되는 어떠한 promise에 대해든지간에 캐싱된다. 만약 컨텐츠 소스가 실패하면 (resolve에 대해 200번대가 아니고, fetch에 대해 rejected promise), Fusion이 에러가 있는지 체크할것이다.
만약 에러가 있다면 상태코드(300~307, 404) 컨텐츠 소스에 대한 캐시는 없어질 것이다.
(그 요청에 대해 생성됐던 캐시키를 이용한다.)

partial caching은 fetch content source 에 대해서 지원된다.

resolve content source는 어떠한 HTTP calls를 만들면 안되기때문에,
fetcch content source에 대해서만 이용가능하다.

fetch function은 query parameter와 객체로 불려진다(cachedCall을 이용해서)

양식은 다음과 같다.

function cachedCall(
  name: string,
  fn: () => Promise<JSON>,
  options?: { 
    query?: JSON|String, 
    ttl?: number, 
    independent?: boolean 
  }
) => Promise<JSON>

CachedCall 함수는 3개 메인파트로 나뉜다. 그리고 promise를 반환한다.(JSON object로)
1. name
content source name으로 logs에 나타날 부분.
특정 케이스에선, 캐시 키의 일부로 사용된다.

  1. fn
    캐시가 없거나 캐시가 만료되면 부르는 함수다.
    반드시 promise를 반환해야하고, JSON 객체형식이여야 한다.

  2. options -> 어떻게 캐싱이 작동하는지에 따라 3개의 양상으로 나뉜다.

    1) query :
    문자열이나 JSON이 될 수 있다. 항상 파라미터로서 위에 적어둔 fn으로 전달된다. 그리고 default 값으로 {} 가짐.

    만약 문자열이라면, 캐시키로 사용됨.
    만약 JSON이라면, name과 query를 둘다 사용해서 캐시키를 만듬.

    query가 객체이면서 arc-site를 포함하고 있지 않다면,
    parent content source's arc-site 파라미터가 첨가 될 것이다.

    2) ttl :
    얼마나 살아 있을 것이냐에대한 시간.
    부모 content sourece의 ttl에 기본값이 맞춰진다.
    미니멈 120초까지 가능.(기본값은 180초)
    자식 캐시는 역동적으로 계산되어질 수 있다.
    고로, 여러개의 컨텐츠 소스가 같은 캐시를 공유하지만 다른 ttl을 가지고 있다면, 각각 만료되는 시간이 달라질 것이다.

    3) independent :
    true/false 값이다.
    부모 content source가 cleared 됐을때 같이 clear 시킬것이냐에 대한 물음이다.
    true가 아니라면, (false라면) 부모가 죽을 떄 같이 죽는다.

import axios from 'axios';
import { CONTENT_BASE, ARC_ACCESS_TOKEN } from 'fusion:environment';

const fetch = ({ url, 'arc-site': arcSite }, { cachedCall }) => cachedCall(`article-by-url-${url}`, () => axios({
  method: 'GET',
  url: `${CONTENT_BASE}/content/v4/?website=${arcSite}&website_url=${url}`,
  headers: {
    'content-type': 'application/json',
    Authorization: `Bearer ${ARC_ACCESS_TOKEN}`
  }
}).then(({ data }) => data));

export default {
  fetch,
  params: {
    url: 'text'
  }
};

위의 코드는 캐싱된 데이터를 2개 만드는 행위인, 간단한 resolve content source에서 복잡한 fetch content source로 만들고 있다. 너무 불편해 보인다.

Q. (one for the cachedCall and one for the entire content source) << 이게 어딜말하는건지

url에 전체 url이 들어가있음.
향상시켜보자. 우리의 캐시된 content source가 다른 사람들에 의해 사용되면 자원 활용에 더 좋을것이다.
다른 사람들은 지금부터, "똑같은" 이름을 사용해야한다. 이건 좀 이상하게 들리긴 한다.
다른 resolve content sourece들과 캐시를 공유하기위해 조금만 업데이트해보자 .

import axios from 'axios';
import { CONTENT_BASE, ARC_ACCESS_TOKEN } from 'fusion:environment';

const fetch = ({ url, 'arc-site': arcSite }, { cachedCall }) => cachedCall(
'article-by-url', /////// 1 

(url) => axios({ /////// 2
  method: 'GET',
  url,
  headers: {
    'content-type': 'application/json',
    Authorization: `Bearer ${ARC_ACCESS_TOKEN}`
  }
}).then(({ data }) => data),

// query가 추가됨. string 또는 JSON 형식으로 들어옴.
{ query: `${CONTENT_BASE}/content/v4/?website=${arcSite}&website_url=${url}` } /////// 3
);

export default {
fetch,
params: {
  url: 'text'
}
};

똑같은 URL을 가지려고 하는 content source가 있으면,
이제 새로운것을 만드는게 아니라 캐시를 공유할 것이다!

cachecCall의 indepente: true를 함으로써, 보고 있는 aritcle의 첫번째 section으로 부터 분리가 됐다. 부모가 cleared되더라도 자식 data는 그대로 남아있게 된다.
추가적으로,자주바뀌는게 아니란걸 알고 있으면 ttl을 써서 더 길게 남아있게 할 수도 있다.

FAQ.
1. http request에 항상 cachedCall을 이용해야하나?

아니다. 캐시를 공유할때, 또는 다른 ttl을 요구한다면 사용하면 된다.
만약 너의 기사에 대해 fetch call을 하고 Content API를 통해 다른 기사를 로드하지 않는다면, 캐시 할필요 없다. 기억해라. cachedCall은 각각 시간 비용이 든다.

내가 하고 싶은 질문들

independent is a boolean that controls if the cached content should be cleared when the parent content source's cache is cleared. Unless this is set to true, the new cached content will be cleared when the parent content source's cache is cleared.
Q. 어느 부분이 부모 켄텐츠 소스인지, 코드에서 어떻게 확인할 수 있는지 예시를 보고싶다.

All we've done here is covert a simple resolve content source into a more complicated fetch content source that generates twice as much cached data(one for the cachedCall and one for the entire content source)
Q. fetch content source가 캐싱된 데이터를 2배 더 만든다는데 어떻게 2배인지 모르겠다.

profile
Front-Dev

0개의 댓글