React - Json_server 설치, Axios 리팩토링 및 모듈화

김명원·2025년 1월 9일
0

learnReact

목록 보기
17/26

json-server 설치

json-server 설치


json-server는 간단한 JSON 파일을 사용하여 RESTful API를 빠르게 구축할 수 있는 도구입니다. 프론트엔드 개발 시 실제 백엔드가 준비되지 않았더라도 API를 모킹(mocking)하여 개발을 진행할 수 있어 매우 유용합니다. 이번 섹션에서는 json-server를 설치하고 설정하는 과정을 자세히 살펴보겠습니다.

1. json-server 설치

터미널을 열고 다음 명령어를 실행하여 json-server를 프로젝트에 설치합니다:

npm install json-server

설명:

  • npm install json-server: npm 패키지 매니저를 사용하여 json-server를 로컬 프로젝트에 설치합니다. json-server는 개발 의존성(devDependency)으로 설치하는 것이 일반적이지만, 필요에 따라 전역(global)으로 설치할 수도 있습니다.

Tip:

  • 전역 설치를 원할 경우, 다음과 같이 -g 플래그를 사용할 수 있습니다:

    npm install -g json-server

    하지만 프로젝트별로 다른 버전을 관리하거나, 특정 프로젝트에만 json-server를 사용하고자 할 때는 로컬 설치가 더 유용합니다.


package.json scripts 추가


package.json 파일의 scripts 섹션에 json-server를 실행할 수 있는 스크립트를 추가하여 편리하게 API 서버를 시작할 수 있습니다. 이렇게 하면 터미널에서 간단한 명령어로 json-server를 실행할 수 있어 개발 프로세스가 더욱 효율적이 됩니다.

1. package.json 수정

package.json 파일을 열고 scripts 섹션에 다음 라인을 추가합니다:

{
  ...
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
    "lint:fix": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0 --fix",
    "format": "prettier --write --cache .",
    "preview": "vite preview",
    "db": "json-server data/db.json -p 8000"
  },
  ...
}

설명:

  • "db": "json-server data/db.json -p 8000":
    • db: 스크립트의 이름입니다. 터미널에서 npm run db 명령어로 실행할 수 있습니다.
    • json-server data/db.json -p 8000:
      • json-server: 설치한 json-server를 실행합니다.
      • data/db.json: API의 데이터 소스로 사용할 JSON 파일의 경로입니다. 이 파일에 API가 제공할 데이터를 정의합니다.
      • -p 8000: json-server가 실행될 포트를 지정합니다. 기본 포트는 3000이지만, 여기서는 8000번 포트를 사용하도록 설정했습니다.

Tip:

  • 포트 번호는 프로젝트의 다른 서버(예: Vite 개발 서버)가 사용하는 포트와 충돌하지 않도록 선택해야 합니다.
  • JSON 파일의 경로(data/db.json)는 프로젝트 구조에 따라 조정할 수 있습니다. 폴더가 존재하지 않을 경우, 미리 생성해두는 것이 좋습니다.

db.json 파일


json-server가 사용할 데이터베이스 파일인 db.json을 생성하고 초기 데이터를 정의합니다. 이 파일은 JSON 형식으로 작성되며, API의 엔드포인트와 데이터를 설정하는 역할을 합니다.

1. db.json 파일 생성

프로젝트 루트 디렉토리에 data 폴더를 생성한 후, 그 안에 db.json 파일을 생성합니다.

  • 파일 경로: data/db.json

2. db.json 내용

{
  "canvases": [
    {
      "id": 1,
      "title": "친환경 도시 농업 플랫폼",
      "lastModified": "2023-06-15",
      "category": "농업"
    },
    {
      "id": 2,
      "title": "AI 기반 건강 관리 앱",
      "lastModified": "2023-06-10",
      "category": "헬스케어"
    },
    {
      "id": 3,
      "title": "온디맨드 물류 서비스",
      "lastModified": "2023-06-05",
      "category": "물류"
    },
    {
      "id": 4,
      "title": "VR 가상 여행 서비스",
      "lastModified": "2023-06-01",
      "category": "여행"
    }
  ]
}

