-
[Django/React] 백엔드 프론트엔드 통신하기 (fetch)JavaScript/React 2023. 1. 25. 21:56728x90반응형
데이터 fetch하기
django에서는 시스템을 보호하고 있기 때문에 아무데서나 fetch를 해올 수 없기 때문에 이를 설정하기 위해 cors-headers를 설치할 필요가 있다.
데이터를 fetch하기 위해서 먼저 django-cors-headers 설치하기
그런데 django-cors-headers란?
cors-headers는 특정 도메인에서 '나의 서버에서 브라우저로 fetch할 수 있는 사람'을 지정할 수 있게 해준다.
1. 백엔드에 cors-headers를 설치해준다.
python -m pip install django-cors-headers
poetry 환경일 경우
poetry add django-cors-headers
나는 poetry 환경을 사용하고 있기 때문에 아래 코드를 입력했다.
2. config/settings.py 파일 서드파티 리스트에 "corsheaders"를 추가해준다.
THIRD_PARTY_APPS = [ "rest_framework", "rest_framework.authtoken", "corsheaders", # cors-header 추가 ]
3. 같은 파일 미들웨어 리스트에 아래와 같이 추가해준다.
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', # cors-header 추가 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
4. 같은 파일 내에 아래 코드 작성
CORS_ALLOWED_ORIGINS = ["http://localhost:3000"]
이제 localhost:3000 에서는 장고 서버를 fetch할 수 있게 된다.
데이터 fetch해오기
타입스크립트로 작성하고 있기 때문에 일단 받아올 데이터의 타입 인터페이스를 작성해준다.
interface IRoom { pk: number; name: string; country: string; city: string; price: number; rating: number; is_owner: boolean; photos: IPhoto[]; }
데이터의 로딩 상태를 알려주는 useState를 작성하되 기본값은 true로 설정한다.
const [isLoading, setIsLoading] = useState(true); const [rooms, setRooms] = useState<IRoom[]>([]);
fetchRooms() 라는 함수를 만들고 데이터를 fetch해온다.
const fetchRooms = async () => { const response = await fetch("http://127.0.0.1:8000/api/v1/rooms"); const json = await response.json(); setRooms(json); setIsLoading(false); };
useState rooms에 받아온 데이터값을 json화한 상태로 넣어주고, 데이터를 다 받아온 상태이기 때문에 로딩 상태는 false로 변경한다.
fetchRooms() 함수를 useEffect로 호출시킨다.
useEffect(() => { fetchRooms(); }, []);
fetchRooms() 가 실행되고 fetch가 시작된다.
백엔드에서 fetch가 시작되고 response로부터 json을 추출해서 rooms 변수에 저장하고 setLoading은 false로 변경한다.
rooms는 array로 되어있기 때문에 rooms에 map을 해서 표시한다.
{rooms.map((room) => ( <Room // imageUrl={room.photos[0].file} imageUrl={ room.photos[0]?.file ?? `https://source.unsplash.com/random/450x$` } name={room.name} rating={room.rating} city={room.city} country={room.country} price={room.price} /> ))}
전체코드
📁 src/routes/Home.tsx
import { FaStar, FaRegHeart } from "react-icons/fa"; import { Box, Grid, HStack, Skeleton, SkeletonText } from "@chakra-ui/react"; import { useEffect, useState } from "react"; import Room from "../components/Room"; import RoomSkeleton from "../components/RoomSkeleton"; interface IPhoto { pk: string; file: string; description: string; } interface IRoom { pk: number; name: string; country: string; city: string; price: number; rating: number; is_owner: boolean; photos: IPhoto[]; } export default function Home() { const [isLoading, setIsLoading] = useState(true); const [rooms, setRooms] = useState<IRoom[]>([]); const fetchRooms = async () => { const response = await fetch("http://127.0.0.1:8000/api/v1/rooms"); const json = await response.json(); setRooms(json); setIsLoading(false); }; useEffect(() => { fetchRooms(); }, []); return ( <Grid mt={10} px={{ base: 10, // 모바일 버전 lg: 40, // 큰 화면 버전 }} columnGap={4} rowGap={8} templateColumns={{ // 화면 크기별 레이아웃 형태 (반응형으로 만들기) sm: "1fr", md: "1fr 1fr", lg: "repeat(3, 1fr)", xl: "repeat(4, 1fr)", "2xl": "repeat(5, 1fr)", }} > {isLoading ? ( <> <RoomSkeleton /> <RoomSkeleton /> <RoomSkeleton /> <RoomSkeleton /> <RoomSkeleton /> <RoomSkeleton /> <RoomSkeleton /> <RoomSkeleton /> <RoomSkeleton /> <RoomSkeleton /> </> ) : null} {rooms.map((room) => ( <Room // imageUrl={room.photos[0].file} imageUrl={ room.photos[0]?.file ?? `https://source.unsplash.com/random/450x$` } name={room.name} rating={room.rating} city={room.city} country={room.country} price={room.price} /> ))} </Grid> ); }
하지만 계속 이런 식으로 통신하기에는 반복적인 부분이 많고 fetch해오는 api 등 데이터가 많아지면 이 방법은 비효율적일 수 있다.
그래서 앞으로 사용할 것이 React Query이다.
LIST'JavaScript > React' 카테고리의 다른 글
[React] React에서 axios로 API 호출하기 (0) 2023.01.27 [React] React Query | TanStack Query (0) 2023.01.26 [ReactJS] 리액트 라우터 v6.4 (2) 2023.01.18 [ReactJS] 라우터 환경설정 _트위터 클론코딩 (0) 2022.11.26 [ReactJS] firebase _트위터 클론코딩 (0) 2022.11.26