Error: Exception in HostFunction: Malformed calls from JS: field sizes are different.

박은정·2023년 5월 2일
1

리액트네이티브

목록 보기
19/24

원문출처: React native error - 'Malformed calls from JS: Field sizes are different'

리액트 네이티브는 자바스크립트와 리액트를 사용해서 네이티브 모바일 앱을 빌드할 수 있는 강력한도구입니다.
하지만 다른 도구와 마찬가지로 앱을 빌드하는 동안 발생할 수 있는 고유한 문제와 오류가 있습니다.
이러한 오류 중 하나는 "Malformed calls from JS: Field sizes are different." 입니다.
이 오류는 디버깅하기 까다로울 수 있지만, 몇 가지 지침을 따르면 쉽게 수정할 수 있습니다.

어떤 오류인가요?

리액트 네이티브 애플리케이션에 표시되는 오류 메사지는 일괄 처리된 브리지 메시지입니다.
리액트 네이티브는 리액트 네이티브 브리지를 사용해서 네이티브 측에 정보를 전달합니다.
이를 위해 매우 이상한 형식의 배열을 사용하기 때문에 해당 오류를 살펴보겠습니다.

[ 21, 32, 32, 32 ], // 호출된 모듈 ID
[ 1, 0, 1, 0 ], // 모듈 메서드 ID
[
[ 2696, 2000, 1679332067282, false],
[ 2696 ],
[ 2700, 100, 1679332067284, false ],
], // 해당 메서드에 주어진 매개변수
5271
]

이 형식에서 첫 번째 배열에는 호출된 모듈 ID
두 번째 배열에는 호출된 모듈 메서드 ID
세 번째 배열에는 해당 메서드에 주어진 매개변수 가 포함됩니다.

메서드1 을 호출한 두번째 메서드 호출 모듈 21 은 매개변수를 기대했지만, 매개변수로 전달된 것이 없기 때문에 여기서 문제를 쉽게 식별할 수 있습니다.
호출이 올바르게 되려면 세 번째 배열에 다른 자식이 포함되어야 합니다.

[ 21, 32, 32, 32 ], // 호출된 모듈 ID
[ 1, 0, 1, 0 ], // 모듈 메서드 ID
[
[ ] // 이 항목이 누락되었습니다.
[ 2696, 2000, 1679332067282, false],
[ 2696 ],
[ 2700, 100, 1679332067284, false ],
], // 해당 메서드에 주어진 매개변수
5271
]

그래서 리액트 네이티브가 모든 호출에 대해 모든 필드에 정보를 포함해야 한다고 기대하기 때문에 field sizes are different 에러가 발생합니다.
매개변수가 누락된 이유는 모듈 중 하나가, 입력 중 우리가 전달한 매개변수 유형 하나를 좋아하지 않아서 조용히 crash하기로 결정했기 때문입니다.
앱이 crash되지는 않았지만 잘못된 정보가 브리지를 통해 전송되었습니다.

오류를 해결하고 수정하는 방법

이를 해결하려면, 아래 두 가지를 파악해야 합니다.

  • ID가 21인 모듈이 어떤 모듈인지 모듈 이름,
  • ID가 1인 메서드의 메서드 이름 메서드 이름


    여기서 목표는 어떤 네이티브 모듈과 메서드 호출이 crash를 일으켰는지 알아내는 것이며,
    모든 RN 네이티브 모듈 호출은 브릿지를 통과하기 때문에 쉽게 파악할 수 있을겁니다.

1. 코드의 아무곳에나 다음 코드 스니펫을 추가합니다.

if (global.__fbBatchedBridge) {
  const origMessageQueue = global.__fbBatchedBridge;
  const modules = origMessageQueue._remoteModuleTable;
  const methods = origMessageQueue._remoteMethodTable;
  global.findModuleByModuleAndMethodIds = (moduleId, methodId) => {
    console.log(`The problematic line code is in: ${modules[moduleId]}.${methods[moduleId][methodId]}`)
  }
}

2. 디버그 모드에서 애플리케이션을 실행하고, 애플리케이션의 아무 곳에나 다음 코드를 붙여넣습니다. 이 코드에서 중단점을 설정합니다.

global.findModuleByModuleAndMethodIds(21, 1);
global.findModuleByModuleAndMethodIds(32, 0);
global.findModuleByModuleAndMethodIds(32, 1);
global.findModuleByModuleAndMethodIds(32, 0);

3. 각 호출을 조사해서 해당 네이티브 함수에 전달되는 잘못된 매개변수나 이상한 매개변수를 찾습니다.

global.findModuleByModuleAndMethodIds 함수는 crash를 일으킨 문제가 있는 모듈과 메서들 출력합니다.
이 예제에서 문제가 된 코드는 RNFBAnalyticsModule.logEvent , Timing.createTimer , Timing.deleteTimer , Timing.createTimer 중 하나에 있었습니다.

The problematic line code is in: RNFBAnalyticsModule.logEvent
The problematic line code is in: Timing.createTimer
The problematic line code is in: Timing.deleteTimer
The problematic line code is in: Timing.createTimer

해당 예제에서는 RNFBAnalyticsModule.logEvent 에 문제가 있었는데, 이는 이벤트를 Firebase를 로깅하는 방식 때문에 발생한 문제였습니다.
API 오류 응답 객체 전체를 prop 중 하나로 전달하고 있었는데, Firebase가 이를 좋아하지 않아 조용히 crash를 일으켜 위와 같은 이유를 발생했습니다.
문제가 되는 코드를 수정한 뒤에는 오류가 해결되었습니다.

결론적으로,

리액트 네이티브에서 "Malformed calls from JS: Field sizes are different." 오류는 힘들 것같지만, 올바른 접근 방식을 사용하면 수정할 수 있습니다.
위의 단계를 따르면 오류를 일으킨 문제가 있는 코드를 쉽게 식별하고 수정할 수 있습니다.

Malformed calls from JS: field sizes are different 스택오버플로우 에서 영감을 받았습니다.

profile
새로운 것을 도전하고 노력한다

1개의 댓글

comment-user-thumbnail
2023년 11월 2일

와 대박 .. 감사합니다!

답글 달기