필수 개념은 다음과 같다.
- [1-2] 비동기1 - 비동기, promise
- [1-5] json-server
- [1-6 ~ 1-7] axios의 GET, POST, DELETE, PATCH, fetch와의 비교
- [1-10] tanstack query 기본 사용법 (매우중요)
- [1-15] zustand 기본 사용법
- [1-20] 인증인가 개념 실습
- [1-21] tailwind
[1-2] 비동기, promise
< 동기와 비동기 개념 >
동기: 순차적으로 진행, 요청을 보내고 응답을 기다린다.
(ex 주문 후, 커피가 나올 때까지 기다려주세요! 다음사람들은 아직 주문 못한 상태로 기다리는중...)
비동기: 비순차적으로 진행, 요청을 보내고 응답을 기다리지 않고 바로 다음 작업을 진행한다.
(ex 주문 후, 진동벨이 울리면 커피를 가지러 오세요! 모든 사람들의 주문을 다 받고 음료 준비가 다 된 순서대로 줌)
Promise란?
promise는 비동기 작업의 완료 또는 실패를 처리하기 위해 사용되는 개념이다.
비동기 작업의 결과를 다루기 쉽게 하기 위해 만들어졌으며, 비동기 작업이 끝난 이후에 실행될 콜백 함수를 등록할 수 있는 메서드를 제공한다. promise 객체를 생성하기 위해 promise 생성자를 사용할 수 있다.
promise는 세 가지 상태를 가진다.
- Pending(대기): 초기 상태이다. 즉, 이행되거나 거부되지 않은 상태이다.
- Fulfilled(이행): 비동기 작업이 성공적으로 완료된 상태이다.
- Refected(거부): 비동기 작업이 실패한 상태이다.
promise 객체는 then, catch, finally 매서드를 통해 이행되거나 거부된 이후의 동작을 정의할 수 있다.
직접 promise 객체 만들기
const myPromise = new Promise((resolve, reject) => {
// 비동기 작업을 수행합니다.
if (/* 작업이 성공적으로 완료되면 */) {
resolve("성공 메시지");
} else {
reject("실패 메시지");
}
});
사용방법 포함
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
// 작업의 성공 여부를 나타내는 변수
// 여기를 true <-> false 변경해가며 테스트해보세요!
const success = true;
if (success) {
// resolve 함수는 Promise 객체의 상태를 이행(fulfilled) 상태로 변경해요.
// resolve 함수 자체는 반환값이 없어요.
// 다만, resolve 함수가 호출되면 그 값이 then 메서드의 callback 함수로 전달돼요.
resolve("작업이 성공적으로 완료되었습니다!");
} else {
// 마찬가지 원리로, reject 함수가 호출되면 그 값이 catch 메서드의 callback 함수로 전달돼요.
reject("작업이 실패했습니다.");
}
}, 2000); // 2초 후에 작업이 완료
});
myPromise
.then((result) => {
console.log(result); // "작업이 성공적으로 완료되었습니다!" 출력
})
.catch((error) => {
console.log(error); // "작업이 실패했습니다." 출력
});
본격적으로 알아보기!
// React 라이브러리에서 useState와 useEffect 훅을 가져옵니다.
// useState는 상태 관리를 위해, 기억하죠?
// useEffect는 컴포넌트의 생명주기 동안 특정 작업을 수행하기 위해!
import React, { useState, useEffect } from "react";
function App() {
// state 선언 및 초기화
// setMessage : 상태 업데이트 함수
// useState는 상태 변수와 그 변수를 업데이트하는 함수를 반환합니다.
// 즉, 좌측의 [state, setState] 구조는 useState의 결과물을 '구조분해할당'한 것이죠!
const [message, setMessage] = useState("타이머 시작");
// useEffect 훅을 사용하여 컴포넌트가 마운트되었을 때 실행될 효과를 정의
// 빈 배열 []을 두 번째 인자로 넘겨주어, 이 효과가 컴포넌트가 처음 렌더링 된 후 한 번만 실행
useEffect(() => {
// delay 함수 정의
// (1) delay 함수는 Promise 객체를 새로(new) 만들어 반환합니다.
// ** 여기서 Promise는 객체를 생성하기 위한 생성자입니다.
// (2) 만들어진 promise 객체는 주어진 밀리초(ms)만큼 동작을 지연시킵니다.
// (1) delay함수는 주어진 밀리초(ms)만큼 지연시키는 Promise를 반환합니다.
// (2) setTimeout을 사용하여 지정된 시간(ms) 후에 resolve를 호출합니다.
// (3) 따라서, 지정된 시간(ms) 후에 pending -> fulfilled로 상태가 바뀌어요.
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// (1) delay 함수를 호출하여 2000밀리초(2초) 동안 지연시킵니다.
// (2) delay 함수가 반환하는 Promise가 완료되면 then 메서드가 호출되고, 이 메서드 안의 콜백 함수가 실행됩니다.
// (3) 이 콜백 함수는 setMessage를 호출하여 message 상태를 "2초 후 메시지 변경"으로 업데이트합니다.
delay(2000).then(() => setMessage("2초 후 메시지 변경"));
}, []);
// 초기 상태는 "타이머 시작"이며, 2초 후에는 "2초 후 메시지 변경"으로 업데이트됩니다.
return (
<div>
<h1>{message}</h1>
</div>
);
}
export default App;
다른 쉬운 예시
const fetchData = new Promise((resolve, reject) => {
// 가상의 데이터 fetch
setTimeout(() => {
const data = { id: 1, name: "John" };
resolve(data); // 데이터와 함께 resolve 호출
}, 1000);
});
fetchData.then(data => console.log(data)); // { id: 1, name: "John" } 출력
promise의 구조: promise 생성자는 실행자 함수를 인자로 받는다. 이 실행자 함수는 두개의 인자를 받는다. resolve와 reject
new Promise((resolve, reject) => {
// 비동기 작업 수행
});
resolve의 역할
- resolve는 promise가 성공적으로 완료 되었음을 나타내는 함수
- resolve를 호출하면 promise의 상태가 'fullfilled(이행)'으로 변경됨.
- resolve에 전달된 값은 promise의 결과값이 됨.
then의 역할
- promise가 fullfilled(이행) 상태가 되면 then 에 등록된 콜백함수가 실행됨.
- promise의 결과값을 이 콜백함수의 인자로 전달
fetchData.then(data => console.log(data));
- data는 promise의 결과값이다.
실생활에서 사용 ⭐⭐⭐⭐⭐
useEffect(() => {
fetch("URL")
.then((response) => response.json())
.then((json) => console.log(json));
}, []);
- fetch 함수:
- fetch("URL")는 Promise를 반환한다.
- 이 Promise는 네트워크 요청이 완료되면 Response 객체로 이행(fulfill)된다.
- 첫 번째 .then():
- response.json()은 Response 객체의 본문을 JSON으로 파싱하는 메서드이다.
- 이 메서드도 Promise를 반환한다.
- 두 번째 .then():
- 파싱된 JSON 데이터를 받아 처리한다.
- 여기서는 단순히 콘솔에 로그를 출력한다.
이 코드의 Promise 체인을 단계별로 살펴보면:
- fetch("URL") Promise가 완료된다.
- 첫 번째 .then()이 실행되어 응답을 JSON으로 파싱한다.
- 두 번째 .then()이 실행되어 파싱된 JSON 데이터를 처리한다.
이 구조는 "Promise 체이닝"이라고 불립니다. 각 .then()은 이전 Promise의 결과를 받아 처리하고, 새로운 Promise를 반환한다.
[1-5] json-server
json-server란?
아주 간단한 DB와 API 서버를 생성해주는 패키지이다. 우리가 사용하는 이유는 백엔드에서 실제 DB와 API 서버가 구축될 때까지 프론트엔드 개발에 임시적으로 사용할 mock data를 생성하기 위함이다.
설치
yarn add json-server
yarn add json-server -D # 개발 환경인 경우, -D 옵션을 함께 입력합니다.
파일 생성
아래 이미지처럼 프로젝트 루트 경로에 db.json이라는 파일을 생성한다.
그리고 아래와 같이 내용을 입력한다. json-server는 이 내용을 바탕으로 데이터베이스를 제공하게 된다.
{
"todos": []
}
내가 추가하고 싶은 내용으로 수정한다.
{
"todos": [
{
"id": 1,
"title": "json-server",
"content": "json-server를 배워봅시다."
}
]
}
이렇게 작성했으면 내가 만든 API 서버가 잘 작동하고 있는지 확인해야한다.
먼저, 터미널에 아래의 코드를 입력한다. 이렇게 하면 4000번 포트에서 돌아가는 서버가 실행된다.
yarn json-server db.json --port 4000
그리고 브라우저에 http://localhost:4000/todos를 입력한다. 그러면 잘 작동하고 있는 것을 볼 수 있다.
'강의' 카테고리의 다른 글
비동기 및 json-server (0) | 2024.09.10 |
---|---|
리액트 심화 주차 필수 개념 정리(2) (1) | 2024.09.06 |
hover (1) | 2024.08.20 |
useEffect (0) | 2024.08.16 |
드디어 React (0) | 2024.08.08 |