React Native에서 Spring Boot 서버와 통신하려면 HTTP 요청을 보내야 한다.... fetch를 사용해 보자.
fetch 기본 문법
GET 요청은 단순하다. URL만 넘기면 된다.
const response = await fetch('http://서버주소/api/words');
const data = await response.json();
POST 요청은 method, headers, body를 지정해야 한다.
const response = await fetch('http://서버주소/api/words', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ english: 'apple', korean: '사과' })
});
개발 환경에서 서버 주소
로컬 개발할 때 가장 많이 겪는 문제가 서버 연결이다. Android 에뮬레이터에서 localhost를 쓰면 에뮬레이터 자기 자신을 가리키기 때문에 연결이 안 된다. 호스트 PC의 서버에 접근하려면 10.0.2.2를 써야 한다. iOS 시뮬레이터는 localhost가 정상 작동한다.
import { Platform } from 'react-native';
const BASE_URL = Platform.select({
android: 'http://10.0.2.2:8080/api',
ios: 'http://localhost:8080/api',
});
에러 핸들링 주의점
fetch는 Axios와 다르게 4xx, 5xx 응답에서 에러를 던지지 않는다. 서버가 404를 응답해도 fetch는 성공으로 처리한다. 그래서 response.ok를 직접 체크해야 한다.
const response = await fetch(url);
if (!response.ok) {
throw new Error(`서버 오류: ${response.status}`);
}
const data = await response.json();
네트워크 자체가 안 되는 경우(서버 꺼짐, 인터넷 끊김)에만 fetch가 에러를 던진다.
컴포넌트에서 사용 패턴
API 호출할 때는 loading, error, data 세 가지 상태를 관리하는 게 일반적이다. 로딩 중에는 스피너를 보여주고, 에러가 나면 에러 메시지를 보여주고, 성공하면 데이터를 렌더링한다.
const [words, setWords] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(`${BASE_URL}/words`)
.then(res => res.json())
.then(data => setWords(data))
.catch(err => setError(err.message))
.finally(() => setLoading(false));
}, []);