설명:

  • canvases:
    • API 엔드포인트 /canvases를 통해 접근할 수 있는 데이터 배열입니다.
    • 각 객체는 하나의 린 캔버스를 나타내며, id, title, lastModified, category 필드를 포함합니다.
  • 필드 설명:
    • id: 각 린 캔버스의 고유 식별자입니다.
    • title: 린 캔버스의 제목을 나타냅니다.
    • lastModified: 린 캔버스가 마지막으로 수정된 날짜를 나타냅니다.
    • category: 린 캔버스가 속한 카테고리를 나타냅니다.

Tip:

  • json-serverdb.json 파일을 읽어 API 엔드포인트를 자동으로 생성합니다. 예를 들어, /canvases 엔드포인트를 통해 위의 데이터에 접근할 수 있습니다.
  • 더 많은 엔드포인트가 필요할 경우, db.json에 추가적인 키-값 쌍을 정의하면 됩니다. 예를 들어, "users": [...], "posts": [...] 등.

실습 - 목록 조회


이제 json-server를 통해 설정한 API에서 데이터를 가져와 프론트엔드 애플리케이션에 표시해보겠습니다. 이를 위해 Home.jsx 컴포넌트를 수정하여 서버로부터 데이터를 fetching(fetching)하고, 이를 목록으로 렌더링합니다.

1. src/pages/Home.jsx 수정

import { useEffect, useState } from 'react';
import CanvasList from '../components/CanvasList';
import SearchBar from '../components/SearchBar';
import ViewToggle from '../components/ViewToggle';

function Home() {
  const [searchText, setSearchText] = useState('');
  const [isGridView, setIsGridView] = useState(true);
  const [data, setData] = useState([]);

  // 데이터 fetching 함수
  async function fetchData() {
    try {
      const response = await fetch('http://localhost:8000/canvases');
      if (!response.ok) {
        throw new Error('네트워크 응답에 문제가 있습니다.');
      }
      const data = await response.json();
      setData(data);
    } catch (error) {
      console.error('데이터를 가져오는 중 오류가 발생했습니다:', error);
    }
  }

  // 컴포넌트 마운트 시 데이터 fetching
  useEffect(() => {
    fetchData();
  }, []);

  // 특정 아이템 삭제 핸들러
  const handleDeleteItem = id => {
    setData(data.filter(item => item.id !== id));
  };

  // 검색 텍스트에 따른 필터링된 데이터
  const filteredData = data.filter(item =>
    item.title.toLowerCase().includes(searchText.toLowerCase()),
  );

  return (
    <div className="container mx-auto px-4 py-16">
      {/* 검색 바와 보기 토글 */}
      <div className="mb-6 flex flex-col sm:flex-row items-center justify-between">
        <SearchBar searchText={searchText} setSearchText={setSearchText} />
        <ViewToggle isGridView={isGridView} setIsGridView={setIsGridView} />
      </div>
      
      {/* 캔버스 목록 */}
      <CanvasList
        filteredData={filteredData}
        isGridView={isGridView}
        searchText={searchText}
        onDeleteItem={handleDeleteItem}
      />
    </div>
  );
}

export default Home;

