React 트러블슈팅

김태성·2024년 4월 27일

내실 다지기

목록 보기
7/11

프로젝트를 하면서 생긴 트러블슈팅 기록용 공간이다.
이 글의 목적은 지금 배워서 나중에 써먹겠다는 것이 아닌, 지금 한번 경험해서 어떤 문제가 있었는지에 대해 기록하고, 나중에 이 부분을 다시 공부할때 내가 어떤것을 몰랐는지 확인하는 용도로 사용될 것이다.

최대깊이 오류

문제상황

원인

  componentDidUpdate(prevProps: Props) {
    if (prevProps.expand !== this.props.expand) {
      this.setState({ open: this.props.expand });
    }
      this.updateContentHeight();
  }

componentDidUpdate라는걸 사용했는데 그냥 썼더니 무한반복이 일어났다.

해결방법

  componentDidUpdate(prevProps: Props) {
    if (prevProps.expand !== this.props.expand) {
      this.setState({ open: this.props.expand });
    }
    if (prevProps.answers !== this.props.answers) {
      this.updateContentHeight();
    }
  }

this.updateContentHeight(); 함수에 if문을 달았다.
검색을 해보니 didupdate를 사용할때는 제귀를 조심해라는 글이 많다.

다음은 gpt의 대답이다.

  • componentDidUpdate 내에서 상태를 업데이트할 때는 조건문을 사용하여 무한 루프에 빠지지 않도록 해야 합니다. 상태 업데이트는 다시 componentDidUpdate를 호출할 수 있기 때문입니다.
  • 함수형 컴포넌트와 Hooks를 사용하는 경우, componentDidUpdate와 유사한 동작을 useEffect Hook으로 구현할 수 있습니다.

클래스 컴포넌트에서 navigate 안됨.

문제상황
클래스에서 navigate 사용이 안됨.

원인
클래스는 navigate 사용이 안된다고 함.

해결방법

const Create: React.FC = () => {
    const navigate = useNavigate();
    return (
        <>
        <NavBar /> 
        <PageBackGround>
        <ProblemPage navigate={navigate}/>
        </PageBackGround>
        </>
    );
  };
  
  export default Create;
---------
}else{this.props.navigate('/workbook');}

래핑을 한 후, 예외처리를 다 한뒤 navigate 함수를 썼음.
class 는 Hook을 사용하지 못한다고 한다.
그리고 class는 this를 통해서 상태를 관리하기 때문에
래핑을 한 후 navigate를 줘야 사용할 수 있다.

javascript url 입력값 오류

문제상황
백엔드 팀원이 데이터 출력값이 이상하다고 내 코드를 확인해라고 했다.

원인
프론트에서는 잘 보내고 있었다.

url = localhost:3000/api/~~~ /${text}/~~
(text = boolean)

if(!text){
~~
}

팀원의 코드는 이런식으로 돌아가는 코드였고, 내가 봐도 이상하지는 않았다.
하지만 아무리 봐도 데이터가 걸러지지 않는건 if문이 true가 나오는것이라 판단해서
typeof로 확인해보니 boolean이 아닌 string으로 나오고 있었다.

해결방법

스택오버플로우에도 같은 문제가 발생한 사람이 있었다.
위 글처럼 하드코딩한건 아니고 validation pipe 설정을 바꿔서 boolean 값도 들어오게 했다.
nest에서 사용하는 기술이라고 한다.
(transform = true)

데이터 내려보내기

문제상황

게시판 -> 게시물(카드형태) -> 자세히 보기
순으로 데이터를 계속 내려보내야 하는데, 부모 컴포넌트에서 자식 컴포넌트로 데이터를 보낼 때 null값을 내려보낸다.
console을 찍어도 분명히 데이터는 재대로 잘 있는데 null값만 계속 나왔다.

  const location = useLocation();
  const { state } = location;
  const [quizsetId, setQuizsetId] = useState<number | undefined>(undefined);
  console.log('quizsetid = ',state);
  useEffect(() => {
    if (state && state.quizsetId) {
        setQuizsetId(state.quizsetId);
    }
}, [state]);

모르겠는데 뭐라도 해야겠다 생각해서 location도 쓰고 코드가 난리가 났다.

원인
가만히 보면 useState, useLocation, useEffect를 모두 썼다.
동기/비동기가 섞였고 useEffect에는 조건까지 넣어서 순서가 더욱 꼬였는데,
useEffect가 실행되기 전에 데이터를 넘겨버리면 useState에 초기값인 null이나 undefine값이 먼저 넘어가버리고, 데이터를 받아온다는 것이었다.

console.log를 찍어도 계속 데이터가 정상적으로 나왔는데, 계속 고민하고 찾다보니 결국 찾은 것 같다.

해결방법

