connecting dots

Beginner 17회차 (8/27) | json-server, HMR (Hot Module Replacement), Tanstack Query 본문

Live Class/Beginner

Beginner 17회차 (8/27) | json-server, HMR (Hot Module Replacement), Tanstack Query

dearsuhyun 2024. 8. 28. 10:03

json-server

npm i -D json-server concurrently

// json-server랑 vite 서버 동시에 켜기 위해서 concurrently

 

pakage.json

"scripts": {
    "watch:json-server": "json-server db.json --port 1234",
    // db.json 파일을 실행
    "watch:vite": "vite",
    "dev": "concurrently npm:watch:*",

 

db.json

데이터 베이스 직접 만들기

{
  "todos": [
    {
      "id": "abc",
      "title": "hello world",
      "done": false
    }
  ],
  "users": [],
  "posts": []
}

 

main.tsx

// 즉시 실행 함수
(async () => {
  // 기본값 = GET
  const res = await fetch("http://localhost:1234/todos");
  const data = await res.json();
  console.log(data);
})();

 

npm run dev 하면 콘솔에 이렇게 내가 만든 데이터가 뜬다

 

요청 메소드

  • GET 조회 (read) default,  body 부분을 첨부할 수 없음 (안하는게 아니라 못함)
  • POST 생성 (create)
  • PUT 전체 수정 (update)
  • PATCH 일부 수정 (json-server에서는 일부 수정으로 사용 ! api 마다 다름)
  • DELETE 삭제 (delete)

RESTful 하다 --> CRUD의 쓰임에 맞게 api를 사용한다

 

json-server 사용 실습

POST

// 즉시 실행 함수
(async () => {
  // 기본값 = GET
  const res = await fetch("http://localhost:1234/todos", {
    method: "POST",
    body: JSON.stringify({
      title: "아침 먹기",
      done: true,
    }),
  });
  const data = await res.json();
  console.log(data);
})();

 

PATCH

 

 

GET

// 즉시 실행 함수
(async () => {
  // 기본값 = GET
  const res = await fetch("http://localhost:1234/users", {
    method: "GET",
  });
  const data = await res.json();
  console.log(data);
})();

 

 

60세 이하만 가져오고 싶다면 ?

쿼리스트링 사용

 

 

range

2~3번째 데이터만 가지고 오고 싶으면 ?

쿼리스트링 사용, start/end

zerobased numbering 사용 (slice method랑 같음)

 

가져올 데이터의 갯수를 제한하고 싶으면 ?

쿼리스트링 사용, start/limit

 

 

pagination

"posts": [
    { "id": "a", "title": "A" },
    { "id": "b", "title": "B" },
    { "id": "c", "title": "C" },
    { "id": "d", "title": "D" },
    { "id": "e", "title": "E" },
    { "id": "f", "title": "F" },
    { "id": "g", "title": "G" },
    { "id": "h", "title": "H" },
    { "id": "i", "title": "I" },
    { "id": "j", "title": "J" },
    { "id": "k", "title": "K" },
    { "id": "l", "title": "L" },
    { "id": "m", "title": "M" },
    { "id": "n", "title": "N" },
    { "id": "o", "title": "O" },
    { "id": "p", "title": "P" },
    { "id": "q", "title": "Q" },
    { "id": "r", "title": "R" },
    { "id": "s", "title": "S" },
    { "id": "t", "title": "T" },
    { "id": "u", "title": "U" },
    { "id": "v", "title": "V" },
    { "id": "w", "title": "W" },
    { "id": "x", "title": "X" },
    { "id": "y", "title": "Y" },
    { "id": "z", "title": "Z" }
  ]

 

sort

나이순으로 정렬을 하고 싶다면 ?

나이가 어린 순서대로 정렬되어서 출력되는 모습

 

DELETE

 

NoSQL

  • 데이터 베이스: {todos, users}
  • collection: todos, users 각각
  • document: {id, title, done}
  • field: todos안에 id, title, done 속성
  • todos의 스키마: id, title, done

 

users의 스키마(Schema) = id, name, age !

마지막 배열은 users의 스키마에 맞지 않기 때문에 사용 불가 (NoSQL은 물리적으로는 넣을 수 있지만 넣으면 안됨 !)

특히 POST로 생성할 때 잘 생성해야 함 !

 

age속성 없는 것은 가능하지만 웬만하면 null로 넣어주기

json에는 undefined랑 함수 못 씀 !

"age": null

// null: 아무것도 아니야, 명시적
// undefined: 아무것도 아니야, 암시적(자동으로 들어가짐)

HMR (Hot Module Replacement)

코드 작성한 것을 저장하면 바로바로 화면에 반영해주는 것

 

JSON.stringify

문자화 !

 

zustand 적용

import { create } from "zustand";
import { combine } from "zustand/middleware";

interface User {
  name: string;
  age: number;
  id: string;
}

export const useUsersStore = create(
  combine(
    {
      users: [],
    },
    (set) => {
      return {
        fetchUsers: async () => {
          const res = await fetch("http://localhost:1234/users");
          const users = await res.json();
          set({
            users, // users:users
          });
        },
        // Omit<User, 'id'>: User에서 id를 제외한 타입
        addUser: async (user: Omit<User, "id">) => {
          await fetch("http://localhost:1234/users", {
            method: "POST",
            body: JSON.stringify(user),
          });
          fetchUsers();
        },
        updateUser: async (user: User) => {
          await fetch(`http://localhost:1234/users/${user.id}`, {
            method: "PUT",
            body: JSON.stringify(user),
          })
          // 목록 갱신
          1. fetchUsers();
          2. set(state => ({
            users: state.users.map(u => u.id === updatedUser.id ? updatedUser : u) // OK!
            // users: state.users.map(u => u.id === user.id ? user : u) // OK!
          }))
        },
        deleteUser: async (user: User) => {
          await fetch(`http://localhost:1234/users/${user.id}`, {
            method: "DELETE",
            // 삭제하는거니까 body 필요 없음
          });
          set((state) => ({
            users: state.users.filter(
              (userItem: User) => userItem.id !== user.id
            ),
            // userItem = state.users 배열 내의 각 사용자 객체
            // userItem의 id가 삭제하려는 user의 id와 다른지를 확인
            // 다르면 남겨두고, 같으면 삭제됨
          }));
        },
      };
    }
  )
);
function fetchUsers() {
  throw new Error("Function not implemented.");
}

 

문자 데이터

  • ""
  • ''
  • ``

""와 ''중 하나만 사용하기

// 데이터 보간
const fruit = '사과'
const paragraph = `나는 ${fruit}를 좋아해요`

 

Tanstack Query

@tanstack/react-queryReact Query의 최신 버전으로, 비동기 데이터 관리를 효율적으로 할 수 있게 도와주는 라이브러리입니다. React Query는 서버 상태를 관리하는 데 특화된 도구로, 특히 API 요청을 다루는 데 강력한 기능을 제공합니다.

npm i @tanstack/react-query

 

App.tsx

 

주요 부분 설명
1. useQuery 훅:
useQuery는 @tanstack/react-query에서 제공하는 훅으로, 서버에서 데이터를 가져오고, 이를 상태로 관리하는 기능을 제공합니다.
훅은 API 요청, 데이터 캐싱, 로딩 및 에러 상태 관리 등 복잡한 비동기 작업을 간편하게 처리할 수 있게 해줍니다.

2. queryKey:
queryKey: ["users", "get"]는 이 쿼리를 고유하게 식별하는 키입니다.
이 키를 통해 React Query는 이 쿼리를 캐싱하고, 상태를 관리하며, 필요시 데이터를 새로 가져옵니다.

복합적인 배열 형태로 사용하여, 특정 리소스와 관련된 여러 쿼리를 명확하게 구분할 수 있습니다.

3. queryFn:
queryFn은 데이터를 가져오는 비동기 함수입니다. 이 함수는 실제로 서버에 요청을 보내고, 결과를 JSON 형태로 변환하여 반환합니다.
여기서는 fetch API를 사용해 GET 요청을 보내고, 사용자 데이터를 받아옵니다.

4. staleTime:
staleTime: 1000 * 10은 데이터가 신선한 상태로 간주되는 시간을 정의합니다. 이 경우 10초(1000ms * 10) 동안은 데이터를 다시 가져오지 않고 캐시된 데이터를 사용합니다.
이 시간 동안 동일한 쿼리가 다시 호출되면, 네트워크 요청 없이 캐시된 데이터를 바로 사용할 수 있습니다.

 

main.tsx


* 화상 회의 자주하는 게 좋음

* 스크럼 회의
목표 설정 --> 문서화 (기본적으로 지켜줘야 함, 일정 관리를 위해)

* 프로젝트에서 zustand 사용법
강의 3번째 시간에 설명해주시니 그거 보고 설정하기

 

code . -r
// Visual Studio Code를 현재 디렉토리에서 실행하는 명령어
code .
// 현재 경로 폴더를 새로운 vs 코드 창으로 열어주세요

mkdir vite-project2
// vite-project2라는 이름의 새 디렉토리를 만듭니다

cd vite-project2
//vite-project2 디렉토리로 이동합니다.

npm create vite@latest .
// 현재 디렉토리에 최신 버전의 Vite 프로젝트를 생성합니다.

 

https://github.com/typicode/json-server

 

GitHub - typicode/json-server: Get a full fake REST API with zero coding in less than 30 seconds (seriously)

Get a full fake REST API with zero coding in less than 30 seconds (seriously) - typicode/json-server

github.com

 

반응형