React 기반 앤트디자인으로 구현한 임의 데이터 관리 시스템

간단한 데이터 관리 기능을 갖춘 도서 정보 시스템을 개발하고자 했으며, Ant Design 컴포넌트 라이브러리를 활용해 직관적인 인터페이스를 구현했습니다.

먼저 가상의 초기 데이터를 정의합니다:

const mockBooks = [
  { id: 1, title: '책 제목 1', author: '지은이 1' },
  { id: 2, title: '책 제목 2', author: '지은이 2' },
  { id: 3, title: '책 제목 3', author: '지은이 3' },
  { id: 4, title: '책 제목 4', author: '지은이 4' },
  { id: 5, title: '책 제목 5', author: '지은이 5' },
  { id: 6, title: '책 제목 6', author: '지은이 6' },
  { id: 7, title: '책 제목 7', author: '지은이 7' },
  { id: 8, title: '책 제목 8', author: '지은이 8' }
];

테이블 컬럼 구성은 다음과 같습니다. 각 행에 편집 및 삭제 옵션이 포함됩니다:

const tableColumns = [
  { title: '제목', dataIndex: 'title', key: 'title' },
  { title: '저자', dataIndex: 'author', key: 'author' },
  {
    title: '작업',
    key: 'actions',
    render: (_, record) => (
      <span>
        <a onClick={() => openEditModal(record)}>수정</a>
        <span>|</span>
        <a onClick={() => confirmDelete(record)}>삭제</a>
      </span>
    )
  }
];

모달 창을 통해 항목 추가 또는 수정을 처리합니다. 사용자가 현재 페이지에서 작업을 완료하거나 취소할 수 있도록 하며, 상태 관리를 위해 useStateuseForm를 활용합니다:

<Modal
  title={selectedItem ? '수정하기' : '새로 등록'}
  visible={modalOpen}
  onOk={handleSave}
  onCancel={handleCloseModal}
>
  <Form form={form}>
    <Form.Item name="title" label="도서명">
      <Input />
    </Form.Item>
    <Form.Item name="author" label="저자">
      <Input />
    </Form.Item>
  </Form>
</Modal>

저장 로직에서는 선택된 항목 여부에 따라 추가 또는 업데이트를 분기 처리합니다:

const handleSave = () => {
  if (selectedItem) {
    const updatedList = books.map(book =>
      book.id === selectedItem.id
        ? { ...book, ...form.getFieldsValue() }
        : book
    );
    setBooks(updatedList);
  } else {
    const newEntry = {
      id: books.length + 1,
      ...form.getFieldsValue()
    };
    setBooks([...books, newEntry]);
  }
  closeModal();
};

취소 버튼은 모달을 닫는 단순 동작을 수행합니다:

const handleCloseModal = () => {
  setModalOpen(false);
};

항목 삭제는 confirm 팝업을 통해 안전하게 처리되며, 필터링을 통해 해당 아이디를 제외한 리스트만 유지합니다:

const confirmDelete = (item) => {
  Modal.confirm({
    title: '삭제 확인',
    content: `정말 "${item.title}"을 삭제하시겠습니까?`,
    onOk: () => {
      const filteredList = books.filter(b => b.id !== item.id);
      setBooks(filteredList);
    }
  });
};

새 항목 추가는 showModal 함수를 통해 실행되며, 기존 선택 항목을 초기화하고 모달을 열어줍니다:

const showModal = () => {
  setSelectedItem(null);
  setModalOpen(true);
};

폼 상태는 모달 열림/닫힘에 따라 자동으로 리셋되도록 설정합니다:

const [form] = Form.useForm();

useEffect(() => {
  form.resetFields();
}, [modalOpen]);

최종 컴포넌트 구조는 다음과 같습니다:

import React, { useState, useEffect } from 'react';
import { Card, Table, Button, Modal, Form, Input } from 'antd';

const { confirm } = Modal;

function BookManager() {
  const initialBooks = [
    { id: 1, title: '책 제목 1', author: '지은이 1' },
    { id: 2, title: '책 제목 2', author: '지은이 2' },
    // 추가 항목...
  ];

  const [books, setBooks] = useState(initialBooks);
  const [selectedItem, setSelectedItem] = useState(null);
  const [modalOpen, setModalOpen] = useState(false);
  const [form] = Form.useForm();

  useEffect(() => {
    form.resetFields();
  }, [modalOpen]);

  const tableColumns = [
    { title: '제목', dataIndex: 'title', key: 'title' },
    { title: '저자', dataIndex: 'author', key: 'author' },
    {
      title: '작업',
      key: 'actions',
      render: (_, record) => (
        <span>
          <a onClick={() => openEditModal(record)}>수정</a>
          <span>|</span>
          <a onClick={() => confirmDelete(record)}>삭제</a>
        </span>
      )
    }
  ];

  const openEditModal = (item) => {
    setSelectedItem(item);
    form.setFieldsValue(item);
    setModalOpen(true);
  };

  const confirmDelete = (item) => {
    confirm({
      title: '삭제 확인',
      content: `정말 "${item.title}"을 삭제하시겠습니까?`,
      onOk: () => {
        const filteredList = books.filter(b => b.id !== item.id);
        setBooks(filteredList);
      }
    });
  };

  const handleSave = () => {
    if (selectedItem) {
      const updatedList = books.map(book =>
        book.id === selectedItem.id
          ? { ...book, ...form.getFieldsValue() }
          : book
      );
      setBooks(updatedList);
    } else {
      const newEntry = {
        id: books.length + 1,
        ...form.getFieldsValue()
      };
      setBooks([...books, newEntry]);
    }
    setModalOpen(false);
  };

  const closeModal = () => {
    setModalOpen(false);
  };

  return (
    <div>
      <Card title="도서 목록">
        <Button type="primary" onClick={showModal}>도서 추가</Button>
        <Table dataSource={books} columns={tableColumns} pagination={{ pageSize: 5 }} />
      </Card>

      <Modal
        title={selectedItem ? '수정하기' : '새로 등록'}
        visible={modalOpen}
        onOk={handleSave}
        onCancel={closeModal}
      >
        <Form form={form}>
          <Form.Item name="title" label="도서명">
            <Input />
          </Form.Item>
          <Form.Item name="author" label="저자">
            <Input />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
}

export default BookManager;

태그: React Ant Design Form Table Modal

7월 10일 16:15에 게시됨