const QuestionInfo = () => {
  const {quizSetId} = useParams();

구조를 뜯어고쳤다. useParams라고 url을 통해서 데이터를 전달하는 방법을 사용햇다.

방법은 useParams를 사용해서 Id값을 전달한 후,
전달한 컴포넌트에서 get을 통해 데이터를 가져오는 방식이다.

  const {quizSetId} = useParams();
  const location = useLocation();
  const { subLectureUrl } = location.state || { subLectureUrl: "" };

그리고 이후 url도 내려줘야되서 코드를 다시 손봤는데 이건 잘된다.
괜히 useEffect를 사용법도 모르고 남용하다가 비동기 처리에 의해
순서가 미뤄지는 상황이 발생했나 보다.

++ useEffect는 랜더링 이후에 실행된다고 한다.

힘들었던점
console.log를 써도 디버깅이 전혀 안나오고 감도안잡혔던 적은 처음이다. 한참을 고민하고 검색도 많이 했어야 했는데, 검색 키워드를 재대로 정하는게 힘들었던거 같다. 대략 한 5시간쯤 걸렸던거 같다.

발표 1시간전에 mediapipe 프레임워크가 작동을 안함

문제상황
발표를 해야되는데 갑자기 fail to fetch가 떴다.
난 프론트 작업을 해야해서 media pipe가 뭔지 하나도 몰랐다.

해결 과정
fail to fetch를 검색했음.

  • 서버 확인
  • cors
  • 엔드포인트가 없음
  • 요청 api나 url이 잘못됨

이 4가지 중에 어제까지는 잘 되었으니 cors, endpoint, url 관련 문제는 아니라고 판단.
그럼에도 mediapipe가 안되는건 서버에서 데이터를 못보낸다고 판단.

=> mediapipe란 무엇인가?
구글에서 제공하는 api

그러면 어딘가에서 데이터를 보내와서 우리가 사용하는 구조겠구나.

그럼 어디에서 보낼까를 확인하려고 import url을 확인했음.

import vision from "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.3";

뭔지 모르겠으니까 일단 npm 검색.
이후 cdn jsdeliver가 있다는걸 확인

그래서 cdn jsdeliver의 연결 상태 확인

-> 인터넷 글 중에 cdn jsdeliver의 인증서가 만료되어서 연결이 안된다는 글 발견
cdn -> fastly로 바꾸니까 연결이 잘 됨.

힘들었던점
당장 1시간 뒤에 발표인데 어제까지만 해도 잘 되던게 안되니까
멘탈이 상당히 흔들렸음.

React Hook call error

문제상황
에러가 났다.

src/pages/create_question.tsx
  Line 12:52:  React Hook "useCookies" cannot be called inside a callback. 
  React Hooks must be called in a React function component or a custom React Hook function  react-hooks/rules-of-hooks

잘 읽어보니 React Hook은 callback 안에서 선언되면 안된다는 것이다.
생각해보니 useEffect 안에서 Cookie 관련 함수들을 잔뜩 썼었다.

해결방법

token
    const [cookies, setCookie, removeCookie] = useCookies(['jwt']);
	// useEffect 밖으로 꺼내기  
    useEffect(() => {
        
        const token = cookies.jwt;
        if (!token) {
            alert('로그인 해 주세요!')
            navigate('/main');
            return;
        }

useEffect 안에 있던 cookie 코드들을 밖으로 꺼냈다

Date.now() 시간 오류

문제 상황
cookie를 만드는데 자꾸 과거 시간이 떴다.

약 9시간 정도

원인
Date.now()는 UTC 시간대를 사용한다.
UTC란 전 세계 시간 연구소가 보유하는 시간의 척도 라고 하며
한국은 +9시간을 해야 한다고 한다.

해결

시간을 보정해주니 잘 되었다.

힘들었던점
무의식적으로 브라우저나 컴퓨터 시간일거라 생각을 해서 한참 해맸다.(약 2시간?)

쿠키 저장/불러오기 오류

문제상황
로그인해서 쿠키를 만들때 navigate로 페이지를 넘어가면 쿠키를 인식하지 못함.
근데 한번 더 로그인하면 잘 넘어감

원인

    const [cookies, setCookie, removeCookie] = useCookies();
    useEffect(() => {
        
        const token = cookies.get('jwt')   

이 코드가 문제였다.
useCookies()를 사용해서 cookies에 데이터를 받은 후,
이걸 get을 사용해서 불러올려고 했었다.
그래서 token을 console.log로 추적했다.

다음은 내 계정으로 처음 로그인 했을때 찍은 log이다.

깔끔하게 undefined가 되어있는걸 볼 수 있다.
다음은 내 계정이 아닌 팀의 계정으로 로그인 했을때 찍은 log이다.

내 계정의 token이 들어가 있는걸 볼 수 있다.


실제로 접속해 있는 계정의 쿠키값과 console.log에 찍히는 값이 다르다
그래서 우리가 추론할 수 있는거는 다음과 같다.

  • 리액트 hook을 사용할때(state, cookies) 처음은 빈 값을 들고오고, 사용했을때 갱신하게 된다.

  • 즉 처음은 빈값은 undefined가 나오고, 이후 값을 갱신한다.

해결방안

        const cookies = new Cookies();
        const token = cookies.get('jwt');  

cookies를 새로 선언하고 jwt를 가져오니 되었다.

이번 문제도 거의 3시간동안 머리싸메고 고민하다가 팀원분이 도와주셔서 고치긴 했는데, 뭐가 문제인지 머리싸매다가 겨우 알아내고 다시 적는 글이다.
왜 호출할때 갱신한뒤 호출을 안해주는지 진심으로 궁금하다.














profile
닭이 되고싶은 병아리

0개의 댓글