Logo
Published on
·5 min read

React Navtive에서 외부 api 호출 시 발생한 오류: Network request failed

개요

React Navtive로 작업 중 외부 apiPOST로 호출했을 때 오류가 발생했습니다.

참고로, GET으로 동일한 호스트의 다른 api를 호출할 때는 문제가 없었습니다.

오류: Network request failed

처음 발생한 오류는 Network request failed입니다.

검색 시 가장 많이 나오는 해결 방법은 Android Manifest 수정이었습니다.

Android Manifest 수정

결론부터 말씀드리면, 저는 이 문제는 아니었습니다.
  1. android의 android/app/src/main/AndroidManifest.xml 파일에 android:networkSecurityConfig 설정을 아래와 같이 추가
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 생략 -->
    <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher"
               android:roundIcon="@mipmap/ic_launcher_round"
               android:allowBackup="false"
               android:theme="@style/AppTheme"
               android:networkSecurityConfig="@xml/network_security_config">
       <!-- 생략 -->
    </application>
</manifest>
  1. android/app/src/main/res/xml/network_security_config.xml 파일을 생성하고 아래와 같이 설정
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">example.com</domain>
    </domain-config>
</network-security-config>

하지만, 저의 경우 이 방법으로는 해결되지 않았습니다.

원인을 찾고 에러 해결 후에, 이 내용을 삭제하고 실행해도 Network request failed 에러가 발생하지 않았습니다.

그래서 위 내용은 원상 복구했습니다.

참고로 android/app/src/main/AndroidManifest.xml 원상 복구 내용은 아래와 같습니다.

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 생략 -->
    <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher"
                android:roundIcon="@mipmap/ic_launcher_round"
                android:allowBackup="false"
                android:theme="@style/AppTheme"
                android:usesCleartextTraffic="true">
        <!-- 생략 -->
    </application>
</manifest>

fetch 호출 부분: 'Content-Type'

headers'Content-Type'을 설정하지 않았습니다.
(Copilot을 사용하다보니, 자동완성으로 'Content-Type'이 아닌 ContextType으로 설정해주는 바람에 생긴 오류였습니다. 😂)

React Navtive 공식 문서의 Networking 문서를 참고하면 아래와 같은 코드로 설명합니다.
header에서 'Content-Type'은 작은 따옴표(')로 감싸져서, Accept와 다르게 쓰이고 있는 것을 주목하세요.

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue',
  }),
})

이 것으로 해결이 되었습니다.

최종 코드는 아래 최종 코드에서 확인할 수 있습니다.

오류: 403

번외로, Network request failed의 원인을 찾으며 body에 json이 아닌 object로 데이터를 보내봤습니다.

저는 google drive api를 호출했는데, body 내용이 제대로 전달되지 않아(content-type이 맞지 않아) 아래와 같이 403 에러가 발생했습니다.

{"error": {"code": 403, "errors": [[Object]], "message": "The user does not have sufficient permissions for this file."}}

최종 코드

최종 코드를 남겨봅니다.

오류를 발생시켰던 코드는 주석으로 함께 남겨두었습니다.

export const createGDriveAppDataFile = async (fileName: string, fileContent: string) => {
  const url = `https://www.googleapis.com/drive/v3/files?key=${key}&alt=json`

  return fetch(url, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${accessToken}`,
      //ContextType: 'application/json', // Network request failed
      'Content-Type': 'application/text',
    },
    body: JSON.stringify({
      name: fileName,
      parents: ['appDataFolder'],
      mimeType: 'application/json',
    }),
    /*
    // 403, The user does not have sufficient permissions for this file.
    body: {
      "name": fileName,
      "parents": ['appDataFolder'],
      "mimeType": 'application/json',
    },*/
  })
}

마무리

원인을 파악하고 나니, Content-Type이 정상적으로 동작하지 않은 간단한 이유인데,
이 부분을 찾는데 시간이 걸린지라;;; 이렇게 기록해둡니다.

저처럼 시간 허비 하지 않길 바랍니다. 😂

생활코딩! React 리액트 프로그래밍, 위키북스  리액트 네이티브를 다루는 기술:실무에서 알아야 할 기술은 따로 있다!, 길벗
(위 링크는 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.)