[React] React 로 kakao 책 검색 사이트 만들기

go·2021년 8월 23일
2

Project

목록 보기
1/4

🔍 Project Overview

Library는 책을 검색 후 장바구니에 추가하면 책의 개수와 가격을 계산해 주는 서비스입니다.

이번 프로젝트는 React.js와 카카오 검색 API 를 활용하여 간단한 프로젝트를 하나 만들어 보고자 시작하게 되었습니다.

Git hub 에서 프로젝트 데모 확인이 가능합니다.
Git hub 에서 소스 코드를 볼 수 있습니다.

💡 개발 기간, 인원

  • 2021.08 ~ 2021.08 (1인)

💡 사용기술

  • React.js
  • Styled-components

💡 API

🔍 구현 기능

  • 책 검색 기능 구현
  • 장바구니에 책 추가 기능, 수량 추가, 삭제 기능 구현
  • 책 수량에 따른 가격 측정 기능 구현


  • 이미지 hover 시 책 정보 나타나는 효과 구현

🔍 학습 내용

1. 카카오 API 사용하기

src/api.js

import axios from 'axios';

const Kakao = axios.create({
  baseURL: 'https://dapi.kakao.com', // 공통 요청 경로를 지정해준다.
  headers: {
    Authorization: 'KakaoAK {Kakao API Key}',
  },
});

// search book api
export const bookSearch = (params) => {
  return Kakao.get('/v3/search/book', { params });
};

{Kakao API Key} 에 자신이 카카오 에서 발급 받은, API 키를 넣어줍니다.

2. 책 검색 API 호출, 상태 관리하기

AppStateProvider에서 책 검색, 장바구니의 상태를 관리해줍니다.

bookSearchHttpHandler 함수의 인자값으로, 첫 번째는 변경된 query state이고, 두 번째는 리스트를 초기화 한 후 다시 랜더링 할 것인지의 true/false 입니다.

bookSearchHttpHandler에서 api를 호출한 후, 호출 한 데이터와 현재 books state를 병합해 줍니다.

Kakao 책 검색 API 링크를 통해 parameter를 참고할 수 있습니다.

const [books, setBooks] = useState([]);
const [query, setQuery] = useState('');

  // 책 검색
  useEffect(() => {
    if (query.length > 0) {
      bookSearchHttpHandler(query, true); // 컴포넌트 마운트 후에, 함수를 호출한다.
    }
  }, [query]);

  // book search 핸들러
  const bookSearchHttpHandler = async (query, reset) => {
    // Parameter 설정
    const params = {
      query: query,
      sort: 'accuracy', // accuracy | recency 정확도 or 최신
      page: 1, // 페이지번호
      size: 10, // 한 페이지에 보여 질 문서의 개수
    };

    const { data } = await bookSearch(params); // api 호출
    if (reset) {
      setBooks(data.documents);
    } else {
      setBooks(books.concat(data.documents));
    }
  };

  const searchBook = (text) => {
    setQuery(text);
  };

3. 장바구니 상태 관리하기

✔️ 장바구니 추가를 위한 addToOrder() 함수

useCallback을 통해 책을 장바구니에 추가해주는 addToOrder() 함수를 생성합니다.

어떤 책을 장바구니에 넣어줄지 isbn 파라미터를 통해 넣어줍니다.

동일한 책을 추가할 땐 2권, 3권으로 변경해주기 위해 finded를 통해 해당 책이 장바구니에 있는지 isbn를 검사 합니다. 동일한 책이 있으면 quantity(권 수) 에 +1 을 해주고 없으면 quantity에 1을 넣어 줍니다.

const [orders, setOrders] = useState([]);

// 장바구니 추가
// [{isbn, quantity : 1}]
const addToOrder = useCallback((isbn) => {
  setOrders((orders) => {
    // 동일한 책을 추가할 땐 2권, 3권 으로 변경해주기 위해 동일한 isbn가 있는지 검사
    const finded = orders.find((order) => order.isbn === isbn);
    // 장바구니에 동일한 책이 없으면 quantity에 1을 넣어줌
    if (finded === undefined) {
      return [...orders, { isbn, quantity: 1 }];
    } // 동일한 책이 있으면
    else {
      return orders.map((order) => {
        if (order.isbn === isbn) {
          return {
            isbn,
            quantity: order.quantity + 1,
          };
        } else {
          return order;
        }
      });
    }
  });
}, []);