설명:

  • 임포트 추가:

    • useEffect, useState: React 훅을 사용하여 컴포넌트의 상태와 라이프사이클을 관리합니다.
    • CanvasList: 캔버스 목록을 렌더링하는 컴포넌트입니다.
    • SearchBar: 사용자가 검색할 수 있는 검색 바 컴포넌트입니다.
    • ViewToggle: 그리드 보기와 리스트 보기를 전환할 수 있는 토글 컴포넌트입니다.
  • 상태 관리:

    • searchText: 사용자가 입력한 검색어를 저장합니다.
    • isGridView: 현재 목록이 그리드 보기인지 리스트 보기인지를 저장합니다.
    • data: 서버로부터 가져온 전체 캔버스 데이터를 저장합니다.
  • 데이터 fetching (fetchData 함수):

    • fetch: 브라우저의 Fetch API를 사용하여 http://localhost:8000/canvases 엔드포인트에서 데이터를 가져옵니다.
    • 에러 핸들링: 네트워크 오류나 응답 오류를 감지하고 콘솔에 오류 메시지를 출력합니다.
    • 데이터 저장: 성공적으로 데이터를 가져오면 data 상태를 업데이트합니다.
  • useEffect 훅:

    • 컴포넌트가 마운트될 때 fetchData 함수를 호출하여 데이터를 가져옵니다.
    • 빈 배열([])을 두 번째 인자로 전달하여 이펙트가 컴포넌트의 첫 렌더링 시에만 실행되도록 합니다.
  • 아이템 삭제 핸들러 (handleDeleteItem):

    • 특정 id를 가진 캔버스를 data 상태에서 제거합니다.
    • 이는 CanvasList 또는 Note 컴포넌트에서 삭제 버튼을 클릭할 때 호출됩니다.
  • 필터링된 데이터 (filteredData):

    • searchText를 기준으로 data를 필터링하여 검색어를 포함하는 캔버스만 표시합니다.
    • 대소문자를 구분하지 않기 위해 toLowerCase()를 사용합니다.
  • 렌더링 로직:

    • 검색 바와 보기 토글: 상단에 검색 바와 보기 전환 토글을 배치하여 사용자가 목록을 필터링하고 보기 방식을 변경할 수 있도록 합니다.
    • 캔버스 목록 (CanvasList): 필터링된 데이터를 CanvasList 컴포넌트에 전달하여 실제 목록을 렌더링합니다. 또한, 보기 방식과 삭제 핸들러도 전달합니다.

Tip:

  • CORS 문제 해결: json-server는 기본적으로 CORS를 허용하지만, 프론트엔드 서버(Vite)와 백엔드 서버(json-server)가 다른 포트를 사용할 경우 CORS 정책에 의해 요청이 차단될 수 있습니다. 이 경우, json-server 실행 시 CORS 옵션을 설정하거나 프록시 설정을 통해 문제를 해결할 수 있습니다.

    예를 들어, json-server에 CORS를 허용하는 플래그를 추가할 수 있습니다:

    json-server data/db.json -p 8000 --watch --cors
  • 데이터 수정: json-server는 GET, POST, PUT, PATCH, DELETE 등의 HTTP 메서드를 지원하므로, CRUD(Create, Read, Update, Delete) 작업을 쉽게 테스트할 수 있습니다.

결과:

  • Home 컴포넌트는 json-server로부터 캔버스 데이터를 성공적으로 가져와 화면에 목록으로 표시합니다.
  • 사용자는 검색 기능을 통해 원하는 캔버스를 필터링할 수 있으며, 그리드 보기와 리스트 보기를 전환할 수 있습니다.
  • 각 캔버스는 삭제 버튼을 통해 목록에서 제거할 수 있습니다.

결론

이번 실습에서는 json-server를 활용하여 간단한 RESTful API를 구축하고, 프론트엔드 애플리케이션에서 이를 연동하여 데이터를 fetching(fetching)하고 목록으로 표시하는 과정을 배웠습니다. 주요 학습 포인트는 다음과 같습니다:

  1. json-server 설치 및 설정:

    • json-server를 설치하고, package.json에 스크립트를 추가하여 쉽게 실행할 수 있도록 했습니다.
    • db.json 파일을 생성하여 API의 데이터 소스를 정의했습니다.
  2. API 데이터 fetching:

    • React의 useEffectuseState 훅을 사용하여 컴포넌트가 마운트될 때 데이터를 가져오고 상태를 관리했습니다.
    • Fetch API를 통해 서버로부터 데이터를 가져오는 방법과 에러 핸들링을 구현했습니다.
  3. 동적 목록 렌더링 및 상호작용:

    • 검색 기능과 보기 전환 토글을 통해 사용자 경험을 향상시켰습니다.
    • 삭제 버튼을 통해 목록에서 아이템을 동적으로 제거하는 기능을 구현했습니다.

