간단한 데이터 관리 기능을 갖춘 도서 정보 시스템을 개발하고자 했으며, 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>
)
}
];
모달 창을 통해 항목 추가 또는 수정을 처리합니다. 사용자가 현재 페이지에서 작업을 완료하거나 취소할 수 있도록 하며, 상태 관리를 위해 useState와 useForm를 활용합니다:
<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;