240612 TIL

웅웅·2024년 6월 13일

json-server

  아주 간단한 DB와 API 서버를 생성해주는 패키지이다. json-server는 주로 나와 같이 front-end를 공부하거나 백엔드에서 실제 DB와 서버가 완성되기 전 개발에 임시적으로 사용할 mock data를 생성하기 위해 쓰인다.

앞서 공부했던 Supabase와 Firebase는 백엔드가 없는 환경에서 실제 서비스 구축에 유용하지만 학습이 목적이거나, 실무와의 연관성을 고려하였을 때 json-server가 더 적합하다고 볼 수 있다.

설치

yarn add json-server
yarn add json-server -D # 개발 환경인 경우, -D 옵션을 함께 입력합니다.

생성

  설치가 완료되면 db.json 파일을 생성 후 사용할 data를 넣어준다.

{
  "todos": [
    {
      "id": "1",
      "title": "json-server"
    }
  ]
}

실행

  그 후 서버를 실행해주면 간단하게 json-server를 사용할 수 있다. 대략적으로 db.json 파일을 db로 정하고, 4000 포트에서 서버를 시작하겠다는 의미이다.

yarn json-server db.json --port 4000

axios

  node.js와 브라우저를 위한 Promise 기반 http 클라이언트 = http를 이용해서 서버와 통신하기 위해 사용하는 패키지. fetch의 기능과 유사하다.

//axios 설치
yarn add axios

(0) .env

  보통 API_KEY 또는 SERVER_URL과 같은 민감한 정보는 .env 파일에 숨긴다. Vite로 만든 프로젝트의 경우 아래처럼 관리할 수 있다.

# .env 파일
VITE_이름 = 123
VITE_EXAMPLE_SERVER_URL = http://localhost:4000
VITE_API_KEY = test1234
VITE_SECRET_KEY = abcdefg

// 사용 예시: src/main.js 또는 src/App.jsx 등
const apiKey = import.meta.env.VITE_API_KEY;
console.log('API Key:', apiKey);

  프로젝트를 깃으로 공유할 경우, 민감한 정보가 repository에 포함되지 않도록 아래처럼 .gitignore 파일을 작성해주어야 한다.

# .gitignore 파일
# Node.js 관련 파일
node_modules/

# 환경 설정 파일
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# 빌드 출력 파일
build/
dist/

# 기타
.DS_Store

(1) Get

  axios.get은 서버의 데이터를 조회할 때 사용한다.

const [todos, setTodos] = useState(null);
useEffect(() => {
    const fetchPost = async () => {
      try {
        const { data } = await axios.get(
          "http://localhost:4000/todos"
        );
        setTodos(data);
      } catch (error) {
        console.error("Error => ", error);
      }
    };

    fetchPost();
  }, []);

  아래는 공식문서에 나와 있는 전체 정보 혹은 상세 정보 url을 작성하는 예시이다.

(2) Post

  위의 예시에서 아래 코드를 추가한다. axios.post는 서버에 데이터를 추가할 때 사용한다. 사용 url과 추가하는 값을 인자로 넣어준다.

  const [todo, setTodo] = useState({
    title: "",
  });
  
  const onSubmitHandler = async (todo) => {
    const {data} = await axios.post("http://localhost:4000/todos", todo);
    setTodos([...todos, data]);
  }
  
  return (
    <div>

      <h3>axios 연습</h3>
      <form onSubmit={(e) => {
        //alert("submit");
        e.preventDefault();
        onSubmitHandler(todo);
      }}>
        <input
          type='text'
          onChange={(e) => {
            setTodo({ ...todo, title: e.target.value });
          }}
        />
        <button>추가하기</button>
      </form>

    </div>
  );

  json-server에서는 아이디가 string 타입으로 랜덤 생성되어 삽입된다. 따라서 위 예시처럼 title의 값을 넣어주면 아이디는 자동 생성되며, 이를 오류없이 화면에 출력하기 위해 response에 먼저 할당 후 setTodos를 해주어야 한다.

