상세 컨텐츠

본문 제목

[리액트] 리액트에서 서버와 통신하려면 ajax 1

리액트

by front-hyun 2023. 8. 31. 10:18

본문

서버란?

서버: 부탁하면 진짜로 들어주는 프로그램

 

유저가 데이터달라고 요청을 하면 데이터를 보내주는 간단한 프로그램일 뿐입니다.

네이버웹툰 서버 : 유저가 웹툰 달라고 하면 웹툰 보내주는 프로그램

유튜브 서버 : 유저가 영상 달라고 하면 영상 보내주는 프로그램

입니다. 

그래서 서버개발 별거아님

"누가 A를 요청하면 A를 보내주세요" 라고 코드짜는게 서버개발 끝입니다. 

 

 

 

유저가 그냥 데이터달라고 떼쓰면 서버가 보내주진 않습니다.

서버에 데이터를 요청할 때는 정확한 규격에 맞춰서 요청해야하는데 

1. 어떤 데이터인지 (URL 형식으로) - 서버만든 사람에게 물어보면 됩니다!!

2. 어떤 방법으로 요청할지 (GET or POST)

잘 기재해야 데이터를 보내줍니다. 

네이버서버야 웹툰 좀 보내줘라 그 URL에 있는 웹툰 보내줘
네이버 서버야 그 URL에 글 좀 보내주라. 내가 쓴 글을 거기로 보내줘

 

데이터를 가져올 때는 보통 GET 고르면 되고 (서버에서 가져오기.. 유튜브 영상 등)

데이터를 서버로 보낼 때는 POST 고르면 됩니다. (네이버 글 등 전달)

그리고 어떤 데이터를 보고싶은지 URL만 잘 기재하면 되는데 

 

예를 들어서 쇼미더럭키짱이라는 네이버웹툰을 보고싶으면

https://comic.naver.com/webtoon/list?titleId=783054 여기 URL로 GET요청하면 보내줍니다.

예를 들어서 독립일기라는 네이버웹툰을 보고싶으면

https://comic.naver.com/webtoon/list?titleId=748105 여기 URL로 GET요청하면 보내줍니다.

URL을 어떻게 알았냐고요? 

네이버 웹툰 서버개발자에게 물어보거나 URL이 기재된 html 페이지를 찾아보거나 그러면 됩니다. 

 

 

 

누가 URL로 Get 요청하면 저에게 보내주세요~

누가 URL로 Post 요청하면 전달해주세요~

 

 

 

GET/POST 요청하는 법?

 

GET요청을 날리고 싶으면 가장 쉬운 방법은 브라우저 주소창입니다.

거기에 URL 아무거나 적으면 그 곳으로 GET요청을 날려줍니다.

진짠지 테스트해보셈 

브라우저 주소창에 서버 주소 입력했더니 상품 데이터 3개 줌

POST요청을 날리고 싶으면

<form action="요청할url" method="post"> 태그 이용하면 됩니다.

그럼 폼이 전송되었을 때 POST요청을 날려줍니다. 

근데 GET, POST 요청을 저렇게 날리면 단점이 뭐냐면 브라우저가 새로고침됩니다.

 

 

 

 

 

 

 

AJAX란? 

 

자바스크립트로 새로고침 없이 GET, POST 요청 할 수 있음 !

서버에 GET, POST 요청을 할 때 새로고침 없이 데이터를 주고받을 수 있게 도와주는

간단한 브라우저 기능을 AJAX라고 합니다. 

그거 쓰면 새로고침 없이도 쇼핑몰 상품을 더 가져올 수도 있고

새로고침 없이도 댓글을 서버로 전송할 수도 있고 

그런 기능을 만들 수 있는 것임 

 

AJAX로 GET/POST요청하려면 방법 3개 중 택1 하면 됩니다.

1. XMLHttpRequest라는 옛날 문법 쓰기

2. fetch() 라는 최신 문법 쓰기

3. axios 같은 외부 라이브러리 쓰기  -> 코드가 좀 더 짧아짐

3번이 가장 편하니 3번을 써봅시다. 

 

터미널 열어서 

npm install axios 

하면 설치 끝입니다.

 

 

 

 

 

AJAX 요청하는 법

 