종합적으로, json-server를 활용한 API 모킹은 프론트엔드 개발 시 빠르고 유연한 데이터 관리를 가능하게 하며, 실제 백엔드 개발이 완료되기 전에 프론트엔드 기능을 테스트하고 개발할 수 있는 유용한 도구입니다. 앞으로 더 복잡한 데이터 구조나 사용자 인증 등의 기능을 추가할 때도 json-server를 기반으로 다양한 시도를 해볼 수 있을 것입니다.


Axios 리팩토링 및 모듈화

프론트엔드 애플리케이션에서 백엔드 API와 통신할 때, fetch API를 사용하는 대신 axios 라이브러리를 활용하면 코드의 가독성과 유지보수성이 크게 향상됩니다. 이번 섹션에서는 axios를 설치하고, 이를 활용하여 API 요청을 리팩토링하고 모듈화하는 방법을 단계별로 살펴보겠습니다.

Axios 리팩토링 및 모듈화

1. Axios 소개 및 장점

Axios는 Promise 기반의 HTTP 클라이언트로, 브라우저와 Node.js 환경에서 모두 사용할 수 있습니다. fetch API와 비교했을 때, axios는 다음과 같은 장점을 제공합니다:

  • 에러 처리: axios는 HTTP 응답이 실패했을 때 자동으로 에러를 발생시켜, 에러 처리가 간편합니다. 반면, fetch는 응답 상태를 수동으로 확인해야 합니다.
  • 코드 간결성: axios를 사용하면 .then 체인 없이도 response.data로 직접 데이터를 접근할 수 있어 코드가 더 깔끔해집니다.
  • 기본 설정: 기본 URL 설정, 헤더 추가, 타임아웃 설정 등 다양한 기본 설정을 지원하여 일관된 네트워크 요청을 유지할 수 있습니다.
  • 인터셉터: 요청이나 응답 전에 작업을 수행할 수 있는 인터셉터 기능을 제공하여, 모든 요청 또는 응답에 대해 공통적인 처리를 쉽게 관리할 수 있습니다.
  • 자동 JSON 데이터 변환: axios는 요청 및 응답 데이터를 자동으로 JSON으로 변환해주어 추가적인 데이터 변환 과정이 필요 없습니다.

이러한 장점들 덕분에 axios는 네트워크 요청 관리가 더 쉽고, 코드의 가독성과 유지보수성이 향상됩니다.

2. Axios 설치

프로젝트에 axios를 설치하기 위해 다음 명령어를 실행합니다:

npm install axios

설명:

  • npm install axios: axios 라이브러리를 프로젝트의 node_modules에 설치합니다. 이후, 프로젝트 내에서 axios를 임포트하여 사용할 수 있습니다.

3. API 요청 모듈화

API 요청을 모듈화하면 코드의 재사용성이 높아지고, 네트워크 요청을 중앙에서 관리할 수 있어 유지보수가 용이해집니다. 아래와 같이 axios를 활용하여 API 요청을 모듈화해보겠습니다.

3.1. src/api/http.js

import axios from 'axios';

/**
 * Create an Axios instance with default configurations.
 * @param {string} baseURL - The base URL for the API.
 * @param {object} options - Additional Axios configurations.
 * @returns {AxiosInstance} - Configured Axios instance.
 */
