[나만의 친환경 - 게시글 목록페이지] Axios-API통신 CRUD

lee·2024년 2월 22일
0
post-thumbnail

게시글 목록페이지에는 검색기능, 좋아요/북마크 버튼, 페이지네이션, 커뮤니티 목록 4곳에 api통신이 필요했다.
이번 게시글은 다시 상기하고 axios를 어떻게 사용했었는지 정리해볼려고 한다.

Axios

1. axios 선택한 이유

  • Node.js와 브라우저를 위한 Promise 기반 HTTP 비동기 통신 라이브러리
  • 비동기로 HTTP통신을 가능하게 해주고, REST API에 데이터를 요청할 때, promise 객체로 return을 해주기 때문에 response 데이터를 다루기 쉽다.
  • 요청(Request)와 응답(reply)을 JSON형태로 자동 변경해주어 편리.

📌 알아가기 : REST API란?

  • REST(Representational State Transfer)의 약자로 자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것을 의미합니다.
  • 웹 서비스 간의 통신을 위한 아키텍처 스타일입니다.
  • 즉 REST란
    1. HTTP URI(Uniform Resource Identifier)를 통해 자원(Resource)을 명시하고,
    2. HTTP Method(POST, GET, PUT, DELETE, PATCH 등)를 통해
    3. 해당 자원(URI)에 대한 CRUD Operation을 적용하는 것을 의미합니다.
  • CRUD Operation 란?
    Create : 데이터 생성(POST)
    Read : 데이터 조회(GET)
    Update : 데이터 수정(PUT, PATCH)
    Delete : 데이터 삭제(DELETE)
  • 정리 : REST API는 클라이언트와 서버 간의 통신을 위한 아키텍처 스타일로, 규칙과 규약을 정의합니다. 이는 HTTP 프로토콜을 기반으로 하며, HTTP 메소드를 사용하여 CRUD(Create, Read, Update, Delete) 작업을 수행한다.
    또한 REST API는 상태를 유지하지 않는 Stateless 특성을 가지고 있습니다. 이는 각각의 요청이 서로 독립적이며 이전 요청에서의 상태나 컨텍스트를 서버가 저장하지 않는다는 것을 의미한다.

📌 알아가기 : Promise 객체란?

  • js에서 제공하는 비동기를 간편하게 처리할 수 있게 도와주는 객체
  • Promise는 대기와 성공과 실패가 있다.
    - 대기(pending): 이행하지도, 거부하지도 않은 초기 상태.
    - 이행(fulfilled): 연산이 성공적으로 완료됨.
    - 거부(rejected): 연산이 실패함.
  • 반환된 값은 직접 접근할 수 없고 .then, .catch, .finally의 메서드를 사용해야 접근이 가능합니다.

📌 알아가기 : 동기(sync)&비동기(async)/blocking&non-blocking 란?

  • 동기(sync) vs 비동기(async) : 처리해야 할 작업들에 대한 처리과정.
    1. 동기 :
    - 작업 A의 종료시간과 작업 B의 시작시간이 같으면 동기적이라 한다.
    - 이전 작업의 실행이 끝나야 다음 작업 실행 시작
    => ex) 은행 업무 처리방식 - 손님요청 끝나야 다음 손님
    2. 비동기 :
    - 동기와 반대로 대상이 작업시간기 같지 않을 때 비동기적이라고 본다.
    - 이전 작업의 실행과 무관하게 바로 다음 작업 실행
    => ex) 카페에서 손님 받는 방식 - 손님요청하면 커피만들면서 다음 손님요청받고 다시 바로 실행

  • 블로킹(Blocking) vs 논블로킹(Non-Blocking) :
    전체적인 작업의 흐름 자체를 막냐 안막냐로 구분 할 수 있다.
    1. 블로킹 :
    - 직접 제어할 수 없는 작업이 끝날 때까지 기다려야 하는 경우.
    - A함수가 B함수를 호출 할때 B함수에게 제어권을 넘겨 B함수가 끝날때까지 A함수는 작업을 실행할 수 없음.
    2. 논블로킹 :
    - 직접 제어할 수 없는 작업이 완료되기 전에 제어권을 넘겨주는 경우.
    - A함수가 B함수를 호출 하지만 제어권을 A함수가 그대로 가지고 있어 계속 A함수가 실행됨.

📌 알아가기 : 동기와 비동기 그리고 블로킹과 논블로킹 상황알아보기

