[JS] Vanilla JS로 To-do 사이트 만들 때, API 연동하기(fetch 방식)

녕녕·2023년 5월 24일
0

JavaScript🍰

목록 보기
4/6
post-thumbnail

Rest API를 사용하여 CRUD를 구현하여 To-do 사이트를 만들었다. API를 어떻게 연동했는지 적어두려고 한다.

🐾 API util 함수 만들기

API가 여러 개이다. 기능을 구현하는 파일에 같이 넣어두기보다, API만 모아둔 파일을 따로 만들어 가독성을 높였다. APIs.js를 살펴보려고 한다.

📌 상수와 보안

// APIs.js

import { TODO_KEY } from "./APIkey.js";

const APIKEY = TODO_KEY;
const USERNAME = "HongGildong";
const HEADERS = {
  "content-type": "application/json",
  APIKEY: APIKEY,
  username: USERNAME,
};

const APIURL = "https://example.com/api/todos";

서버로 전송해야할 일정한 값들을 상수로 지정해뒀다. 특히 KEY의 경우는 노출되면 보안상 좋지 않으므로, 따로 적어뒀다. 리팩토링을 하지 않았는데, 노출되면 안되는 KEY 등은 .env 파일을 만들어 그 안에 적으면 더 좋겠다.

📌 서버 통신, 비동기

//get
export async function getServerTodos() {
  try {
    const res = await fetch(APIURL, {
      method: "GET",
      headers: HEADERS,
    });
    const json = await res.json();
    return json;
  } catch (error) {
    console.log(error);
  }
}

상수를 통해 기본적인 설정을 해뒀으니, 서버에 등록된 To-do를 가져오는 getServerTodos 함수를 만든다. fetchasync/await을 통해 가져온다. 두가지는 아래와 같은 역할을 한다.

fetch
JavaScript에서 서버로 네트워크 요청을 보내고 응답을 받을 수 있도록 해주는 메서드이다. 첫번째 인자로는 요청을 보낼 url을 입력하고, 두번째 인자로는 선택적으로 options을 넘겨줄 수 있다. 반환값으로는 Promise를 반환한다.

async await
자바스크립트의 비동기 처리 패턴 중 하나이다.

즉, fetch로 서버와 통신하여 서버의 데이터를 가져오거나 서버로 데이터를 전송하며 그때마다 request값을 주거나 reponse값을 받을 수 있다. 이 과정을 비동기로 처리하기 위해 async/await을 사용하고, 값을 res에 할당한다. try/catch를 써서 에러가 나면 console에 에러문구를 표시하도록 처리해준다.

📌 API 메서드와 파라미터

메서드와 파라미터는 서버에서 설계한 API 명세대로 작성하면 된다. 일반적으로 많이 사용하는 GET(조회), POST(추가), PUT(변경), PATCH(일부 변경), DELETE(삭제)가 있다. 원칙대로 설계했다면 API의 역할에 맞게 메서드를 쓰게 될 것이다.

//add
export async function addServerTodos(title, order) {
  try {
    const res = await fetch(APIURL, {
      method: "POST",
      headers: HEADERS,
      body: JSON.stringify({
        title: title,
        order: order,
      }),
    });
    const json = await res.json();
    return json;
  } catch (error) {
    console.log(error);
  }
}

위에서 To-do를 가져오는 API를 사용할 때는 method GET을 썼는데, 추가하는 API를 사용할 때는 method POST를 쓰도록 했다. 서버로부터 데이터를 가져오는 것이 아니라 추가하는 것이므로, 값을 전달해야 한다. 설계자가 짠대로 하면 된다.request body 파라미터에 값을 담아 전달한다. 이때 JS의 객체를 JSON 문자열로 변환하는 JSON.stringify를 사용한다. 서버와 클라이언트 간에 데이터를 주고받을 때, 데이터의 일관성을 유지하기 위해 JSON 형식을 사용한다.

//edit
export async function editServerTodos(id, title, done = false, order = 0) {
  try {
    const res = await fetch(`${APIURL}/${id}`, {
      method: "PUT",
      headers: HEADERS,
      body: JSON.stringify({
        title: title,
        done: done,
        order: order,
      }),
    });
    const json = await res.json();
    return json;
  } catch (error) {
    console.log(error);
  }
}

//delete
export async function deleteServerTodos(id) {
  try {
    const res = await fetch(`${APIURL}/${id}`, {
      method: "DELETE",
      headers: HEADERS,
    });
    const json = await res.json();
    return json;
  } catch (error) {
    console.log(error);
  }
}

수정과 삭제 API 함수는 path 파라미터와 request body 파라미터를 모두 사용하여 값을 전달했다. 이 것도 API 명세에 따라 값을 전달해주면 된다.

🐾 기능 구현할 때 API 사용하기

import { getServerTodos, addServerTodos, editServerTodos, deleteServerTodos } from './APIs.js';

만들어 둔 API 함수들을 모두 가져온다.

// 조회
let getData = await getServerTodos();

// 추가
formEl.addEventListener('submit', async (e) => {
  e.preventDefault();
  생략...
  let getData = await addServerTodos(newTitle);
  생략...
});
  
// 수정
async function editCompleted(e, text, done) {
  const li = e.target.closest('li');
  const getEditData = await editServerTodos(li.id, text, done);
  li.remove();
  생략...
}
  
// 삭제
async function deleteHandler(e) {
  생략...
  const li = e.target.parentElement;
  li.remove();
  await deleteServerTodos(li.id);
  생략...
}

적재적소에 써준다.

profile
FE Developer | 차근차근

0개의 댓글