진행중인 React프로젝트에 Recoil 상태 관리, Axios, Postman을 활용한 API 통신 및 MockServer 연동을 했습니다
Mock 서버는 실제 서버의 동작을 모방하는 서버입니다. 실제 서버와 동일한 엔드포인트를 제공하며, 클라이언트가 요청 시 미리 정의된 응답을 반환합니다. 백엔드 개발이 완료되지 않은 상태에서 프론트엔드 개발을 진행하거나, 서버 통신에 대한 테스트를 수행할 때 유용하게 사용됩니다.
먼저, Postman을 실행하고 "Mock Server"를 선택하고 + 로 추가합니다.
다음화면에서 콜렉션을 정의합니다.
다음으로 Mock서버의 이름을 작성하고 Save the mock server URL as an new environment variable 체크하고 서버를 생성합니다.
이렇게 생성된 Mock 서버는 Postman의 주소를 통해 접근할 수 있습니다.예를 들어, https://{{mockId}}.mock.pstmn.io/{{endpoint}} 와 같은 형태의 주소로 요청을 보낼 수 있습니다.
다시 Collections 탭으로 돌아가 Add request로 새로운 요청을 하나 생성합니다.
요청 URL 및 ResponseBody에 데이터 입력하기
Try로 요청에 대한 응답확인body에 응답이 잘 받아졌습니다.
우선, Recoil을 프로젝트에 설치하고 import합니다.
npm install recoil
그 다음으로, RecoilRoot를 추가합니다. Recoil component는 RecoilRoot 내에서만 사용할 수 있습니다. 이를 보통 최상위 컴포넌트에 적용합니다.
App.js
import { RecoilRoot } from "recoil";
...
export default function App() {
return (
<RecoilRoot>
{/* 컴포넌트들 */}
</RecoilRoot>
);
}
Recoil 상태를 생성합니다. 여기서는 list와 posts라는 두 가지 상태를 관리하도록 했습니다.
recoilState.js
import { atom, selector } from "recoil";
import axios from "axios";
// List에 대한 Atom
export const listState = atom({
key: "listState",
default: [],
});
// List에 대한 Selector
export const fetchListState = selector({
key: "fetchListState",
get: async () => {
const response = await axios.get(
`${process.env.REACT_APP_API_BASE_URL}/list`
);
const data = response.data;
return data;
},
});
// Posts에 대한 Atom
export const postsState = atom({
key: "postsState",
default: [],
});
// Posts에 대한 Selector
export const fetchPostsState = selector({
key: "fetchPostsState",
get: async () => {
const response = await axios.get(
`${process.env.REACT_APP_API_BASE_URL}/posts`
);
const data = response.data;
return data;
},
});
이 코드는 Recoil의 atom
과 selector
를 사용하여 데이터를 관리하는 방법을 보여주고 있습니다. 먼저, atom
은 상태의 단위로 생각할 수 있습니다. 이 코드에서는 list와 posts라는 두 가지 상태를 관리합니다.
// List에 대한 Atom
export const listState = atom({
key: "listState",
default: [],
});
// Posts에 대한 Atom
export const postsState = atom({
key: "postsState",
default: [],
});
각 atom은 고유한 key를 가진 상태의 단위입니다. 이 경우, 각각의 기본값은 빈 배열입니다.
다음으로, selector
는 파생된 상태를 나타냅니다. 파생된 상태는 기본 상태를 입력으로 받아서 변환한 값입니다. 이 경우, get 함수 내부에서 비동기 작업을 수행하여 데이터를 가져옵니다.
// List에 대한 Selector
export const fetchListState = selector({
key: "fetchListState",
get: async () => {
const response = await axios.get(
`${process.env.REACT_APP_API_BASE_URL}/list`
);
const data = response.data;
return data;
},
});
// Posts에 대한 Selector
export const fetchPostsState = selector({
key: "fetchPostsState",
get: async () => {
const response = await axios.get(
`${process.env.REACT_APP_API_BASE_URL}/posts`
);
const data = response.data;
return data;
},
});
Postman에서 만들었던 MockServer의 URL을 .env에 넣어서 따로 관리하였습니다.
각 selector
는 API를 호출하여 데이터를 가져옵니다. 이 작업은 비동기로 이루어지므로 async/await
구문을 사용하였습니다. 이렇게 selector
를 사용하면, 상태 값이 필요할 때마다 API를 호출하여 최신 데이터를 가져올 수 있습니다.
이렇게 Recoil을 사용하면, React 컴포넌트에서 필요한 상태를 쉽게 생성하고 관리할 수 있습니다. 이를 통해 애플리케이션의 상태 관리를 보다 효율적으로 할 수 있습니다.
먼저, Recoil을 사용하여 상태 관리를 설정합니다. fetchListState를 가져오기 위해 Recoil의 useRecoilValue 훅을 사용합니다.
MainDatePick.jsx
import { useRecoilValue } from "recoil"; // Recoil 훅 추가
import { fetchListState } from "../../stores/recoilState"; // fetchListState import
export default function MainDatePick() {
const data = useRecoilValue(fetchListState); // Recoil에서 데이터 가져오기
...
}
Axios를 사용하여 API 통신을 수행하고, Recoil에서 가져온 데이터를 사용합니다.
recoilState.js
import axios from "axios";
// ...
export const fetchListState = selector({
key: "fetchListState",
get: async () => {
const response = await axios.get(
`${process.env.REACT_APP_API_BASE_URL}/list`
);
const data = response.data;
return data;
},
});
컴포넌트에서 Recoil에서 가져온 데이터를 사용하여 UI를 업데이트합니다.
export default function MainDatePick() {
const data = useRecoilValue(fetchListState); // Recoil에서 데이터 가져오기
const [selectedDate, setSelectedDate] = useState(new Date());
// ...
const sortedData = [...data].slice(0, 6);
const filteredData = sortedData.filter(
(item) =>
(formatDate(item.start) <= selectedDate &&
formatDate(item.end) >= selectedDate) ||
formatDate(item.start).toDateString() === selectedDate.toDateString() ||
formatDate(item.end).toDateString() === selectedDate.toDateString()
);
// ...
return (
<MainDatePickWrap>
{/* Calendar 또는 DatePicker 렌더링 */}
{/* ListContainer에서 데이터 렌더링 */}
{/* 모바일 환경에서 MoreButton 렌더링 */}
</MainDatePickWrap>
);
}