✔️ 주문 취소를 위한 remove() 함수

주문 취소도 useCallback을 통해 orders 배열 안에 isbn

// 장바구니에서 책 삭제하기
const remove = useCallback((isbn) => {
  setOrders((orders) => {
    return orders.filter((order) => order.isbn !== isbn);
  });
}, []);

✔️ 전체 주문을 취소하기 위한 removeAll() 함수

전체 주문을 취소하는 removeAll() 함수는 useCallback을 통해 빈 배열로 바꿔줍니다.

// 장바구니에서 전체 책 삭제하기
  const removeAll = useCallback(() => {
    setOrders([]);
}, []);

3. AppStateProvider 컴포넌트 전역으로 관리하기

위에서 만든 함수를 value 에 넣어줍니다.

return (
    <AppStateContext.Provider
      value={{
        books,
        searchBook,
        orders,
        addToOrder,
        remove,
        removeAll,
      }}>
      {children}
    </AppStateContext.Provider>
  );

value를 전역으로 관리하기 위해 AppStateProvider 컴포넌트를 App 상위에 감싸줍니다.

function App() {
  return (
    <>
      <AppStateProvider>
        <BrowserRouter>
          <Switch>
            <Route component={MainPage} exact path='/' />
            <Route compoennt={LibraryPage} path='/library' />
          </Switch>
        </BrowserRouter>
      </AppStateProvider>
    </>
  );
}

4. hooks 만들어 주기

✔️ books 데이터를 받아서 내주는 역할을 하는 useBooks Hook

import { useContext } from 'react';
import AppStateContext from '../contexts/AppStateContext';

// books 데이터를 받아서 내주는 역할을 하는 Hook
export default function useBooks() {
  const { books, searchBook } = useContext(AppStateContext);
  return { books, searchBook };
}

✔️ addToOrder(), remove(), removeAll() 상태를 받아서 보내주는 역할을 하는 useActions Hook

import { useContext } from 'react';
import AppStateContext from '../contexts/AppStateContext';

// 상태를 받아서 보내주는 역할을 하는 useBooks Hook
export default function useActions() {
  const { addToOrder, remove, removeAll } = useContext(AppStateContext);

  return { addToOrder, remove, removeAll };
}

✔️ orders 데이터를 받아서 내주는 역할을 하는 useOrders Hook

import { useContext } from 'react';
import AppStateContext from '../contexts/AppStateContext';

// orders 데이터를 받아서 내주는 역할을 하는 Hook
export default function useOrders() {
  const { orders } = useContext(AppStateContext);
  return orders;
}

📝 마무리

이번 프로젝트를 통해 AppStateProvider를 사용하여 전역으로 value 값을 관리하고, Hooks로 컴포넌트를 분리하여 사용하는 방법을 이해할 수 있었습니다.
책을 검색하면 책의 데이터를 받아와 내주는 useBooks Hook, 장바구니의 추가, 삭제, 전체 삭제 기능을 관리하는 useActions Hook, orders를 관리하는 useOrders Hook 이렇게 컴포넌트를 기능별로 분리하여 관리하니 훨씬 간결해지고 읽기 쉬운 코드가 된 것 같았습니다.
Kakao 검색 API 를 활용하여 React를 공부하고자 만든 사이트라 디자인 부분에서 많이 부족하고 신경을 못 썼지만, 카카오 API 해당 문서를 이해하고 직접 발급받은 API KEY를 사용하여 데이터를 불러오는 뿌듯한 경험을 할 수 있었습니다. parameter를 이용하여 더 많은 기능을 추가하고 싶었지만, 시간 관계상 구현하지 못해 아쉬운 부분이 많이 남았지만 조금 더 실력을 키워 더 완성도 있는 프로젝트를 구현하고자 합니다.

0개의 댓글