function create(baseURL, options = {}) {
  const instance = axios.create({
    baseURL,
    ...options,
  });
  
  // 요청 인터셉터 추가 (예: 인증 토큰 포함)
  instance.interceptors.request.use(
    config => {
      // 예시: 로컬 스토리지에서 토큰 가져오기
      const token = localStorage.getItem('token');
      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
      return config;
    },
    error => Promise.reject(error)
  );
  
  // 응답 인터셉터 추가 (예: 응답 데이터 포맷 통일)
  instance.interceptors.response.use(
    response => response,
    error => {
      // 예시: 특정 에러 처리
      if (error.response && error.response.status === 401) {
        // 로그아웃 처리 또는 토큰 갱신 로직
      }
      return Promise.reject(error);
    }
  );
  
  return instance;
}

export const canvases = create('http://localhost:8000/canvases/');

설명:

  • create 함수: 주어진 baseURL과 추가 옵션을 사용하여 axios 인스턴스를 생성합니다. 이 함수는 재사용 가능한 axios 인스턴스를 생성하는데 사용됩니다.
  • 인터셉터 설정:
    • 요청 인터셉터: 모든 요청에 대해 공통적으로 처리해야 할 작업(예: 인증 토큰 추가)을 수행합니다.
    • 응답 인터셉터: 모든 응답에 대해 공통적으로 처리해야 할 작업(예: 에러 핸들링)을 수행합니다.
  • canvases 인스턴스: /canvases 엔드포인트를 기본 URL로 설정한 axios 인스턴스를 생성하여 내보냅니다. 이를 통해 다른 파일에서 canvases 인스턴스를 임포트하여 API 요청을 할 수 있습니다.

3.2. src/api/canvas.js

import { canvases } from './http';

/**
 * Get all canvases.
 * @returns {Promise} - Promise 객체를 반환하며, 캔버스 데이터를 포함합니다.
 */
export function getCanvases() {
  return canvases.get('/');
}

/**
 * Delete a canvas by ID.
 * @param {number} id - 삭제할 캔버스의 ID.
 * @returns {Promise} - Promise 객체를 반환하며, 삭제 결과를 포함합니다.
 */
export function deleteCanvas(id) {
  return canvases.delete(`/${id}`);
}

/**
 * Create a new canvas.
 * @param {object} canvasData - 생성할 캔버스의 데이터.
 * @returns {Promise} - Promise 객체를 반환하며, 생성된 캔버스 데이터를 포함합니다.
 */
export function createCanvas(canvasData) {
  return canvases.post('/', canvasData);
}

/**
 * Update an existing canvas by ID.
 * @param {number} id - 업데이트할 캔버스의 ID.
 * @param {object} canvasData - 업데이트할 캔버스의 데이터.
 * @returns {Promise} - Promise 객체를 반환하며, 업데이트된 캔버스 데이터를 포함합니다.
 */
export function updateCanvas(id, canvasData) {
  return canvases.put(`/${id}`, canvasData);
}

설명:

  • API 함수 정의:
    • getCanvases: 모든 캔버스 데이터를 가져옵니다.
    • deleteCanvas: 특정 ID를 가진 캔버스를 삭제합니다.
    • createCanvas: 새로운 캔버스를 생성합니다.
    • updateCanvas: 특정 ID를 가진 캔버스를 업데이트합니다.
  • 재사용성: 각 함수는 특정 API 엔드포인트와 HTTP 메서드에 대한 호출을 캡슐화하여, 다른 컴포넌트에서 쉽게 재사용할 수 있습니다.

4. Home.jsx 리팩토링

기존의 fetch API를 사용하여 데이터를 가져오던 코드를 axios로 리팩토링하고, API 요청을 모듈화하여 관리하도록 변경합니다.

4.1. 변경 전 코드

import { useEffect, useState } from 'react';
import CanvasList from '../components/CanvasList';
import SearchBar from '../components/SearchBar';
import ViewToggle from '../components/ViewToggle';
import axios from 'axios';

