개발환경에서는 발생하지 않았던 ReferenceError: data is not defined 오류가 많았다. 원인은 데이터를 fetching 해오기 전에 하위 컴포넌트가 먼저 렌더링이 되면서 데이터를 찾을 수 없다는 오류였다.
그래서 아래와 같이 데이터가 있을 때만 컴포넌트를 렌더링하거나 옵셔널 체이닝을 넣어서 방어코드를 작성했다.
const { datas,loading,error,refetchData } =useGetOrderedMenu('/pay');// datas가 있을 때만 컴포넌트 렌더링{datas && <component />}// 옵셔널 체이닝datas?.map((data) => {...})
3. ContextAPI, useReducer 사용
useState, useEffect는 사용법이 간단했는데 ContextAPI, useReducer는 비교적 어려웠다. 또 두 개의 훅을 결합해서 사용해야했기 때문에 헷갈리는 부분이 많았다.
총 4개의 ContextAPI를 사용해 전역 상태로 관리를 했다. 1. CartCotextProvider(일반 장바구니), 2. EasyOrderContextProvider(간편주문 장바구니), 3. LoginContextProvider(로그인), 4. SelectedStoreContextProvider(선택한 매장)
아쉬웠던 점: 아래 CartContextProvider.jsx와 같이 확장성을 고려하지 못하고 total객체에 Qty, prices가 구분없이 다 들어가 있다. 그러다보니, localStorage에 저장하는 객체들도 너무 더러워졌다.
express, sequelize 등 백엔드 라이브러리 혹은 프레임워크를 배우지 않아 Firebase의 realtime database를 사용헀다. db를 생성하면 https:// … /menu.json 자동으로 생성되는 주소 뒤에 menu.json을 붙이면 api 요청주소를 get, post, put, patch, delete할 수 있어서 쉽게 통신할 수 있었다.
리액트 첫 프로젝트이어서 useEffect, custom hook api를 만들어 백엔드와 통신하는데 친해질 수 있었다.
5. 1일 이상 나를 괴롭혔던 문제
useGetMenu에서 비동기로 이미 처리를 하고 있는데 const datas = data.find((menu) => menu.id === id);는 왜 undefined가 나올까
useGetMenu 커스텀 훅에서 데이터를 비동기로 가져오기 때문에 data 상태는 초기값인 빈 배열([])로 초기화된다.
그리고 useEffect 훅에서 fetchMenu() 함수를 호출하여 비동기적으로 데이터를 가져오고, setData() 함수를 호출하여 data 상태를 업데이트함. 이 과정에서 data 상태가 업데이트되기 전에 MenuDetail 컴포넌트가 렌더링될 수 있음.
그래서 datas 변수가 data.find((menu) => menu.id === id)로 초기화되는 시점에는 data 상태가 아직 업데이트되지 않은 상태일 수 있기 때문에 undefined를 반환할 수 있다.
해결:
해결 방법으로는 datas 변수를 data 상태를 직접 사용하는 것이 아니라, data.find() 함수를 MenuDetail 컴포넌트 내부에서 사용하여 datas 변수를 업데이트하도록 변경할 수 있음. 이렇게 하면 datas 변수가 undefined를 반환하는 문제를 해결할 수 있다.
6. 카카오페이 api(단건 결제) 적용
React + kakao pay API를 적용한 다른 프로젝트를 구글링 혹은 블로그를 찾아봤지만 프론트단의 로직 설명만 있거나 설명이 부족했다. 그래서 kakao developers api 명세서를 직접 보면서 해결해나갔다. 덕분에, 비록 한국어로 설명된 명세서였지만, api 명세서를 읽고 적용하는 자신감이 생겼다.
http1.1의 kakao pay
지금까지 접해왔던 형식과 다른 이전 버전의 형식의 http 요청을 해야했다. 하지만 기본 용어들은 같았기 때문에 처음엔 헤맸지만 쉽게 적용할 수 있었다.
기능
HTTP 1.1
HTTP/2
멀티플렉싱
하나의 연결에 하나의 요청을 처리하므로, 동시에 여러 요청을 처리하려면 여러 연결이 필요합니다.
하나의 연결에 여러 요청 및 응답을 동시에 처리할 수 있습니다. 이를 통해 네트워크 리소스를 효율적으로 사용할 수 있습니다.
헤더 압축
HTTP 1.1에서는 헤더를 압축하지 않습니다. 이로 인해 불필요한 네트워크 대역폭 사용이 증가할 수 있습니다.
HTTP/2에서는 HPACK라는 표준을 사용하여 헤더를 압축하여 네트워크 리소스를 절약할 수 있습니다.
서버 푸시
HTTP 1.1에서는 서버가 클라이언트의 명시적인 요청 없이 데이터를 보내는 것이 불가능합니다.
HTTP/2에서는 서버 푸시 기능을 통해 클라이언트가 요청하지 않아도 미리 예상되는 필요한 리소스를 클라이언트에게 보낼 수 있습니다.
이진 프로토콜
HTTP 1.1은 텍스트 기반 프로토콜입니다. 따라서 오류 발생 시 디버깅이 쉽습니다. 하지만 이로 인해 효율성이 떨어질 수 있습니다.
HTTP/2는 이진 프로토콜로, 통신 효율성과 정확성을 높이는데 기여합니다. 이진 프로토콜은 디버깅이 어려울 수 있지만, 고급 도구를 통해 분석이 가능합니다.
보안
HTTP 1.1은 자체적인 보안 기능을 제공하지 않습니다. 일반적으로 SSL/TLS와 함께 사용하여 HTTPS를 형성하며, 이를 통해 보안을 제공합니다.
HTTP/2는 기본적으로 SSL/TLS와 함께 작동하도록 설계되어 있어 HTTPS가 기본적으로 사용됩니다. 그러나 자체적으로 보안 기능을 가지고 있지는 않습니다.