1. 동기이면서 블로킹(sync/blocking)
- 다른 작업이 진행되는 동안 자신의 작업을 처리하지 않고(blocking), 다른 작업의 완료 여부를 바로 받아 순차적으로 처리하는(sync) 방식이다.
- 다른 작업의 결과가 자신의 작업에 영향을 주는 경우 활용 가능.
- 기본적으로 자바스크립트 코드는 동기적이면서 블로킹하다고 생각한다.
2. 동기이면서 논블로킹(sync/Non-Blocking)
- 다른 작업이 진행되는 동안에도 자신의 작업을 처리하고(non-blocking), 다른 작업의 결과를 바로 처리하여 작업을 순차대로 수행 하는(sync) 방식이다.
- 자바스크립트로 예를 들으면 async/await 등 api요청을 할 때 비동기-논블로킹 방식을 동기-논블로킹 방식으로 바꿔주는 기법이다. (하지만 내부적으로는 여전히 비동기-논블로킹 방식임을 기억하자)
- 활용예시 : 로딩바 => 로딩바가 채워진다는 것은 백그라운드(다른 곳)에서 무엇인가 이뤄지고 있고 그것을 보여주는 방식이기에 결국 제어권은 아직 나한테 있기에 계속해서 조회를 하는 것이다.

📍여기서 잠깐 : 그럼 동기-블로킹, 동기-논블로킹 결국 순차적으로 진행이 되니깐 차이가 없는 것 아니냐?
답 : 아니다. 성능과 상황에 따라 다르겠지만 보통은 동기-논블로킹 방식을 어떻게 구현하냐에 따라 더 효율적으로 작업이 처리 가능함.
(파일을 다운로드 받으면서 유튜브나 웹서핑 등 멀티 태스킹 가능함 - 제어권을 내가 가지고 있기 때문에)

3. 비동기이면서 논블로킹(async/Non-Blocking)
- 다른 작업이 진행되는 동안에도 자신의 작업을 처리하고(non-blocking), 다른 작업의 결과를 바로 처리하지 않아 작업 순서가 지켜지지 않는(async)방식이다.
- 다른 작업의 결과가 자신의 작업에 영향을 주지 않은 경우에 활욜할 수 있다.
- 보통 비동기 작업은 거의 논블로킹이라고 생각한다. 위에 설명한 async/await 또한 비동기-논블로킹이지만 동기적이게 보이게한 기법이라고 설명했다 하지만 실질적인 동작은 비동기이면서 논블로킹이라고 할 수 있다.(.then과 동일하게 작동한다는 것이 증거)
- 타이머 함수도 예를 들 수 있다.
4. 비동기이면서 블로킹(async/blocking)
- 다른 작업이 진행되는 동안 자신의 작업을 멈추고 기다리는(blocking), 다른 작업의 결과를 바로 처리하지 않고 순서대로 작업을 수행하지 않는(async)방식이다.
- 거의 다룰일이 없음
- 하지만 node.js + MySQL 조합에서는 사용이 되는데 백엔드 쪽이라... 패스~

정리

블로킹, 동기
f(a) // 완료 시 반환
f(b) // 완료 시 반환

논블로킹, 동기
f(a) // 바로 반환
f(b) // 바로 반환
// a,b 순서대로 완료 통지 받음

논블로킹, 비동기
f(a) // 바로 반환
f(b) // 바로 반환
// a,b 완료 순서 보장되지 않음

2. Ajax란 무엇인가? Axios와 차이점은?

Ajax(Asynchronous JavaScript and XMLHttpRequest)는 웹 페이지의 전체 리로드 없이 서버와 비동기적으로 데이터를 교환할 수 있는 기술이다. 주로 XMLHttpRequest객체를 사용한다.

하지만 요즘에는 Promise객체를 사용하게 되고 그것을 도와주는 것이 Fetch API 혹은 Axios 라이브러리가 있는 것이다.
Axios는 Ajax 통신을 도와주는 외부 라이브러리 인것이다.

3. 설치 & 사용하기

npm i axios

대표적으로 쓰이는 method

GET : axios.get(url[, config])
POST : axios.post(url, data[, config])
PUT : axios.put(url, data[, config])
DELETE : axios.delete(url[, config])

1. axios Instance 만들기

이번 프로젝트에서 팀 프로젝트이다 보니 범용적으로 사용하기 좋은 axios를 사용하자고 말을 하였고, 팀원들이 좋다고 하여 axios로 진행을 하였다.

1단계

  • Instance를 만들면 좋은 점은 baseURL을 지정하여 매 요청마다 굳이 모든 url주소를 적는 것이 아닌 필요한 엔드포인트만 추가해주면 되어 편리했다.
  • Content-Type, Access-Control-Allow-Origin 등 헤더옵션을 headers에 따로 담아 보낼 수도 있다. 우리 프로젝트에선 사용하지 않았다.

