- Published on
- ·5 min read
React Navtive에서 외부 api 호출 시 발생한 오류: Network request failed
개요
React Navtive로 작업 중 외부 api
를 POST
로 호출했을 때 오류가 발생했습니다.
참고로, GET
으로 동일한 호스트의 다른 api를 호출할 때는 문제가 없었습니다.
오류: Network request failed
처음 발생한 오류는 Network request failed입니다.
검색 시 가장 많이 나오는 해결 방법은 Android Manifest 수정이었습니다.
결론부터 말씀드리면, 저는 이 문제는 아니었습니다. Android Manifest 수정
- 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>
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이 정상적으로 동작하지 않은 간단한 이유인데,
이 부분을 찾는데 시간이 걸린지라;;; 이렇게 기록해둡니다.
저처럼 시간 허비 하지 않길 바랍니다. 😂