function Home() {
  const [searchText, setSearchText] = useState('');
  const [isGridView, setIsGridView] = useState(true);
  const [data, setData] = useState([]);

  async function fetchData() {
    const response = await axios.get('http://localhost:8000/canvases');
    setData(response.data);
  }

  useEffect(() => {
    fetchData();
  }, []);

  const handleDeleteItem = id => {
    setData(data.filter(item => item.id !== id));
  };

  const filteredData = data.filter(item =>
    item.title.toLowerCase().includes(searchText.toLowerCase()),
  );

  return (
    <div className="container mx-auto px-4 py-16">
      <div className="mb-6 flex flex-col sm:flex-row items-center justify-between">
        <SearchBar searchText={searchText} setSearchText={setSearchText} />
        <ViewToggle isGridView={isGridView} setIsGridView={setIsGridView} />
      </div>
      <CanvasList
        filteredData={filteredData}
        isGridView={isGridView}
        searchText={searchText}
        onDeleteItem={handleDeleteItem}
      />
    </div>
  );
}

export default Home;

4.2. 변경 후 코드

import { useEffect, useState } from 'react';
import CanvasList from '../components/CanvasList';
import SearchBar from '../components/SearchBar';
import ViewToggle from '../components/ViewToggle';
- import axios from 'axios';
+ import { getCanvases, deleteCanvas, createCanvas, updateCanvas } from '../api/canvas';

function Home() {
  const [searchText, setSearchText] = useState('');
  const [isGridView, setIsGridView] = useState(true);
  const [data, setData] = useState([]);

  async function fetchData() {
-    const response = await axios.get('http://localhost:8000/canvases');
+    try {
+      const response = await getCanvases();
+      setData(response.data);
+    } catch (error) {
+      console.error('데이터를 가져오는 중 오류가 발생했습니다:', error);
+    }
  }

  useEffect(() => {
    fetchData();
  }, []);

  const handleDeleteItem = async id => {
    try {
      await deleteCanvas(id);
      setData(data.filter(item => item.id !== id));
    } catch (error) {
      console.error('캔버스를 삭제하는 중 오류가 발생했습니다:', error);
    }
  };

  const filteredData = data.filter(item =>
    item.title.toLowerCase().includes(searchText.toLowerCase()),
  );

  return (
    <div className="container mx-auto px-4 py-16">
      <div className="mb-6 flex flex-col sm:flex-row items-center justify-between">
        <SearchBar searchText={searchText} setSearchText={setSearchText} />
        <ViewToggle isGridView={isGridView} setIsGridView={setIsGridView} />
      </div>
      <CanvasList
        filteredData={filteredData}
        isGridView={isGridView}
        searchText={searchText}
        onDeleteItem={handleDeleteItem}
      />
    </div>
  );
}

export default Home;

설명:

  • 임포트 변경:

    • 기존의 axios 임포트를 제거하고, ../api/canvas에서 정의한 API 함수를 임포트합니다.
    • 기존:
      import axios from 'axios';
    • 변경 후:
      import { getCanvases, deleteCanvas, createCanvas, updateCanvas } from '../api/canvas';
  • fetchData 함수 리팩토링:

    • axios.get을 직접 호출하던 부분을 getCanvases 함수를 호출하도록 변경했습니다.
    • 에러 처리를 추가하여 네트워크 요청 중 발생할 수 있는 오류를 콘솔에 출력합니다.
    • 변경 전:
      const response = await axios.get('http://localhost:8000/canvases');
      setData(response.data);
    • 변경 후:
      try {
        const response = await getCanvases();
        setData(response.data);
      } catch (error) {
        console.error('데이터를 가져오는 중 오류가 발생했습니다:', error);
      }
  • handleDeleteItem 함수 리팩토링:

    • axios.delete를 직접 호출하던 부분을 deleteCanvas 함수를 호출하도록 변경했습니다.
    • 삭제가 성공적으로 완료되면 상태에서 해당 아이템을 제거합니다.
    • 에러 처리를 추가하여 삭제 요청 중 발생할 수 있는 오류를 콘솔에 출력합니다.
    • 변경 전:
      const handleDeleteItem = id => {
        setData(data.filter(item => item.id !== id));
      };
    • 변경 후:
      const handleDeleteItem = async id => {
        try {
          await deleteCanvas(id);
          setData(data.filter(item => item.id !== id));
        } catch (error) {
          console.error('캔버스를 삭제하는 중 오류가 발생했습니다:', error);
        }
      };
  • 코드 간결성 및 유지보수성 향상:

    • API 요청을 별도의 모듈로 분리함으로써 Home.jsx 파일의 책임을 줄이고, 코드의 가독성을 높였습니다.
    • API 관련 변경 사항이 있을 경우, src/api/canvas.js 파일만 수정하면 되므로 유지보수가 용이해집니다.