2단계
밑에 사진에는 2단계 부분이 잘 안적혀 있지만, 추후 공부를 통해 알게된 사용방법은 요청과, 응답을 인터셉터를 할 수 있다.

  • 요청 : 요청을 인터셉터할때는 로그인 여부를 파악하는 토큰등을 담아 요청을 보낼 수 있다.
  • 응답 : 응답또한 특정 에러코드가 반환되면 그 코드에 맞게 에러 처리가 가능하다. ( ex. 액세스토큰 시간 끝나면 리프레쉬 토큰으로 다시 요청하기 등)

1. 게시글 목록페이지

- 검색기능

// /api/axios
import axios from "axios";
import { request } from "./create";

// 목록페이지 데이터 get요청
export const listData = async (
   curPage: number,
   memberId: string,
   cate?: string,
   title?: string,
   content?: string,
   tag?: string
) => {
   try {
      const { data } = await request.get(
         `boards${memberId}?page=${curPage}${cate}${title}${content}${tag}`
      );
      return data;
   } catch (error) {
      throw error;
   }
};

axios를 사용하여 instance를 만든 request를 import하고 axios도 import하여 모듈을 불러온다.
그후 async/await을 통하여 데이터를 받아오고 리턴해준다.

보면 get메소드 뒤에 baseUrl을 안적어주고 엔드포인트만 넘겨준것을 볼 수 있는데 instance를 만들었기 때문에 가능한 것이다.

// ListSearch 컴포넌트로 프롬내려주는 함수 (검색 get요청)
   const searchSubmitHandler = async () => {
      let data;
      if (cate === undefined) {
         if (title === "제목") {
            data = await listData(
               curPage,
               `/${memberId}`,
               ``,
               `&title=${search}`,
               "",
               ""
            );
         }
         if (title === "내용") {
            data = await listData(
               curPage,
               `/${memberId}`,
               "",
               "",
               `&content=${search}`,
               ""
            );
         }
         if (title === "제목+내용") {
            data = await listData(
               curPage,
               `/${memberId}`,
               "",
               `&title=${search}&`,
               `content=${search}`,
               ""
            );
         }
         if (title === "태그") {
            data = await listData(
               curPage,
               `/${memberId}`,
               "",
               ``,
               ``,
               `&tag=${search}`
            );
         }
      } else {
         if (title === "제목") {
            data = await listData(
               curPage,
               `/${memberId}`,
               `&cate=${cate}&`,
               `title=${search}`,
               "",
               ""
            );
         }
         if (title === "내용") {
            data = await listData(
               curPage,
               `/${memberId}`,
               `&cate=${cate}&`,
               "",
               `content=${search}`,
               ""
            );
         }
         if (title === "제목+내용") {
            data = await listData(
               curPage,
               `/${memberId}`,
               `&cate=${cate}&`,
               `title=${search}&`,
               `content=${search}`,
               ""
            );
         }
      }
      // 검색하면 새로운 데이터가 담길 수 있게함
      setDatas(data.data);
      setPageInfo(data.pageInfo);
      setSearch("");
   };

위 코드를 다시 보니깐... 너무 길고 가독성도 안좋은듯 싶다.

const searchSubmitHandler = async () => {
  let requestData = {
    curPage: curPage,
    memberId: `/${memberId}`,
    cate: cate ? `&cate=${cate}` : "",
    title: "",
    content: "",
    tag: "",
  };

  if (title === "제목") {
    requestData.title = `&title=${search}`;
  } else if (title === "내용") {
    requestData.content = `&content=${search}`;
  } else if (title === "제목+내용") {
    requestData.title = `&title=${search}`;
    requestData.content = `&content=${search}`;
  } else if (title === "태그") {
    requestData.tag = `&tag=${search}`;
  }

  const data = await listData(`boards${requestData.memberId}?page=${requestData.curPage}${requestData.cate}${requestData.title}${requestData.content}${requestData.tag}`);

  setDatas(data.data);
  setPageInfo(data.pageInfo);
  setSearch("");
};

위 코드대로 수정을 해보았는데 서버 에러로 제대로 동작이 될지 싶지만 좀더 코드가 보기 좋아진거 같다.

참고

rest api란
inpa블로그 동기/비동기,블로킹/논블로킹 정리
비동기와 논블로킹 블로그
인파-axios설치 사용법
api config 설명 블로그

profile
초보 코딩

0개의 댓글