버튼누르면 제가 만든 서버로 ajax 요청을 해봅시다.

https://codingapple1.github.io/shop/data2.json 이 URL로 GET요청을 하면 상품 3개를 가져와줍니다.(상품데이터 줌)

여기로 요청해봅시다. 

 

 

import axios from 'axios'

function App(){
  return (
    <button onClick={()=>{
      axios.get('https://codingapple1.github.io/shop/data2.json').then((결과)=>{
        console.log(결과.data)
      })
      .catch(()=>{
        console.log('실패함')
      })
    }}>버튼</button>
  )
}

1. axios를 쓰려면 상단에서 import해오고 - 이 페이지에서 axios 라이브러리 사용 가능해짐 !!

2. axios.get(URL) 이러면 그 URL로 GET요청이 됩니다.

3. 데이터 가져온 결과는 결과.data 안에 들어있습니다. 

 

그래서 위의 버튼 누르면 서버에서 가져온 데이터가 콘솔창에 출력됩니다. 

console.log(결과) -> 출력상태 등 자세한 정보까지 출력해줌
console.log(결과.data) -> 핵심 data만을 출력해줌

 

4. 인터넷이 안되거나 URL이 이상하면 실패하는데 

실패했을 때 실행할 코드는 .catch() 안에 적으면 됩니다.  => 예외처리

 

리액트에서는 거의 서버와 ajax를 사용해서 통신합니다. 

 

 

 

그래서 오늘의 숙제로

버튼을 누르면 서버에서 상품데이터 3개를 가져와서 

메인페이지에 상품카드 3개를 더 생성해봅시다. 

 

(팁) 리액트에선 html을 3개 더 생성해주세요~라고 코드짜지 않는다고 했습니다. 

state 조작하면 html 알아서 생성될걸요 

 

오늘의 숙제 : 

버튼을 누르면 서버에서 상품데이터 3개를 가져와서 메인페이지에 상품카드 3개를 더 생성해봅시다. 

https://codingapple1.github.io/shop/data2.json

여기로 GET요청하면 상품데이터를 3개 더 보내줍니다.

 

가져온 데이터를 shoes에 추가해주세요 ~

큰 array 안에 3개의 객체씩 있는 형태이다. 

복사본 먼저 만들기! [{}, {}, {}, {}, {}, {}] 이렇게 만들고 싶으면 밑에 나처럼 하면 안 되고 강의본처럼 괄호 벗기기를 한 곳에 모아두고 해야 한다!!

내 코드처럼 하면.. 각 버튼 누를 때마다 이미지 하나씩만 추가되고, 전체 3개 데이터 GET 해오지 못함

심심하면 이런 것들도 해봅시다.

 

응용1. 버튼을 2번 누르면 7,8,9번 상품을 가져와서 html로 보여주려면?

여기로 GET요청하면 7,8,9번 상품 줍니다. 

https://codingapple1.github.io/shop/data3.json

버튼을 몇번 눌렀는지 어디 변수나 state 같은 곳에 기록해둬도 되겠군요.

 

응용2. 버튼을 3번 누르면 더 상품이 없다고 안내문을 띄우려면?

아니면 버튼을 숨기거나 그래도 되겠군요.

 

응용3. 버튼을 누른 직후엔 "로딩중입니다" 이런 글자를 주변에 띄우고 싶으면?

그리고 요청이 성공하거나 실패하거나 그 후엔 "로딩중입니다" 글자를 제거해야합니다. 

 

import Container from 'react-bootstrap/Container';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar';
import './App.css';
import {useState} from "react";
import data from './data';
import {Routes, Route, Link, useNavigate, Outlet} from 'react-router-dom';
import Detail from './routes/Detail';
import axios from 'axios';