결과:

  • Home 컴포넌트는 이제 axios 대신 axios를 기반으로 한 모듈화된 API 함수를 사용하여 데이터를 가져오고 삭제합니다.
  • 코드의 가독성이 향상되었으며, 에러 처리가 명확하게 추가되어 안정성이 높아졌습니다.
  • API 요청과 관련된 로직이 컴포넌트 외부로 분리되어 재사용성과 유지보수성이 향상되었습니다.

전체적인 구조와 동작 방식


이번 섹션에서는 axios를 활용하여 API 요청을 리팩토링하고 모듈화함으로써 코드의 효율성과 유지보수성을 크게 향상시켰습니다. 전체적인 구조와 동작 방식을 요약하면 다음과 같습니다:

1. 컴포넌트 분리 및 모듈화

  • src/api/http.js:

    • axios 인스턴스를 생성하고, 공통된 설정(예: baseURL, 인터셉터)을 적용합니다.
    • 여러 API 엔드포인트를 위한 axios 인스턴스를 생성하여 내보냅니다.
  • src/api/canvas.js:

    • http.js에서 생성한 axios 인스턴스를 임포트하여, 캔버스 관련 API 요청 함수를 정의합니다.
    • CRUD(Create, Read, Update, Delete) 작업을 수행하는 함수를 제공합니다.
  • src/pages/Home.jsx:

    • axios를 직접 사용하지 않고, canvas.js에서 정의한 API 함수를 사용하여 데이터를 가져오고 삭제합니다.
    • 컴포넌트 내의 네트워크 요청 로직이 간결해지고, 재사용성이 향상되었습니다.

2. 상태 관리 및 데이터 흐름

  • Home 컴포넌트:
    • 상태 관리:
      • searchText: 사용자의 검색 입력을 저장합니다.
      • isGridView: 현재 보기 방식을 저장합니다 (그리드 보기 또는 리스트 보기).
      • data: 서버로부터 가져온 캔버스 데이터를 저장합니다.
    • 데이터 fetching:
      • useEffect 훅을 사용하여 컴포넌트가 마운트될 때 데이터를 가져옵니다.
      • axios 기반의 API 함수를 사용하여 데이터를 비동기적으로 가져옵니다.
    • 데이터 필터링:
      • searchText에 따라 데이터를 필터링하여 사용자에게 원하는 결과를 제공합니다.
    • 데이터 삭제:
      • 특정 캔버스를 삭제할 때, API 요청을 통해 서버에서도 해당 데이터를 제거하고, 로컬 상태에서도 업데이트합니다.

3. 에러 처리 및 사용자 피드백

  • 에러 처리:
    • API 요청 중 발생할 수 있는 오류를 try-catch 블록을 통해 처리하여, 오류 발생 시 콘솔에 명확한 메시지를 출력합니다.
    • 추가적으로, 사용자에게 에러 메시지를 표시하거나, 재시도 로직을 구현하여 사용자 경험을 향상시킬 수 있습니다.

