동기와 비동기
리액트에서 async와 await를 알아보기 전에 동기와 비동기에 대해 알아봐야 한다. 동기는 API를 요청 응답하는데 있어서 하나의 응답이 끝난 이후에 요청이 들어가는 방식이다.
비동기는 동기와 달리 여러 일을 할 때 사용한다. 예를 들어 네이버의 경우 뉴스의 게시글 목록을 가져오는 동시에 상품 목록을 가져오는 경우에 해당한다. 스마트폰에서 게임을 다운로드하면서 카톡 하는 나의 모습이 비동기의 모습과 같다.
async와 await
rest-API나 graphql-API 를 사용해서 요청에 대한 응답으로 받은 객체(JSON)를 변수에 담아서 사용하는데 응답 결과를 변수에 담아서 사용하려면 통신이 완료될 때까지 기다려야 한다. 그때 사용하는 것이 async와 await이다.
// mutation에 동기식 처리
async function handleClickPost(){
const result = await createBoard({
variables: {
aaa: "훈이",
bbb: "1234",
ccc: "안녕하세요 훈이에요",
ddd: "반갑습니다"
}
})
// 결과물 확인하기
console.log(result)
}
return (
<button onClick={handleClickPost}>게시물 등록</button>
)
버튼을 눌렀을 때 onClick={hanleClickPost}에 의해 handleClickPost 함수가 실행되며 async와 await로 통신을 연결시켜준다.
동기 통신과 비동기 통신은 await의 유무에 따라 달라진다.
// 비동기 통신
async function 함수명() {
axios('API이름')// 서버에 요청하는 코드 (기다리지 않음)
}
// 동기 통신
async function 함수명() {
await axios('API이름') // 서버에 요청하는 코드 (기다림)
}
--------------------------------------------------------------------------------
// 화살표 함수의 경우
const 함수명 = async () => {
await // 서버에 요청하는 코드
}
동기와 비동기 방식에서 결과값은 달라진다. 비동기 통신의 경우는 Promise라는 값을 볼 수 있게 되고 동기 통신의 경우 우리가 원하는 객체(JSON)의 형식으로 볼 수 있게 된다.
// 비동기 통신
async function 함수이름(){
const data = axios.get('https://koreanjson.com/posts/1')
console.log(data) // Promise
// 동기 통신
async function 함수이름(){
const data = await axios.get('https://koreanjson.com/posts/1')
console.log(data) // {id:1, title:"정당의 목적이나 활동이...", ...}
}
실습사례
VSCODE에서 rest-API를 이용하여 JSON 데이터를 요청한다면 axios를 이용해야 하는데, axios를 다운로드한 뒤에 import를 진행하면 된다. rest-API의 사례를 살펴보면 아래와 같다.
import axios from "axios";
import { useState } from "react";
export default function restGet() {
const [aaa, setAaa] = useState("");
// async function zzz() {
// const result = await axios.get("https://koreanjson.com/posts/1");
// console.log(result.data.title);
// setAaa(result.data.title);
// }
// 화살표 함수
const zzz = async () => {
const result = await axios.get("https://koreanjson.com/posts/1");
console.log(result.data.title);
setAaa(result.data.title);
};
// function zzz() {
// console.log("어쩔티비");
// }
return (
<>
<button onClick={zzz}>Rest-API 요청하기!!!</button>
<div>{aaa}</div>
</>
);
}
//zzz는 이벤트핸들러 함수
//함수가 중복되면 에러발생할 수 있음. 막으려면 함수를 const로
state를 활용하여 버튼을 클릭했을 때 https://koreanjson.com/posts/1 API에 요청하여 해당 제목을 가져오게 된다.
주로 사용하게 될 graphql-API는 이와 다른데 먼저 _app.js에 import를 해줘야한다.
import "../styles/globals.css";
import { ApolloClient, InMemoryCache, ApolloProvider } from "@apollo/client";
function MyApp({ Component, pageProps }) {
const client = new ApolloClient({
uri: "api주소",
cache: new InMemoryCache(),
});
return (
<ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
);
}
export default MyApp;
그리고 index.js를 살펴보면 apollo/client를 통해서 useMutation, gql을 활용한다.
import { useMutation, gql } from "@apollo/client";
import { useState } from "react";
const CREATE_BOARD = gql`
mutation {
createBoard(
writer: "철수"
title: "제목입니다~"
contents: "내요이에요~~"
) {
_id
number
message
}
}
`;
export default function GraphqlMutation() {
const [aaa, setAaa] = useState("");
const [qqq] = useMutation(CREATE_BOARD);
const zzz = async () => {
// const result = await axios.get("https://koreanjson.com/posts/1");
const result = await qqq();
// console.log(result.data.title);
// setAaa(result.data.title);
console.log(result.data.createBoard.message);
setAaa(result.data.createBoard.message);
};
return (
<>
<button onClick={zzz}>Graphql-API 요청하기!!!</button>
<div>{aaa}</div>
</>
);
}
//zzz는 이벤트핸들러 함수
//함수가 중복되면 에러발생할 수 있음. 막으려면 함수를 const로
조회가 아닌 데이터를 생산/수정하는 것으로 query가 아닌 mutation으로 useMutation을 apollo/client에서 가져온다.
댓글