🔍 배경 및 궁금증

상당히 이상했다. CORS 문제는 아니었다. 그저,
meta
라는 친구를 위에서 말해줄 때 발생한 오류였다.난생 처음 보는 오류의 타입인지라 당황스럽기 그지 없었다. 그렇다면, 어떻게 해결할까?
다음은 당시 오류가 나왔을 때의 코드이다.
import React, { useEffect, useMemo, useState } from 'react'; import styled from '@emotion/styled'; import Image from '@components/common/Image'; import colors from '@assets/colors'; const USER_IMAGE_DEFAULT = 'https://mblogthumb-phinf.pstatic.net/MjAxODEyMDVfMjY5/MDAxNTQ0MDA3NDgyNjgw.v21vfp4yFzGtYlNrFPeo7Cxkd6ZVa3ZNKeRwZe5l3e0g.y2pAI3tJYWq04q_FwbVgTOoTVo9bKcwISdhj9EAxNYgg.GIF.nang723/IMG_0834.GIF?type=w800'; const UserCard = ({ children, visible, userInfo, nowTag }) => { const { _id, fullName } = userInfo; const meta = userInfo.meta ? JSON.parse(userInfo.meta) : {}; const placeholder = useMemo(() => USER_IMAGE_DEFAULT, []); return ( <StyledUserCard key={_id}> <UserImageContainer> <UserAuthBadge visible={visible} /> <Image src={userInfo.image ?? ''} lazy block width={50} height={50} placeholder={placeholder} alt="profile" isCircle /> </UserImageContainer> <UserInfo> <Username>{fullName}</Username> <UserDoing>{meta?.tag ?? ''}</UserDoing> </UserInfo> {children} </StyledUserCard> ); }; export default UserCard;
📢 해결 방법
먼저 오류를 자세히 검토해보았을 때, 몇 가지 에러에서의 특징이 보였다.
performSyncWorkRoot
라던지, WorkLoopSync
라던지 말이다.또한, 리액트에서는
eact doesn't have access to the actual error object in development
라는 말에서 큰 힌트를 얻었다.즉, 리액트 내부에서는 이 오류를 관리할 권한이 없다는 것이다.
아무래도 해당
meta
는 비동기로 받아온 작업이기도 했고, 특히 렌더링에 있어서는 이것이 비동기로 받아온 작업이라는 힌트가 주어지지 않은 상태였다.따라서 이러한 상황에서는,
meta
를 useEffect
로 관리해주는 것이 타당해보였다.const [meta, setMeta] = useState({}); useEffect(() => { if (!userInfo) return; setMeta((state) => ({ ...state, ...(userInfo.meta ? JSON.parse(userInfo.meta) : {}), })); }, [userInfo]);
하지만 허탕...
여저니
memory
leak이라는 내용이 나왔는데... 그런데, 멘탈이 깨지는 와중에서 한 가지 아이디어가 나왔다.
본래
meta
는 비동기로 처리되는 상태인데, 내가 동기로 작동하는 부분에서 건드린 것은 아닐까?라는 생각이 들었다.따라서, 초기 userInfo를 내려주는 부분에서
useEffect
가 써져 있는 부분을 보았다.useEffect(() => { async function getUserInfo() { const userInfoToken = getCookie('userInfo'); if (userInfoToken) { const { _id, email, fullName, isOnline, notifications, posts, comments, banned, username = '', meta = {}, } = await getAuthUser(userInfoToken); fillUserInfo((state) => ({ ...state, _id, email, token: userInfoToken, fullName, isOnline, notifications, posts, comments, banned, username, meta, })); } } getUserInfo(); // 초기 렌더링에만 체크하는 역할이므로 넣지 않았다. // eslint-disable-next-line }, []);
여기서 만약 meta를 넣는다면 어떨까?라고 생각을 하게 됐다.
그래서 meta를 넣은 결과...!

오류 없이 잘 작동한다!
배운 점.
비동기 로직에서 관리되는 상태는 동기에서 제어시켜주면 안 된다는 것을 깨달았다. 이는 데이터의 일관적인 흐름을 방해하기 때문이다.
비록 1시간이나 오바된 에러였지만, 잘 해결할 수 있어서 다행이다!