4. 유지보수성 및 확장성

  • 모듈화된 API 요청:

    • API 요청 로직이 별도의 모듈(canvas.js)로 분리되어, 다른 컴포넌트에서도 쉽게 재사용할 수 있습니다.
    • API 엔드포인트가 변경되거나, 새로운 기능이 추가될 때, 관련 모듈만 수정하면 되므로 유지보수가 용이합니다.
  • 인터셉터 활용:

    • 요청 및 응답 인터셉터를 사용하여, 인증 토큰 추가, 공통 에러 핸들링 등을 중앙에서 관리할 수 있습니다.
    • 이는 코드의 중복을 줄이고, 일관된 네트워크 요청 처리를 가능하게 합니다.

5. 향후 개선 사항

  • 환경 변수 활용:

    • API의 baseURL을 하드코딩하지 않고, 환경 변수(.env 파일)를 사용하여 관리하면, 개발 환경과 배포 환경 간의 설정을 유연하게 변경할 수 있습니다.
    // src/api/http.js
    const baseURL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/canvases/';
    const instance = axios.create({
      baseURL,
      // 기타 설정...
    });
  • 전역 에러 핸들링:

    • 응답 인터셉터를 활용하여, 모든 API 요청에 대한 전역적인 에러 핸들링을 구현할 수 있습니다. 예를 들어, 인증 실패 시 자동으로 로그인 페이지로 리다이렉트하는 로직 등을 추가할 수 있습니다.
  • 타입스크립트 도입:

    • 프로젝트에 타입스크립트를 도입하여, API 요청 및 응답에 대한 타입을 정의함으로써, 코드의 안정성과 가독성을 더욱 향상시킬 수 있습니다.

결론

이번 실습에서는 axios를 활용하여 API 요청을 리팩토링하고 모듈화함으로써, 프론트엔드 애플리케이션의 코드 품질과 유지보수성을 크게 향상시켰습니다. 주요 작업은 다음과 같습니다:

  1. axios 설치 및 기본 설정:
    • axios를 프로젝트에 설치하고, 공통된 설정을 가진 axios 인스턴스를 생성하여 재사용성을 높였습니다.
  2. API 요청 모듈화:
    • http.jscanvas.js 파일을 생성하여, API 요청을 중앙에서 관리하고, 코드의 재사용성을 높였습니다.
  3. 컴포넌트 리팩토링:
    • Home.jsx 파일을 리팩토링하여, 직접 axios를 사용하지 않고 모듈화된 API 함수를 사용하도록 변경했습니다. 이를 통해 코드의 가독성과 유지보수성을 향상시켰습니다.
  4. 에러 처리 강화:
    • try-catch 블록을 사용하여 네트워크 요청 중 발생할 수 있는 오류를 효과적으로 처리했습니다. 이는 애플리케이션의 안정성을 높이는 데 기여했습니다.
  5. 확장성 고려:
    • 인터셉터를 활용하여, 공통된 네트워크 요청 처리를 중앙에서 관리할 수 있도록 했습니다. 이는 향후 기능 확장 시, 일관된 네트워크 요청 처리를 가능하게 합니다.

종합적으로, axios를 활용한 API 요청 리팩토링과 모듈화는 프론트엔드 개발 시 코드의 효율성과 유지보수성을 크게 향상시키는 중요한 단계입니다. 이러한 접근 방식을 통해, 보다 견고하고 확장 가능한 애플리케이션을 구축할 수 있을 것입니다. 앞으로도 axios의 다양한 기능을 활용하여, 네트워크 요청을 더욱 효과적으로 관리하고, 사용자에게 안정적인 서비스를 제공할 수 있을 것입니다.


profile
개발자가 되고 싶은 정치학도생의 기술 블로그

0개의 댓글