fetch()는 ECMA Script가 제공하는 메서드입니다. API 서버로 http 요청을 송신 및 수신 할 수 있도록 도와줍니다.자세한 정보
fetch()
는 url을 매개변수로 받거나 url, options를 매개변수로 받습니다. return 값은 promise object입니다. then
과 catch
에 각각 onResolve
, onReject
, onError
콜백 함수를 전달해 응답을 처리할 수 있습니다.
fetch("localhost:8080/todo") // GET 요청
.then(response => {
// response 수신 시 하고 싶은 작업(onResolve)
},
rejected => {
// promise가 reject 됐을 때 하고 싶은 작업(onReject)
})
.catch(e => {
// error 발생 시 하고 싶은 작업(onError)
})
아래 두 가지 상황에서는 url과 options를 매개변수로 지정합니다.
① 메서드를 명시하고 싶은 경우
② 헤더나 바디를 함께 보내야 하는 경우
const options = {
method: "POST",
headers: [
["Content-Type", "application/json"]
],
body: JSON.stringify(data)
},
fetch("localhost:8080/todo", options)
.then(response => {
// response 수신 시 하고 싶은 작업(onResolve)
}, rejected => {
// promise가 reject 됐을 때 하고 싶은 작업(onReject)
})
.catch(e => {
// error 발생 시 하고 싶은 작업(onError)
})
위 코드와 같이 fetch에 localhost:8080/todo
를 명시하면 확장성이 낮습니다. 유틸리티 함수를 작성합니다. 유틸리티 함수는 api-config.js
, ApiService.js
를 작성합니다.
api-config.js
let backendHost;
const hostname = window && window.location && window.location.hostname;
if (hostname === "localhost") {
backendHost = "http://localhost:8080";
}
export const API_BASE_URL = `{backendHost}`;
apiService.js
import { API_BASE_URL } from '../api-config';
export function call(api, method, request) {
let options = {
headers: new Headers({
"Content-Type": "application/json",
}),
url: API_BASE_URL + api;
method: method,
};
if (request) {
// GET method
options.body = JSON.stringify(request);
}
return fetch(options.url, options).then((response) => {
if (response.status === 200) {
return response.json();
}
}).catch((error) => {
console.log("http error");
console.log(error);
});
}
App Component에서 앞서 작성한 유틸리티 함수를 사용합니다. 무한루프를 피하기 위해 useEffect()
를 추가했고, addItem
, deleteItem
, editItem
메서드가 수정됐습니다.
import './App.css';
import Todo from './Todo';
import React, { useEffect, useState } from 'react';
import { Container, List, Paper } from '@mui/material';
import AddTodo from './AddTodo';
import { call } from './service/ApiService';
function App() {
const [items, setItems] = useState([]);
const requestOptions = {
method: "GET",
headers: { "Content-Type": "application.json"},
};
useEffect(() => {
call("/todo", "GET", null)
.then((response) => setItems(response.data));
}, []);
const addItem = (item) => {
call("/todo", "POST", item)
.then((response) => setItems(response.data));
}
const deleteItem = (item) => {
call("/todo", "DELETE", item)
.then((response) => setItems(response.data));
}
const editItem = () => {
call("/todo", "PUT", item)
.then((response) => setItems(response.data));
}
let todoItems = items.length > 0 && (
<Paper style={{ margin: 16 }}>
<List>
{items.map((item) => (
<Todo item={item} key={item.id} editItem={editItem} deleteItem={deleteItem} />
))}
</List>
</Paper>
);
return <div className="App">
<Container maxWidth="md">
<AddTodo addItem={addItem} />
<div className="TodoList">{todoItems}</div>
</Container>
</div>
}
export default App;
다음 글은 백엔드와 프론트엔드를 통합하는 방법 - Effect Hook, Promise에 대해 다룹니다.
React.js, 스프링 부트, AWS로 배우는 웹 개발 101
김다정 지음ㅣ에이콘출판ㅣ2022ㅣ도서 정보