반응형

리팩토링은 어려워


얼마 전 react-query 로 데이터 호출 프로세스를 변경했다. 이 때만해도 데이터가 술술 잘 불러와지더라니 낌새를 챘어야 했다. 컴포넌트를 하나 둘 추가하다 보니 Mypage 로 이동할 때마다 에러를 마주치게 되었다.

 

Should have a queue ~~

 

아니 이건 또 처음 보는 에런데,, 당황의 연속,,

구글링을 열심히 해보니 React Hook 의 규칙 중 하나인 “Hook 은 항상 동일한 순서로 호출되어야 한다” 는 규칙을 위반했을 때 발생한다고 한다. 그런데 이전까지는 잘되다가 갑자기 안되는 이유는 무엇?

범인은 바로 너


지피티가 알려준 나의 코드의 문제 부분을 함께 찾아보게 되었다. 예전의 나는 응애였기에 몰라 하란대로 한 부분이었는데 지금 와서 보니 너무 얼척이 없는 문제를 일으키고 있었다.. 공부의 중요성 ,,,,,,,

*// 문제가 있는 코드*

const purchaseUserIds = referralPurchases

.map(*purchase* => purchase?.user_id)

.filter(*id* => !!id);

*// 반복문 안에서 Hook을 호출하는 잘못된 패턴*

const userInfoQueries = purchaseUserIds.map(*userId* => useUserByUserId(userId));

 

문제 원인

useQuery 로 불러온 데이터를 순회하면서 또 useQuery 써버리기

정확히 말하면 반복문 내에서 Hook 을 호출하면 렌더링마다 Hook의 호출 순서가 달라질 수 있기 때문에 동적 Hook 호출이 되고 이는 리액트 규칙 위반이다.

React Hook 규칙


  1. 최상위에서만 호출
    1. 컴포넌트 혹은 커스텀 훅의 최상위 스코프에서만 훅을 호출
    2. 조건문, 반복문, 중첩된 함수 안에서 훅을 호출하면 안됨
  2. 렌더링마다 동일한 순서로 호출
    1. 컴포넌트가 매번 렌더링될 때 훅이 호출되는 순서와 개수가 변하면 안됨
    2. 호출 순서가 바뀌면 이전 렌더에서 저장해둔 “훅의 큐” 를 찾아올 수 없어 오류가 발생

왜 동일한 순서여야 할까?


리액트의 훅 동작 순서를 파악해보자.

  • 컴포넌트가 렌더링 될 때 마다, 리액트는 훅 호출 순서를 따라 hook1, hook2, … 순으로 큐를 꺼내 상태를 연결
  • 만약 어떤 렌더에서 hook2 가 호출되지 않거나, hook4 가 먼저 호출 되면 리액트는 이전에 저장된 큐가 없다고 판단하며 에러를 던짐

리액트가 훅 순서를 기억하는 이유 → 복작한 트리 구조를 따로 추적하지 않아도됨 → 단일 연결 리스트 형태로 훅 상태를 관리

해결 방법 (useQueries)


useQueries 는 훅 순서를 고정해 동적으로 쿼리를 생성할 수 있게 도와준다. 이 훅이 내가 원하는 기능을 구현하기에 안성맞춤이다고 느끼게 되었다.

import { useQueries } from '@tanstack/react-query';

*// 해결된 코드*

const userInfoQueries = useQueries({

queries: purchaseUserIds.map(userId => ({

queryKey: ['user', userId],

queryFn: () => useUserByUserId(userId),

enabled: Boolean(userId),

})),

});

오늘의 교훈


“Hook은 마법 같은 편의 기능이지만, 그 뒤에 숨은 내부 메커니즘을 이해해야 비로소 제대로 쓸 수 있다.”

— 익명의 React 개발자 —

반응형
반응형

오픈을 하루 앞두고 부담감이 솟구치지만 그래도 뭔가 잘 되어가고 있다는 기분에 그나마 버틸만 한 월요일 아침. 팀장님 왈 ‘NFT id 가 1001번 부터 url이 잘못되어있어요.’

 

예?!

아 엑셀 실수..


나는 보통 thirdweb에서 NFT 데이터를 관리하고 NFT를 민팅하는데 csv 파일을 사용해서 올린다. 이전에 했을때는 csv 파일에서 셀 우측하단을 잡고 주욱 잡아 늘리면 아래 행으로 복사가 되었다. 근데 여기서 이름에 해당하는 컬럼의 id 값만 바뀌고 image url은 안바뀌었는데 어찌된 영문인지 이번에는 url 도 같이 바뀌었다. 오마이갓

 

이래서 더블체킹을 해야하는데.. 여튼 자책할시간은 없다. 방법을 찾아보았다.

updateBaseUri


다행스럽게도 updateBaseUri 함수가 구현되어 있었다. nft 를 민팅하면 baseurl 을 기준으로 id 값별 url이 매핑된다. 그래서 tokenId = 1 이라면 baseUrl/1 이렇게 metadata가 매핑된다.

 

하지만, 나는 처음에 baseUrl 이 이미지만 바뀌는 구나! 나는 이미지만 바꾸면되니까 이걸로 고정시켜버리자! 해서 이미지 url을 붙여버렸더니 역시나 안됐다..

 

(이래서 선공부 후개발 해야하는데 급한대로 하다보니 이렇다.)

 

그래서 이걸 어떻게 해야하나 고민을 하다가 대박적인 아이디어가 떠올랐다.

그냥 다시 민팅해~


그렇다. 가장 간단하고 빠른 방법. 다시 민팅

 

