CRUD 기능 실행 중 데이터를 보내 수정, 삭제, 생성을 했을 때 바로 적용되지않는 점 발생
변수가 변할 때(useEffect) get 요청을 보내 각각 변수가 변함을 알고 변할 수 있게 코드를 작성
리액트는 SPA 개발에 맞춰진 JS 라이브러리다. SPA의 큰 특징 중 하나라 함은 Blinking, 즉 새로고침이 없다는 점이 가장 두드러지게 난다.
하지만 단점이 많은데 낮은 SEO, 사용자 부담 증가 등이 있지만 새로고침이 없어서 서버에 CREATE, UPDATE, DELETE 작업을 했을 때 변해진 값으로 바로 변하지 않아 새로고침을 해야 값이 반영되는 문제가 있었다.
이러한 문제를 해결하기 위한 사투를 기록하겠다.
useAxios
기록을 보면 알겠지만 우리는 서버와 비동기 통신을 할 때를 우리가 만들어서 했다. 커스텀훅을 이용해 비동기 통신 관리 관련 훅을 만들었다.
여기에는 실시간 반영 기능이 없기에 그 변수값이 바뀌어도 서버에서 그 데이터를 가져온 변수를 다시 GET하는 게 없다는 뜻이다.
그래서 해결하도록 해봤다.
프론트엔드 팀원들과 모여 논의를 했고, 각자 맡은 기능들이 달라(맛포스트는 모달 위에 렌더링, 맛픽커 리스트 및 맛플레이스 픽 수정 관련 등) 반영을 해야하는 기능들을 따로 만들어서 보고하는 식으로 했다.
나는 카카오맵 관련 기능 / 맛플레이스 검색 기능 / 마이페이지 / 무한스크롤 등을 기능 개발 중이었는데, 마이페이지에 있는 EDIT 기능을 제외하고 CRUD 작업을 적용할 게 없어서 마이페이지에 적용해야하는 실시간 반영을 기술하겠다.
보다싶이 마이페이지에 닉네임, 메모, 사진을 바꾸는 EDIT 기능이 있다. 저걸 바꾸려고 PATCH 요청을 보내면 바로 실시간 반영이 안되고 새로고침을 해야했다.
const MyPage: React.FC = () => {
...
const [isChange, setIsChange] = useState<boolean>(false);
...
const { axiosData: getMemberAxios, responseData: memberData } = useAxios(
getMyData,
[isChange]
);
// 유저정보 중략
const [revisedName, setRevisedName] = useState(nickname);
const [revisedMemo, setRevisedMemo] = useState(memo);
const [revisedImage, setRevisedImage] = useState(profileUrl);
// 프로필 이미지 수정을 위한 ref 중략...
useEffect(() => {
getMemberAxios();
}, [isChange, isLoggedIn]);
// 모달 관련, 이미지 관련 코드 중략...
const onRevise = () => {
updateAxios();
onClickToggleEditModal();
setIsChange(!isChange);
};
return (
<FeedContainer>
<div className="userInfo_header_container">
<ImgContainer>
{profileUrl ? (
<UserImg src={profileUrl} alt="프로필사진" />
) : (
<EmptyImg />
)}
</ImgContainer>
<UserInfo>
<UserNickname>{nickname}</UserNickname>
{memo && <UserRemainder>{memo}</UserRemainder>}
<UserRemainder>
<FollowButton onClick={onClickToggleFollowingModal}>
팔로잉 {followings}
</FollowButton>
<FollowButton onClick={onClickToggleFollowerModal}>
팔로워 {followers}
</FollowButton>
</UserRemainder>
</UserInfo>
<EditIconStyled onClick={onClickToggleEditModal} />
<LogoutIconStyled onClick={onClickToggleLogoutModal} />
</div>
<ContentContainer>
<TabContainer>
<div className="tab_menu focused" aria-hidden="true">
Post
</div>
<div className="tab_menu" onClick={onClickTab} aria-hidden="true">
Pick
</div>
</TabContainer>
</ContentContainer>
<MyPagePostInfo />
// 모달 관련 코드 중략...
{isOpenEditModal && (
<ModalPortal>
<ModalContainer>
<ModalView>
<Header>정보 수정하기</Header>
<div>
<EditUserImg
src={revisedImage || profileUrl}
alt="프로필 사진"
onClick={onClickImg}
/>
<input
type="file"
accept="image/jpg,impge/png,image/jpeg"
name="profile_img"
className="image_upload"
onChange={onChangeImage}
ref={fileInput}
/>
</div>
<Input
type="text"
value={revisedName || ""}
onChange={onChangeName}
></Input>
<Input
type="text"
value={revisedMemo || ""}
onChange={onChangeMemo}
></Input>
<div className="button_container">
<ModalBtn onClick={onRevise}>제출</ModalBtn>
<ModalBtn onClick={onClickToggleEditModal}>취소</ModalBtn>
</div>
</ModalView>
</ModalContainer>
<ModalBackdrop onClick={onClickToggleEditModal} />
</ModalPortal>
)}
...
결론부터 얘기하자면 useState
를 사용해 isChange
라는 상태를 만들었고, 이 상태가 true
면(변한다면) useEffect
를 이용해 GET 작업을 실행하도록 변경했다.
처음 문제를 해결할 때 isChange
가 없는 상태로 진행했었다. 이때 내가 어떤 생각이었냐면
useEffect
의 의존성 배열에 변수를 집어넣으면 변수가 변하니 revise 관련 상태의 변수를 집어넣으면 되겠지
이 생각이었다. 하지만 저걸 넣으려니 당연히 안됐다. revised 관련 변수가 변하는 걸 어떻게 변하는지와 set을 이용해 입력할 때 변수가 변하게 한다면? 이랬는데 변할 때마다 onChange
를 이용해 GET해온다면 서버 통신이 쓸데없이 많아져 골머리를 앓았다.
그래서 구글링을 통해 boolean 데이터 관련 변수를 만들어줘 그 걸 기준으로 하면 어떨까 생각을 하게 됐고, isChange
라는 변수를 만들어 사용했다.
쓰다보니 isChange
가 되게 중요한 존재였다. useEffect
뿐만 아니라 useAxios
에게도 isChange
가 변한다면 너도 변해라 라는 단서를 주니 useAxios
한테도 되게 중요한 데이터였다. 또한 변해야하는 변수(revised
3대장)들이 많은데 isChange
로 실시간 반영이 일어나야하는 부위에 넣어주기만 하니 편하게 할 수 있었다. 또 if문을 활용하여 할 수도 있으니 활용성도 좋았다.
아직도 나는 멀었다. 간단한 서버 통신과 실시간 반영은 쉽게 했었는데 관리해야할 데이터들(맛포스트, 맛플레이스, 마이페이지 등)이 많아지면 그렇게 하면 안된다고 깨달았다.
또한 useEffect
의 존재에 더욱 감사하며 동작원리에 대해서 제대로 알아야겠다고 생각했다. 너무 효율적이고도 좋은 존재다.
그리고.. 단골 손님인.. React-Query는 맨날 나온다.. 실시간 반영 문제를 해결하고 프로젝트도 끝난 뒤 이 포스트를 작성하며 또 찾아봤는데 이러한 문제를 해결하는 방안을 더 찾아봤다.
useEffect
와 useState
를 이용해 GETreact-hot-loader
를 사용이런 식으로 나눠졌다. 역시 바퀴를 다시 발명하지 마라 했던가.. 글고 리액트 쿼리는 무슨 만능인가?? 맨날 나와 무슨;;
쨌든 결론은 리액트 쿼리에 대해서 무조건!! 알아야한다. option까지 붙이는 것도 생각해야하고! 리액트 쿼리는 진짜 재밌고 유익하게 배울 수 있을 거 같다.
뭔가 더 나은 해결점이 많았지만 그래도 배운 점이 많아서 되게 유익했다. 실패하고 공부하고 성장하고 나아가자! 화이팅
프로젝트하면서 돌아만가면 거기에서 끝낸던 제가 부끄럽게 느껴지네요 ㅎㅎ 고찰하는 모습 멋있습니다!