이슈 발췌일: 2022.09.05 (월)
현재 회사에서는 UI 컴포넌트 라이브러리로 Devextreme을 사용한다. 오늘은 Devextreme의 기능 중 CustomStore를 사용하면서 있었던 이슈에 정리해보려고 한다.
Devextreme의 DataGrid나 Lookup 컴포넌트를 사용할 때, 대부분 CustomStore를 만들어주고 이를 컴포넌트에 전달하여 해당 CustomStore로 데이터를 가져오도록 되어있다. Pagination이나 Filter, Sort 등이 필요한 경우에 CustomStore를 사용하면 옵션 값이 바뀌었을 때 알아서 데이터를 다시 가져올 수 있기 때문이다. 사용자의 인터랙션으로 옵션의 값이 바뀌면, CustomStore는 load 함수를 다시 실행하여 데이터를 다시 가져온다. 이 load 함수만 따로 정의 해주면 된다.
Devextreme에서 정의하는 검색 옵션의 형식은 이미 정해져있기 때문에 서버가 해당 포맷을 알맞게 해석하고 데이터를 가져오도록 구현하기만 하면 된다. 아래는 CustomStore + DataGrid 컴포넌트를 작성한 예시이다.
function Example() {
const customStore = New CustomStore({
load: async (loadOptions) => {
const queryString = queryStringify(loadOptions);
return await getList(queryString);
}
});
return <DataGrid columns={columns} store={customStore} />
}
그러나, 위와 같이 CustomStore를 사용한 컴포넌트들에는 문제점이 한가지 있었다. 그건 필요없는 시점에도 데이터를 다시 가져오는 문제였다. 초기 렌더링 시에 데이터 요청을 3 ~ 4번씩 보내는 곳도 있었고, 팝업을 열거나 닫는 등의 인터랙션이 발생한 후에도 데이터를 다시 요청하고 있었다. 문제 해결을 위해 CustomStore가 언제 load 함수를 다시 실행하는 것일까에 대해 생각해보았다.
일단, 초기 렌더링 시 load 함수를 실행하고 있다. 처음 컴포넌트를 렌더링 하면서 데이터도 표시되어야 하기 때문에 어찌보면 당연한 이야기다. 그리고 loadOptions(컴포넌트의 검색 옵션) 값이 바뀔 때 load 함수가 다시 실행된다. 이것도 위에서 이야기한 대로 CustomStore에서 제공해주는 기능이다.
위 두 상황이 아닌 시점에서도 load 함수가 실행되었다. (그리고 초기 렌더링 시에도 3 ~ 4번 중복 호출하고 있다...)
이래저래 분석해본 결과, 스토어가 선언된 컴포넌트의 상태 값이 바뀌었을 때 혹은 상위 컴포넌트의 상태 값이 바뀌었을 때 load 함수가 다시 실행되고 있다는 것을 알아냈다. 이는 React 컴포넌트가 리렌더링 될 때, load 함수가 실행된다는 이야기이다.
그 때, 내 머릿속을 샥 스쳐지나간 생각이 있었다. customStore는 어쨌든 컴포넌트 내부에 선언된 일반 변수니까 리렌더링이 되면 값이 초기화 되겠구나...였다. 그동안 대부분의 값을 state로 선언했더니 잊고 있었다. customStore는 일반 변수로 선언했다는 것을...
혹시나 해서 CustomStore를 useMemo로 감싸서 리턴하도록 해봤더니 세상에...위 문제가 해결되었다. 초기 렌더링 시 중복 호출하는 문제도 사라졌다. 대충 왜 해당 문제가 발생한 것인지 감이 와서 아래와 같이 이슈 내용을 정리하였다.
[이슈 내용]
- CustomStore를 사용하는 컴포넌트(DataGrid or Lookup)는 상위 컴포넌트가 리렌더링 될 때 마다 데이터가 다시 로드되는 문제가 있습니다.
- 리렌더링 시, CustomStore를 생성하는 코드가 다시 평가되어 생성되기 때문에 load 함수가 계속 실행된 것으로 생각됩니다. (CustomStore는 생성되는 시점에 load 함수를 실행하는 것 같습니다)
[해결방안]
- 데이터 요청은 loadOptions 값이 바뀌거나 load 함수 내부에서 사용하는 상태값이 바뀔 때만 수행되어야 합니다. 따라서, 리렌더링 될 때마다 CustomStore가 다시 생성되지 않도록 useMemo를 사용하여 CustomStore 값을 캐싱해주면 해결될 것으로 보입니다.
현재 CustomStore를 사용하는 곳이 한두군데가 아니었기에 이슈 내용을 정리해두고 나머지 부분들도 수정될 수 있도록 Task를 만들어서 해당 내용을 Description으로 넣어주었다.
위 이슈를 겪으면서 React의 리렌더링 Flow에 대해 자세히 조사해보고 싶어졌다. 예전에 setState 타이밍 때문에 한동안 고생했던 적도 있고 해서 React에서 어떻게 변경 값을 인지해서 리렌더링을 하는지 정리해보면 도움이 많이 될 것 같다는 생각이 들었다. 오늘은 일단 여기까지 정리하도록 하겠다!
'이슈 로그' 카테고리의 다른 글
package 버전 문제 (lock 파일의 중요성) (0) | 2022.12.28 |
---|---|
[React] Input Focusing이 없어지는 현상 (1) | 2022.11.08 |
웹 구글 지도 마커 렌더링 최적화 (0) | 2022.11.02 |
z-index가 동작하지 않는 이유, 같은 위계에서 비교하기 (0) | 2022.06.11 |