티스토리 뷰
오늘은 React에서 ajax를 이용하여 데이터를 가지고 오는 것을 배웠다.
ajax를 사용하기 위해서 json-server를 구성할 것이다. 먼저 json-server를 설치한다.
npm install -g json-server
-g 옵션은 global의 준말로, 특정 폴더에 종속되지 않고 현재 컴퓨터 사용자 계정에 대해 전역으로 사용할 수 있도록 설치된다.
그리고 json-server를 가동하기 위한 json 데이터를 구성한다. 이는 json 형태이면 어떤 데이터라도 괜찮다.
이런 json-server는 React를 구동시키며 함께 구동시킬 수 있다.
방법은 간단하다. React 작업 폴더에 있는 package.json 파일에 있는 scripts 중 start 항목에 "react-scripts start"라고 되어 있는 것을 |를 사용하여 "react-scripts start | json-server --watch json데이터파일 --port 포트숫자"로 덧붙인다. 데이터 파일에는 데이터 파일 이름을 적으면 되고(ex. data.json) 포트숫자는 사용할 포트를 적으면 된다. 기본값은 3000이다.
이렇게 사용하다보면 CORS 문제가 나올 수 있다. React와 json-server의 포트번호가 다르면, 도메인과 포트번호의 조합이 완벽하게 일치하지 않기 때문에 CORS를 어겼다고 나오는 것이다. 이를 해결하기 위해 package.json파일에 proxy 설정을 추가한다.
"proxy": "http://localhost:포트번호",
이렇게 수정하면, React 내에서 json-server에 접근할 때 설정에 추가한 도메인을 제외하고 뒤에 있는 부분으로만 접근할수 있다.
예를 들어, json 데이터에 hello라는 항목이 있다면 이 항목은 http://localhost:포트번호/hello로 접근할 수 있다. 그러나 proxy 설정을 했다면 그냥 /hello로 접근하면 된다.
axios
ajax를 처리하는 방법 중 가장 활발히 활용되는 건 axios 라이브러리의 활용이다. 저번 자바스크립트를 배웠을 때도 이 라이브러리를 활용했었다. 먼저 axios 라이브러리를 설치한다.
yarn add axios
그리고 데이터를 준비한다. 수업 때 예제로 사용했던 데이터는 너무 길기 때문에 생략한다.
이제 axios를 활용하여 ajax를 처리해보자.
import React, {memo, useState, useEffect} from 'react';
import axios from 'axios';
const Department = memo(() => {
const [department, setDepartment] = useState([]);
useEffect(() => {
(async () => {
let json = null;
try {
const response = await axios.get('/department');
json = response.data;
} catch (e) {
console.error(e);
alert(`데이터 요청에 실패했습니다\n${e.message}`);
return;
}
setDepartment(json);
})();
}, []);
return (
<div>
<table border='1'>
<thead>
<tr>
<th>학과번호</th>
<th>학과명</th>
<th>학과위치</th>
</tr>
</thead>
<tbody>
{!department.length ? (
<tr>
<td colSpan='3' align='center'>
검색결과가 없습니다.
</td>
</tr>
) : (
department.map((v, i) => {
return (
<tr key={i}>
<td>{v.id}</td>
<td>{v.dname}</td>
<td>{v.loc}</td>
</tr>
)
})
)}
</tbody>
</table>
</div>
);
});
export default Department;
먼저 알아두어야 할 것은, ajax는 비동기처리이다. 다시 말해, 데이터를 불러오는 작업이 끝나든 말든 밑에 있는 코드는 계속해서 실행된다. 때문에 밑에 있는 화면출력이 먼저 실행된다. 그럼 방법이 없을까?
useState를 사용하여 상태값을 만들면 된다. ajax로 가지고 온 데이터를 이 상태값에 넣고, 출력할 때 상태값을 사용하면, 상태값이 바뀔 때마다 컴포넌트가 렌더링 되므로 가지고 온 데이터를 출력할 수 있다.
가지고 오는 데이터는 배열이므로 초기값은 빈 배열로 설정해두었다.
ajax 처리는 페이지가 렌더링 되자마자 실행되어야 한다. 그러므로 useEffect를 사용하여 콜백 함수를 정의하고, 두 번째 파라미터에는 빈 배열을 넣어둔다.
여기서 주의할 것은, useEffect에 전달되는 콜백함수는 async를 직접 적용하면 오류가 난다. 왜일까?
useEffect는 아무것도 반환하지 않거나 clean up 함수(return 뒤에 오는 함수)를 반환한다. 그러나 async 키워드를 사용하게 되면 promise 객체를 반환하므로 오류가 발생하는 것이다.
그러므로 async~await를 사용한 비동기 함수를 useEffect 외부에 정의하거나, 혹은 useEffect의 콜백함수 내부에 정의하거나, 콜백함수 내부에 즉시 실행 함수로 정의해야 한다. 위의 예제에서는 콜백함수 내부에 즉시 실행 함수로 정의했다.
데이터를 받아올 변수인 json을 정의하고, try~catch문을 이용하여 예외처리를 한다. json에 받아온 것의 data를 추출해내고, 이것을 상태값에 넣는다.
밑에 있는 retrun 출력에서는 표를 만들어 가지고 온 상태값을 반복탐색하며 태그를 만들도록 했다. 만약 데이터가 없어서 상태값이 비었다면 검색결과가 없다는 문구가 표에 들어가도록 했다.
axios 뒤에 메서드로 get, post, delete, put 중 무엇을 주냐에 따라 가지고 오는 데이터 방식을 달리할 수 있다.
'React' 카테고리의 다른 글
3. axios hook (0) | 2022.11.03 |
---|---|
1. React (0) | 2022.10.31 |