// api/packge.json
....
},
"proxy" : "http://localhost:3080"
}
기존의 fetch, 혹은 axios를 통해 요청하던 부분에서 도메인 부분을 제거하여주니 CORS 에러를 해결됨
// my-app/services/BookService.js
export const getAllBooks = async () => {
const response = await fetch('/api/books');
return await response.json();
}
export const createBook = async (data) => {
const response = await fetch('/api/book', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({book: data})
})
return await response.json();
}
레포지토리로 받아온 파일에 보면 api2 라는 폴더가 존재하고 있다.
실제로 프로젝트 및 실무를 할 때, 하나의 도메인이 아닌 여러 개의 도메인에서 응답을 받아와야 하는 경우가 종종 있는데, 이럴 때는 유연하게 proxy를 설정해주어야 한다.
먼저 우회할 api 주소 제거
....
},
}
http-proxy-middleware 라이브러리 설치
//파일 전역에다가 설치
npm install http-proxy-middleware --save
React App그의 src 파일 안에서 setupProxy.js 파일을 생성 후 아래와 같이 작성을 해주었다.
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
"/api",
createProxyMiddleware({
target: "http://localhost:3080",
changeOrigin: true,
})
),
app.use(
"/api2",
createProxyMiddleware({
target: "http://localhost:3070",
changeOrigin: true,
})
);
};
api2에 관련된 fetch 함수를 만들어 줌.
export const getAllBooks = async () => {
const response = await fetch('/api/books');
return await response.json();
}
export const createBook = async (data) => {
const response = await fetch('/api/book', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({book: data})
})
return await response.json();
}
export const getAllTodos = async () => {
const response = await fetch('/api2/todos');
return await response.json();
}
export const createTodos = async (data) => {
const response = await fetch('/api2/todo', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({todo: data})
})
return await response.json();
}
CreateBook의 컴포넌트와 복사하여 이름만 바꾸어 주었다.
const CreateTodo = ({ onChangeForm, handleSubmit }) => {
return(
<div className="form-wrapper">
<div className="form">
<form>
<div className="input-group">
<label>todo</label>
<input
type="text"
onChange={(e) => onChangeForm(e)}
name="todo"
placeholder="todo"
/>
</div>
<div className="input-group">
<label>category</label>
<input
type="text"
onChange={(e) => onChangeForm(e)}
name="category"
placeholder="category"
/>
</div>
<div className="input-group">
<label>isComplete</label>
<input
type="text"
onChange={(e) => onChangeForm(e)}
name="isComplete"
placeholder="isComplete"
/>
</div>
<button
className="submit-button"
onClick= {() => handleSubmit()}
>Submit
</button>
</form>
</div>
</div>
)
}
export default CreateTodo;
DisplayBoard에서는 getAllTodo의 버튼이 클릭 될 때 실행 되도록 만들어 주었다.
import React from 'react'
const DisplayBoard = ({numberOfBooks, getAllBook, getAllTodo, numberOfTodos}) => {
return(
<div className="display-wrapper">
<div className="display-box">
<div className="display-board">
<h4>생성된 수</h4>
<div className="number">
{numberOfBooks}
</div>
</div>
<div className="display-board">
<h4>생성된 todo 수</h4>
<div className="number">
{numberOfTodos}
</div>
</div>
<div className="get-button">
<button onClick={() => getAllBook()}>Get all Books</button>
<button onClick={() => getAllTodo()}>Get all todos</button>
</div>
</div>
</div>
)
}
export default DisplayBoard;
BookTable과 비슷하게 구성 이름만 바꾸어 줌.
import React from 'react'
const TodoTable = ({todos}) => {
if (todos.length === 0) return null;
return(
<div className="table-wrapper">
<div className="table-box">
<h2>My Todos</h2>
<div className="table-scroll">
<table>
<thead>
<tr>
<th>Id</th>
<th>todo</th>
<th>Category</th>
<th>isComplete</th>
</tr>
</thead>
<tbody>
{todos.map((todo,index) => {
return (
<tr key = {index} className={index%2 === 0?'odd':'even'}>
<td>{index + 1}</td>
<td>{todo.todo}</td>
<td>{todo.category}</td>
<td>{todo.isComplete}</td>
</tr>
)
})}
</tbody>
</table>
</div>
</div>
</div>
)
}
export default TodoTable;
모든 컴포넌트들을 내려 주기만 하면 끝!
import React, { useState } from 'react';
import './App.css';
import Header from './components/Header';
import BookTable from './components/BookTable';
import TodoTable from './components/TodoTable';
import DisplayBoard from './components/DisplayBoard';
import CreateBook from './components/CreateBook';
import CreateTodo from './components/CreateTodo';
import { getAllBooks, createBook, createTodos, getAllTodos} from './services/BookService';
import Footer from './components/Footer';
function App () {
const [bookShelf, setBookShelf] = useState({});
const [myTodo, setMyTodo] = useState({});
const [books, setBooks] = useState([]);
const [numberOfBooks, setNumberBooks] = useState(0);
const [todos, setTodos] = useState([]);
const [numberOfTodos, setNumberOfTodos] = useState(0);
const handleSubmit = () => {
createBook(bookShelf)
.then(() => {
setNumberBooks(numberOfBooks+1);
});
}
const handleTodoSubmit = () => {
createTodos(myTodo)
.then(() => {
setNumberOfTodos(numberOfTodos+1);
});
}
const getAllBook = () => {
getAllBooks()
.then(data => {
setBooks(data);
setNumberBooks(data.length);
});
}
const getAllTodo = () => {
getAllTodos()
.then(data => {
console.log(data)
setTodos(data);
setNumberOfTodos(data.length);
});
}
const handleOnChangeForm = (e) => {
let inputData = bookShelf;
if (e.target.name === 'book') {
bookShelf.book = e.target.value;
} else if (e.target.name === 'category') {
bookShelf.category = e.target.value;
} else if (e.target.name === 'author') {
bookShelf.author = e.target.value;
}
setBookShelf(inputData);
}
const handleOnChangeTodoForm = (e) => {
let inputData = myTodo;
if (e.target.name === 'todo') {
myTodo.todo = e.target.value;
} else if (e.target.name === 'category') {
myTodo.category = e.target.value;
} else if (e.target.name === 'isComplete') {
myTodo.isComplete = e.target.value;
}
setMyTodo(inputData);
}
return (
<div className="main-wrapper">
<div className="main">
<Header />
<div className='handel_form'>
<CreateBook
bookShelf={bookShelf}
onChangeForm={handleOnChangeForm}
handleSubmit={handleSubmit}
/>
<CreateTodo
myTodo={myTodo}
onChangeForm={handleOnChangeTodoForm}
handleSubmit={handleTodoSubmit}
/>
</div>
<DisplayBoard
numberOfBooks={numberOfBooks}
getAllBook={getAllBook}
getAllTodo={getAllTodo}
numberOfTodos={numberOfTodos}
/>
<BookTable books={books} />
<TodoTable todos={todos} />
<Footer />
</div>
</div>
);
}
export default App;