(3) Delete

  axios.delete는 서버의 데이터를 삭제할 때 사용한다. 아래 예시처럼 삭제할 값의 주소를 인자로 받는다.

  const onDeleteHandler = async (id) => {
    await axios.delete("http://localhost:4000/todos/" + id);
    setTodos(todos.filter((todo) => todo.id !== id));
  };

  return (
    <div>

      <h3>axios 연습</h3>
      <form onSubmit={(e) => {
        //alert("submit");
        e.preventDefault();
        onSubmitHandler(todo);
      }}>
        <input
          type='text'
          onChange={(e) => {
            setTodo({ ...todo, title: e.target.value });
          }}
        />
        <button>추가하기</button>
      </form>
      {
        todos?.map((todo) => {
          return (
            <div key={todo.id}>
              <span>{todo.title}</span> <button onClick={(e) => onDeleteHandler(todo.id)}>삭제</button>
            </div>
          );
        })
      }
    </div>
  );

(4) Patch
  axios.patch는 서버의 데이터를 일부 수정할 때 주로 사용한다. (put은 전체를 수정한다.) 아래 예시처럼 수정할 값의 주소와 함께, 수정할 내용을 인자로 받는다.

  const [targetId, setTargetId] = useState("");
  const [editTodo, setEditTodo] = useState({
    title: "",
  });
  
  const onEditHandler = async (targetId, editTodo) => {
    await axios.patch("http://localhost:4000/todos/" + targetId, editTodo);
    const newTodos = todos.map(todo => {
      if (todo.id === targetId) {
        return {
          ...todo,
          title: editTodo.title
        }
      }
      return todo
    });
    setTodos(newTodos)
  }

  return (
    <div>

      <h3>axios 연습</h3>
      <form onSubmit={(e) => {
        //alert("submit");
        e.preventDefault();
        onSubmitHandler(todo);
      }}>
        <div>
          <input
            type='text'
            placeholder='수정할 id'
            onChange={(e) => {
              setTargetId(e.target.value);
            }}
          />
          <input
            type='text'
            placeholder='수정할 내용'
            onChange={(e) => {
              setEditTodo({ ...editTodo, title: e.target.value });
            }}
          />
          <button
            type='button'
            onClick={() => onEditHandler(targetId, editTodo)}>
            수정하기
          </button>
        </div>
        <input
          type='text'
          onChange={(e) => {
            setTodo({ ...todo, title: e.target.value });
          }}
        />
        <button>추가하기</button>
      </form>
      {
        todos?.map((todo) => {
          return (
            <div key={todo.id}>
              <span>{todo.title}</span> <button onClick={(e) => onDeleteHandler(todo.id)}>삭제</button>
            </div>
          );
        })
      }
    </div>
  );
}

axios vs fetch

  둘은 모두 HTTP 요청(GET, POST …)을 처리하기 위한 JavaScript 라이브러리이다. 다만 axios는 아래와 같은 장점들을 가지고 있어 react에서는 axios를 더 선호하는 경우가 종종 있다.

(1) 기본 설정 및 인터셉터 지원

  axios는 기본 설정을 정의하고, 이를 통해 모든 요청에 공통 설정을 적용할 수 있다. 또한, 요청 또는 응답을 가로채서 전처리 또는 후처리할 수 있다. 이와 관련된 내용은 후에 추가적으로 공부해보자.

(2) 더 나은 오류 처리

  axios는 HTTP 상태 코드를 기준으로 한 일관된 오류 처리를 제공한다. fetch는 기본적으로 네트워크 오류만 catch 블록으로 전달되고, 4xx, 5xx 오류는 then 블록에서 처리한다.

(3) 구형 브라우저 지원

  axios는 구형 브라우저와의 호환성이 좋다.

(4) 간결한 문법

  axios는 간결하고 직관적인 문법을 제공하여 사용하기 쉽다.

0개의 댓글