일단 기존에 나는 두번의 배치 민팅을 통해 nft 를 배포했기 때문에 두개의 baseUrl 이 필요했다. 그래서 새로운 더미 컨트랙트를 배포하고 두번의 동일한 nft를 배포한 후 새로운 uri 를 적용시키기로 했다.

 

결과는 성공적.. 이렇게 내 오전 업무는 날라갔다.

 

오늘의 교훈

  • 더블체킹을 하자.
  • baseUrl 에 대해 알게 되었다.
반응형
반응형

이전 회차에서 rpc url 이 다운되어 새로운 rpc url을 fallback 형식으로 변경했다. 이는 보기엔 잘 되는것 처럼 보였으나,, 블록체인 비즈니스에 대해 잘 모르던 나에게 한 차례 위기가 찾아왔다.

나 사실 공짜아님 ㅋ


drpc 뭐시기 라는 url 을 사용하고 있던 와중 갑자기 408 에러 (맞나?) 가 뜨게 되어 에러 메시지를 보니 다음과 같았다.

??? : 프리티어 끝났다. 더 쓰려면 결제하던지 말던지 ㅋ

왜 공용이겠어


일단 운영서버를 돌려야하니까 급한대로 다시 polygon-main url 을 적용했다. 어느정도 해결이 되는 듯 했으나,, 저번부터 나를 괴롭히던 view 함수 호출 시 이전 값이 랜덤하게 불러와지는 현상이 다시 발생하게 되었다.

 

아 왜그래 진짜

 

이 오류를 해결하기 위해 지피티를 열심히 괴롭힌 결과, polygon-main url은 아마도 공용 url 이니까 여러개의 url을 fallback 했을 것 이고, 그렇기 때문에 가끔 이전 값을 보내줄 수 있다고 설명해줬다.. 고마워 지피티야..

 

이 오류를 안 이후 얼마되지 않아 바로 호출되었고 사태에 대해 설명했다. 솔루션에 대해 고민을 해야했고 찾아본 결과 두 가지로 추려졌다.

  1. 직접 노드를 구매해 관리하기
  2. Alchemy, Infura 등 노드 관리 서비스 이용하기

메인 체인이 확정되지 않았기 때문에 노드를 구매한다는 것 자체가 리스키 했기 때문에 금방 사설 노드를 사용하는것으로 결정 되었다.

새로운 서비스는 어려워


https://www.alchemy.com/

 

Alchemy - the web3 development platform

Whether you're a beginner developer, startup, web3 market leader, or a large enterprise, Alchemy makes multichain web3 development easy.

www.alchemy.com

 

우리 서비스는 rpc call 이 많지 않기때문에 요금제를 크게 잡을 필요가 없어 프리티어 윗단계로 진행했다. 대시보드를 생성하고나니 Alchemy 도메인과 API key를 받게 되었고, 이를 합쳐서 wagmi 에 적용만 해준다면 손쉽게 적용할 수 있었다.

 

이제 새로고침을 한 후 rpc call 이 얼마나 사용되나 볼까? 했더니 얼래 ? 새로고침했다고 call 이 90번이나 호출된 것이다. 도대체 어디서,,

 

지금은 당장 개발이 급해 최적화를 할 시간은 없지만 언젠가는 해결해야할 문제가 생겼다.. 야호

 

여튼 rpc 가 여러모로 나를 많이 괴롭혔다. 여기서 얻은 교훈. 어떻게든 돈을 벌 수 있다(?) 는 아니고 너무 공짜 좋아하지 말자 입니다.

반응형
반응형

배경


회사의 노드 홈페이지가 컨트랙트 정보를 불러올 수 없어 트랜잭션이 발생되지 않는 문제가 있었다. 컨트랙트 데이터가 꼬여있나 싶어 부랴부랴 서버를 까봤지만 문제가 없었다. 그러나, 브라우저 콘솔에 polygon-rpc.com 으로의 요청이 자꾸 실패한다는 에러가 발생하는 것이었다.

 

설마 rpc 가 문제겠나 싶어 급한대로 주석처리하고 해결하고, 리팩토링을 진행했다. 그럼에도 불구하고 계속되는 삽질.

 

혹시 몰라 chainlist 홈페이지에 Polygon rpc 를 검색해보았더니 polygon-rpc 서버가 다운이 되었던 것이다!!

문제


Polygon-rpc.com 서버가 다운되어 요청에 대한 응답 x

문제를 파악했으니 일단 내 잘못이 아님에 안심하고, 대체 서버를 찾아보기로 했다. 다행히도 polygon rpc 서버는 여러가지가 있었고 최상단 빠르고 안전해보이는 서버를 선택하게 되었다.

해결


  1. Wagmi Config 에서 transport 값 변경

기존 코드에서 transport 속성은 다음과 같이 되어있었다.

transports : {
    [polygon.id] : http()
}

 

http() 함수는 블록체인의 rpc 노드를 설정해준다. 인자 값으로 url 을 넣어주면 해당 url 로 rpc 서버가 세팅된다.

 

transports : {
    [polygon.id] : http('https://alternative-rpc-url')
}

계획


현재 다른 일들이 많아 바로 적용은 못했지만 발전된 방향을 찾을 수 있었다.

 

멀티 rpc

 

바뀐 rpc 서버도 맛이 갈 수 있기 때문에 멀티 rpc 주소를 구성해야한다.

transport: fallback([ 
    http('https://1.rpc.thirdweb.com/...'), 
    http('https://mainnet.infura.io/v3/...') 
  ]), 

 

viem 라이브러리의 fallback 함수를 사용하면 url 이 작동이 되지 않을 때, 대체 url 로 시도하게된다.

반응형

+ Recent posts