API 호출 최소화를 통한 성능 개선!
기능 구현을 위해 , 구현에만 초점을 맞춰서 만들다가 성능 측면에서 더 좋은 방법을 조언받아서 개선해보았습니다.
수정 전
수정 후 로직
개선 내용
-> 수정전에는 댓글 생성시마다 SELECT API를 호출하여 새로운 댓글을 보여주었다.
수정 후에는 useState에 댓글 정보를 담아서 댓글 정보를 담아서 임시로 요여주는 형태로 , API 호출을 한번 줄일 수 있게 됐다.
수정 전 코드
// 새로운 댓글 등록하기 함수 ( 댓글 추출 -> api 실행 -> DB에 댓글 저장
const handleSubmit = (event: React.MouseEvent<HTMLButtonElement>) => {
const data = insertText.current?.value;
event.preventDefault();
const axiosData = {
CO_CONTEXT: data,
S_IDX,
};
try {
const result = axiosInstance.post("/clubDetail/insertContext", axiosData);
} catch (error) {
console.log(error);
}
if (insertText.current) {
insertText.current.value = "";
}
};
// 새로운 댓글이 등록될 때마다 , getContext 함수가 실행되며 리렌더링된다.
useEffect(() => {
getContext(); // 댓글 불러오기 함수 (SELECT 댓글)
}, [handleSubmit]);
// JSX 코드
return (
// 댓글 입력 박스
<div className="">
<div className=" my-2 ">
<form>
<div className="flex flex-start">
<input
type="text"
placeholder=" 댓글을 입력해주세요"
className="w-4/5 ml-1 border-y-neutral-800"
ref={insertText}
/>
<button
type="button"
className="mx-1 border-2 px-2 rounded-xl"
onClick={handleSubmit}
>
등록
</button>
</div>
</form>
</div>
<div className="overflow-y-auto h-[10rem]">
// 댓글 불러오기 박스
{context?.map((item, index) => (
<div key={index} className="flex flex-start border-2 py-2 pl-3 my-1 text-[14px] border-y-gray-200 border-x-slate-100">
<p>{item.U_NAME} : </p>
<p> {item.CO_CONTEXT}</p>
</div>
))}
</div>
</div>
);
-> INSERT API 실행 후 SELECT API 실행으로 두 번의 API 호출이 이루어진다.
수정 후 코드
// 댓글 추출용 useRef
const insertText = useRef<HTMLInputElement>(null);
// 댓글 입력 함수
const handleSubmit = async (event: React.MouseEvent<HTMLButtonElement>) => {
// 댓글 추출
const data = insertText.current?.value;
event.preventDefault();
//INSERT API에 보낼 데이터
const axiosData = {
CO_CONTEXT: data,
S_IDX,
};
try {
//INSERT API 실행
const result = await axiosInstance.post(
"/clubDetail/insertContext",
axiosData
);
//유저 ID와 받아온 INSERT_ID저장
const newAddComment = { S_IDX: S_IDX.S_IDX, data, id: result.data.id };
// SELECT API 재호출이 아닌 , 임시로 보여줄 댓글 박스 데이터 저장
setTemporaryContext((prevComment) => [...prevComment, newAddComment]);
} catch (error) {
console.log(error);
}
if (insertText.current) {
insertText.current.value = "";
}
};
// 댓글 입력 완료 될때마다, 임시 댓글창 보여주기 위해 리렌더링 발생
useEffect(() => {}, [temporaryContext]);
//JSX 코트
<div className="my-2">
<form>
<div className="flex border-2 border-x-white border-t-white flex-start">
<input
type="text"
placeholder="댓글을 입력해주세요"
className="w-full outline-none ml-1 border-y-neutral-800 pl-2 py-1"
ref={insertText}
/>
<button
type="button"
className="mx-1 px-2 rounded-xl"
onClick={handleSubmit}
>
<MdSend />
</button>
</div>
</form>
</div>
<div>
<div>
// 새로운 api 호출을 통한 댓글 불러오기가 아닌, 리렌더링만으로 댓글을 임시로 보여주기 위한
// 코드
{temporaryContext.map((item, index) => (
<div
key={index}
ref={(ref) => (contextRef.current[String(item.id)] = ref)}
>
<div
className="flex justify-between border-2 py-2 pl-3 my-1
text-[14px] border-y-gray-100 border-x-white border-t-white"
>
<p>
{userName} : {item.data}
</p>
<p>
<button
onClick={() => deleteTemporaryContext(Number(item.id))}
>
<GrFormClose />
</button>
</p>
</div>
</div>
))}
-> INSERT API 실행 후 정보를 useState에 담아 뿌려줌으로써 백엔드에 한번 더 통신하는 것이 아닌 클라이언트에서 처리할 수 있게 됐다.
( 다른 페이지에 갔다가 다시 들어오면, useState는 초기화되고 SELECT API를 통해 댓글이 불러와진다.)
사용자가 많은 서비스에서는 API 호출 한 번이 성능에 영향을 줄 수 있다.
그래서 기능 구현을 할 때 , 렌더링을 최소화하고 API호출을 하지 않고 클라이언트에서 처리할 수 있는 방법을 고민할 필요가 있다.
React 환경에서 작업할 때는 렌더링을 어떻게 최소화할 수 있을까에 대해서만 생각하고 만들어왔어서, api 호출을 줄이는 방향은 생각하지 못했었습니다. 앞으로는 기능 구현할 때, 좀 더 나은 방향으로 생각해보고 구현해볼 수 있을 것 같습니다.