function App() {
  let [ment, setMent]=useState(true);
  let [click, setClick]=useState(0);
  let [shoes, setShoes]=useState(data);
let navigate = useNavigate();
  return (
    <div className="App">
      

            <Navbar bg="light" data-bs-theme="light">
        <Container>
          <Navbar.Brand href="#home">Navbar</Navbar.Brand>
          <Nav className="me-auto">
            <Nav.Link onClick={()=>{navigate('/')}}>Home</Nav.Link>
            <Nav.Link onClick={()=>{navigate('/detail')}}>Detail</Nav.Link>
          </Nav>
        </Container>
        
      </Navbar>

      <Routes>
<Route path='/' element={

<div>
<div className='main-bg'>
</div>

  <div className='container'>     
         <div className='row'>

{shoes.map((a, i)=>{
return(
  <Card shoes={a} i={i+1} ></Card>

)
})}
      </div>
      
</div>


<button onClick={()=>{
  setClick(click+1);
  setMent(true);
  if(ment===true){ <h4> 로딩중입니다.</h4>}

  if(click===1){axios.get('https://codingapple1.github.io/shop/data3.json')
  .then((result)=>{let copy=[...shoes, ...result.data];
  
    setShoes(copy);})
  setMent(false)
}
  if(click===2){ alert('더 이상 상품이 없습니다. ');
  setMent(false)
}
  if(click===0){
axios.get('https://codingapple1.github.io/shop/data2.json')
.then((result)=>{
  console.log(result.data)
  let copy=[...shoes, ...result.data];
  setShoes(copy);
  setMent(false)
})
.catch(()=>{console.log("실패함")})
  }

}}>버튼</button>

</div>}/>
  <Route path='/detail/:id' element={<Detail shoes={shoes}/>}/>
  <Route path='/event' element={<About/>}>
      <Route path='one' element={<div>첫주문</div>}></Route>
      <Route path='two' element={<div>생일기념 쿠폰</div>}></Route>
  </Route>

  <Route path='*' element={<div>없는 페이지임</div>}/>

</Routes>

    
    </div>
  );
}

export default App;

//신발 컴포넌트(반복적인 부분만 !!)
function Card(props){
  return(
  
        <div className="col-md-4">
        <img src={"https://codingapple1.github.io/shop/shoes"+props.i+".jpg"} style={{width:'80%'}}/>
          <h4>{props.shoes.title}</h4>
          <p>{props.shoes.price}</p> 
      </div>
      
  )
}

function About(){
  return(
    <div>
      <h4>오늘의 이벤트</h4>
      <Outlet></Outlet>
    </div>
  )
}

 

 

 

 

저번시간 숙제는

 

서버에서 데이터 가져와서 상품 html 3개 생성하라고 했는데

1. 서버에서 데이터 가져와주세요

2. html 3개 더 만들어주세요

이렇게 코드 2개만 짜면 되겠군요 근데 1번은 저번시간에 해서 2번만 짜면 숙제 끝임 

 

 

리액트에선 "html 3개 더 만들어주세요~" 이렇게 코드짜지 않습니다.

state 조작하면 알아서 html이 변경되도록 코드짠다고 했는데 

지금도 shoes.map() 덕분에 shoes에 들어있는 자료 갯수만큼 html이 자동으로 생성되고 있어서

여러분은 그냥 state만 조작하면 됩니다. 

"shoes라는 state에 자료 3개 추가해주세요~" 라고 코드짜면 html 알아서 3개 더 생성됩니다.

 

 

 

import axios from 'axios'

function App(){

  let [shoes, setShoes] = useState(어쩌구);
  return (
    <button onClick={()=>{
      axios.get('https://codingapple1.github.io/shop/data2.json').then((결과)=>{
        let copy = [...shoes, ...결과.data]
        setShoes(copy)
      })
      .catch(()=>{
        console.log('실패함')
      })
    }}>버튼</button>
  )
}

1. 점3개 이용해서 shoes의 사본을 만들었습니다.

근데 그 안에 ...결과.data 이것도 함께 뒤에 집어넣었습니다.

결과.data 출력해보면 [{4번상품}, {5번상품}, {6번상품}] 이게 나오기 때문에 ...결과.data 하면 { }, { }, { } 이것만 남을듯요 

2. 그 다음에 그걸 shoes라는 state에 추가했습니다. 

 

 

그럼 이제 버튼누르면 shoes라는 state는 

[{ }, { }, { }, { }, { }, { }]

이렇게 되어있을듯요

그럼 이거에 맞게 상품 html도 알아서 6개가 잘 생성됩니다. 

 

 

 

 

 

 

관련글 더보기