notice React Mix 비교
설명
React 폴더 구조
react-mix1/
├── componets/
│ ├── NoticeAdminPage.js
│ ├── NoticeForm.js
│ └── NoticeList.js
├── app.js
└── admin.html
NoticeAdminPage.js : React
공지사항에서 비즈니스로직과 핵심이 구현된 코드입니다.
import React from 'https://esm.sh/react';
import NoticeList from './NoticeList.js';
import NoticeForm from './NoticeForm.js';
const { useState, useEffect } = React;
export default function NoticeAdminPage() {
const [notices, setNotices] = useState([]);
const [selectedNotice, setSelectedNotice] = useState(null);
const [formData, setFormData] = useState({
title: '',
contents: '',
active_cd: 'D',
top_yn: false,
});
useEffect(() => {
fetchNotices();
}, []);
const fetchNotices = async () => {
try {
const response = await axios.get('/notice/data/list.json');
setNotices(response.data.rows);
} catch (error) {
console.error('Failed to fetch notices:', error);
}
};
const handleRead = (notice) => {
setSelectedNotice(notice);
setFormData({
title: notice.title,
contents: notice.contents || '',
active_cd: notice.active_cd || 'D',
top_yn: notice.top_yn === 'Y',
});
};
const handleList = () => {
setSelectedNotice(null);
};
const handleChange = (e) => {
const { name, value, type, checked } = e.target;
setFormData((prevFormData) => ({
...prevFormData,
[name]: type === 'checkbox' ? checked : value,
}));
};
const handleUpdate = async () => {
if (!formData.title.trim()) {
alert('Title is required.');
return;
}
try {
const response = await axios.put(`data/list/${selectedNotice.ntc_idx}`, formData);
console.log('Notice updated successfully:', response.data);
fetchNotices();
setSelectedNotice(null);
} catch (error) {
console.error('Failed to update notice:', error);
}
};
const handleDelete = async () => {
try {
const response = await axios.delete(`data/list/${selectedNotice.ntc_idx}`);
console.log('Notice deleted successfully:', response.data);
fetchNotices();
setSelectedNotice(null);
} catch (error) {
console.error('Failed to delete notice:', error);
}
};
return (
React.createElement('div', { className: 'container mt-3' },
React.createElement('h2', null, 'Notice Admin Page'),
React.createElement('h5', null, 'Key Features: List inquiry/modification/deletion'),
React.createElement('p', null, 'Data is transmitted when modified or deleted from the test page, but it is not actually processed.'),
!selectedNotice ? (
React.createElement(NoticeList, { notices, handleRead })
) : (
React.createElement(NoticeForm, {
selectedNotice,
formData,
handleChange,
handleUpdate,
handleDelete,
handleList
})
)
)
);
}
NoticeAdminPage.js : Mix React and BindModel
import React, { Component } from 'https://esm.sh/react';
import NoticeList from './NoticeList.js';
import NoticeForm from './NoticeForm.js';
import NoticeAdminService from '../service/notice-admin-svc.js'
export default class NoticeAdminPage extends Component {
constructor(props) {
super(props);
this.bm = new _L.BindModel(new NoticeAdminService(this));
this.bm.url = '/notice/data/list.json';
this.state = { selectedNotice: null };
}
componentDidMount() {
this.bm.cmd['list'].execute();
}
handleList = () => {
this.setState({ selectedNotice: null });
};
handleChange = (e) => {
let { name, value, type, checked } = e.target;
if (type === 'checkbox') value = checked ? 'Y' : 'N';
this.bm.cols[name].value = value; // column value setting
this.forceUpdate(); // Forced screen rendering
};
render() {
const { selectedNotice } = this.state;
return (
React.createElement('div', { className: 'container mt-3' },
React.createElement('h2', null, 'Notice Admin Page'),
React.createElement('h5', null, 'Key Features: List inquiry/modification/deletion'),
React.createElement('p', null, 'Data is transmitted when modified or deleted from the test page, but it is not actually processed.'),
React.createElement(NoticeList, { bindModel: this.bm }),
!selectedNotice || (
React.createElement(NoticeForm, {
handleChange: this.handleChange,
bindModel: this.bm
})
)
)
);
}
}
notice-admin-svc.js : Mix Vue and BindModel
export default class NoticeAdminService {
constructor(reactThis) {
const _this = this;
this.items = {
title: { required: true }
},
this.command = {
create: {
},
read: {
outputOption: 3,
},
update: {
cbBind(bind, cmd, setup) {
console.warn('Caution: Send to the test server, but the data is not reflected.', setup.data);
},
cbEnd(status, cmd, res) {
if (res) {
alert('The post has been modified.');
reactThis.handleList();
}
}
},
delete: {
cbValid(valid, cmd) {
if (confirm('Are you sure you want to delete it?')) return true;
},
cbBind(bind, cmd, setup) {
console.warn('Caution: Send to the test server, but the data is not reflected.', setup.data);
},
cbEnd(status, cmd, res) {
if (res) {
alert('The post has been deleted.');
reactThis.handleList();
}
}
},
list: {
outputOption: 1,
cbEnd(status, cmd, res) {
reactThis.setState({ selectedNotice: null });
}
}
};
this.mapping = {
ntc_idx: { read: ['bind', 'output'], update: 'bind', delete: ['valid', 'bind'] },
title: { read: 'output', update: ['valid', 'bind'], },
contents: { read: 'output', update: 'bind' },
top_yn: { read: 'output', update: ['valid', 'bind'], },
active_cd: { read: 'output', update: ['valid', 'bind'], },
create_dt: { read: 'output' },
};
this.fn = {
handleRead: async (idx) => {
_this.bindModel.cmd['read'].outputOption.index = Number(idx);
await _this.bindModel.cmd['read'].execute();
reactThis.setState({ selectedNotice: true });
},
};
}
}
비교
Mix된 코드에서 클래스 컴포넌트와 BindModel을 활용하는 방식은 React의 상태 관리와 비즈니스 로직을 더욱 명확하게 분리하여 관리할 수 있는 장점을 제공합니다. 이 방식의 주요 장점은 다음과 같습니다.
- 비즈니스 로직의 재사용성과 유지보수성 향상: BindModel을 통해 비즈니스 로직을 컴포넌트에서 분리하여 관리할 수 있습니다. 데이터 바인딩과 API 호출 등의 로직을 BindModel 내부에 정의하면, 다른 컴포넌트에서 동일한 로직을 재사용할 수 있으며, 추후 로직 변경 시 유지보수도 용이합니다. 첫 번째 코드처럼 직접적으로 비즈니스 로직을 구현하는 것보다 구조적으로 더 깔끔한 관리가 가능합니다.
- 데이터 바인딩의 일관성: BindModel을 통해 명시적으로 데이터와 화면 요소를 연결함으로써 데이터 바인딩의 일관성을 보장할 수 있습니다. this.bm.cols[name].value와 같은 방식으로 컬럼 값을 관리하면, 사용자 입력과 데이터 변경 사항을 효율적으로 동기화할 수 있습니다.
- 명확한 상태 관리: 클래스 컴포넌트는 상태를 명시적으로 관리하고, BindModel과의 상호작용을 통해 각 데이터의 상태 변화를 쉽게 추적할 수 있습니다. 이를 통해 컴포넌트 간의 상태 관리를 더욱 체계적으로 할 수 있습니다.
- 대규모 프로젝트에서의 유연성: 이 방식은 규모가 크고 복잡한 프로젝트에서 특히 유리합니다. BindModel은 여러 컴포넌트에서 비즈니스 로직을 일관되게 처리할 수 있도록 도와주며, 확장성과 유연성이 높습니다.
결론적으로, Mix된 코드는 React의 상태 관리와 비즈니스 로직을 명확하게 분리하여 코드의 가독성, 유지보수성, 재사용성을 크게 개선할 수 있는 방식을 제시하며, 특히 대규모 프로젝트나 복잡한 데이터 처리에 적합합니다.