๐ ์ํ ๋ฑ๋ก(C)
- ์กฐ๊ฑด : ๊ด๋ฆฌ์๋ง ์์ฑ๊ฐ๋ฅ
- ๊ธฐ๋ฅ : ์ผํ๋ชฐ์ ํ๋งคํ ์ํ์ ๋ฑ๋ก
โ DB๊ตฌ์ฑ
์ํ์ ํ์ํ ์ ๋ณด๋ค์ ์ํ๋ช (item_name),์ํ์์ธ(item_detail),๊ฐ๊ฒฉ(price), ์๋(count), ์์ฑ๋ ์ง(created_on), ๋ํ ์ด๋ฏธ์ง(titleImage_name,titleImage_mime,titleImage_data), ์ํ๋ถ๋ฅ(category_id), ๋ธ๋๋(seller_index) ๋ก ์ ํ๋ค.
๊ทธ ์ค์์ ์ํ๋ถ๋ฅ์ ๋ธ๋๋๋ ์ํ์ ๋ฑ๋กํ ๋๋ง๋ค ์๋ก ์ ๊ธฐ์ ๋ฒ๊ฑฐ๋ก์ฐ๋ ํ ์ด๋ธ์ ๋ฐ๋ก ๋ง๋ค์ด ๊ฐ์ ๋ฃ๊ณ , ๊ฐ ํ ์ด๋ธ์ ๊ธฐ๋ณธํค( id์ index)๋ฅผ ์ธ๋ํค๋ก ๋ฐ์์ค๋๋ก ์์ฑํ๋ค. ๋ํ ๋ํ์ด๋ฏธ์ง์ ์ฌ์ง์ 1๊ฐ๋ง ๋ฑ๋กํ ๊ฒ์์ผ๋ก ์ด๋ฏธ์ง ํ ์ด๋ธ์ ๋ฐ๋ก ๋นผ์ง์๊ณ ์ํ ํ ์ด๋ธ์ ํจ๊ป ๋ฃ์ด์คฌ๋ค.
โ ์กฐ๊ฑด์ค์ : ๊ด๋ฆฌ์๋ง ๋ฑ๋กํ์ด์ง์ ์ ๊ทผ ํ์ฉํ๊ธฐ
<div class="input-container" id="inputContainer"
th:if="${session.user!=null && session.user.isAdmin()}">
<div class="temp"></div>
<div class="button-container" rel="write">
<a class="article-creation">์ํ ๋ฑ๋กํ๊ธฐ</a>
</div>
</div>
์ํ ๋ชฉ๋ก html ์์ '์ํ๋ฑ๋กํ๊ธฐ' ๋ฒํผ์ ๋ง๋ ํ๊ทธ์ ํ์๋ฆฌํ๋ฅผ ์ด์ฉํ์ฌ ๋ก๊ทธ์ธํ ์ฌ์ฉ์๊ฐ ๊ด๋ฆฌ์์ผ๋์๋ง ๋ณด์ฌ์ง๋๋ก ์กฐ๊ฑด์ ์ค์ ํด์ค๋ค.
<script
th:if="${user == null || !user.isAdmin()}">
alert('ํด๋น ํ์ด์ง๋ ๊ด๋ฆฌ์๋ง ์ ๊ทผํ ์ ์๋ ํ์ด์ง์
๋๋ค.');
window.location.href='/dios/login';
</script>
๋ง์ฐฌ๊ฐ์ง๋ก, ๋ง์ฝ ์ฌ์ฉ์ ์ค ๋๊ตฐ๊ฐ ์์๋ก ์ฃผ์์ฐฝ์ ์ ๋ ฅํด์ ๋ค์ด๊ฐ ๊ฒฝ์ฐ๋ ๋๋นํด์ผํ๊ธฐ ๋๋ฌธ์ ์ํ๋ฑ๋ก html ์์๋ <script> ํ๊ทธ ์์ ํ์๋ฆฌํ ์กฐ๊ฑด์ ์ด์ฉํ์ฌ alert ๊ฒฝ๊ณ ์ฐฝ์ ๋์ด ๋ค ๋ก๊ทธ์ธ ํ๋ฉด์ผ๋ก ์ด๋ํ๋๋ก ํ๋ค.
โ Controller ์์ getWrite ๋ฉ์๋ ์์ฑ : ์ํ๋ฑ๋ก html modelAndView๋ก ์ฐ๊ฒฐ
dios์์(๊ฐ์์ผ๋ก) ํ๋งคํ๋ ์ํ ๋ถ๋ฅ๋์๋ฅ,์ ๋ฐ,๊ธฐ๊ตฌ/์ฉํ/์ฅ๋น์ด๊ณ
(๊ฐ์์ผ๋ก) ์ ์ ํ ๋ธ๋๋๋๋์ดํค,ํธ๋ง,์๋๋ค์ค๋ก ๊ฐ๊ฐ 3๊ฐ์ง์ฉ DB์ ์ ์ฅ๋์ด์๋ค.
๋ฐ๋ผ์ ๊ด๋ฆฌ์๊ฐ ์ํ๋ฑ๋ก์ ํ ๋ ์ํ๋ถ๋ฅ์ ๋ธ๋๋๋ ์ด๋ฏธ ์ ์ฅ๋์ด์๋ DB๋ฅผ ๊ฐ์ ธ์ ์ ํํ๋๋ก ๊ตฌ์ํ์๋ค.
โน๏ธ Controller : service์์ ๊ฐ์ ธ์จ ์ ๋ณด๋ค์ modelAndView ์ addObject ํ์ฌ html์ ์ ๋ณด ์ ๋ฌ
@RequestMapping(value = "write",
method = RequestMethod.GET)
public ModelAndView getWrite(@SessionAttribute(value = "user", required = false) UserEntity user) {
ModelAndView modelAndView;
modelAndView = new ModelAndView("goods/write");
SellerEntity[] sellers = this.goodsService.getSeller();
ItemCategoryEntity[] categories = this.goodsService.getItemCategory();
modelAndView.addObject("seller", sellers);
modelAndView.addObject("category", categories);
modelAndView.addObject("user", user);
return modelAndView;
}
โน๏ธ Service : DB์ ์ ์ฅ๋์ด์๋ ์์ดํ ๋ถ๋ฅ, ๋ธ๋๋์ ์ ๋ณด๋ฅผ mapper์์ ๋ชจ๋ selectํ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ
public SellerEntity[] getSeller() {
return this.goodsMapper.selectSeller();
}
public ItemCategoryEntity[] getItemCategory() {
return this.goodsMapper.selectItemCategory();
}
โน๏ธ HTML : Controller์์ ์ ๋ฌ๋ฐ์ ์ ๋ณด๋ฅผthymeleaf ๋ฅผ ์ด์ฉํด ๊ฐ์ ๊ฐ์ ธ์จ๋ค.
<select id="itemCategory" th:name="itemCategory">
<option value=""> ์ํ ์ข
๋ฅ๋ฅผ ์ ํํด์ฃผ์ธ์.</option>
<option th:each="categories : ${category}"
th:value="${categories.getId()}"
th:text="${categories.getText()}" name="category"></option>
</select>
์์๋ก ์ํ๋ถ๋ฅ๋ ์ฝ๋๋ง ๊ฐ์ ธ์์ง๋ง, ๋ธ๋๋ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ์ ์์ ๋์ผํ๋ค.
โ ์ต์ ๊ฐ ์ ๋ ฅ(์์, ์ฌ์ด์ฆ)
โน๏ธ JavaScript: input ๋ฐ์ค์์ ๋ด์ฉ์ ๋ ฅ ํ 'enter'๋ฅผ ๋๋ฅด๋ฉด selectBox๋ก ์ ๋ ฅํ ๊ฐ ๋๊ธฐ๊ธฐ
form.onsubmit = e => {
e.preventDefault();
};
// color
form['newColor'].addEventListener('keyup', e => {
if (e.key === 'Enter') {
if (form['newColor'].value === '') {
return;
}
const optionElement = document.createElement('option');
optionElement.innerText = e.target.value;
optionElement.setAttribute('value', e.target.value);
form['colors'].append(optionElement);
e.target.value = '';
e.target.focus();
}
});
// size
form['newSize'].addEventListener('keyup', e => {
if (e.key === 'Enter') {
if (form['newSize'].value === '') {
return;
}
const optionElement = document.createElement('option');
optionElement.innerText = e.target.value;
optionElement.setAttribute('value', e.target.value);
form['sizes'].append(optionElement);
e.target.value = '';
e.target.focus();
}
});
ํค๋ณด๋์์ ํค๋ฅผ ๋์๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋๋ก keyup event๋ฅผ ์ฌ์ฉํด์ฃผ๊ณ ,
'Enter'๋ฅผ ์ณค์๋ ์ ๋ ฅ๋ฐ์ ๋ด์ฉ์ ๊ฐ์ผ๋ก ํ๋ option์ ์์ฑํด selectBox์ ์์ฑํ ๊ฐ์ ๋ณด๋ธ๋ค.
โ ๋ํ์ฌ์ง ๋ฑ๋ก
โน๏ธ JavaScript
//๋ํ ์ด๋ฏธ์ง ์ฝ์
ImageForm.querySelector('[rel = "imageSelectButton"]').addEventListener('click', e => {
e.preventDefault();
ImageForm['images'].click();
});
ImageForm['images'].addEventListener('input', () => {
const imageContainerElement = ImageForm.querySelector('[rel="imageContainer"]');
imageContainerElement.querySelectorAll('img.image').forEach(x => x.remove());
const imageSrc = URL.createObjectURL(ImageForm['images'].files[0]);
document.getElementById('imgThumb').setAttribute('src', imageSrc);
})
โ Controller ์์ postWrite ๋ฉ์๋ ์์ฑ
โน๏ธ Controller
@PostMapping(value = "write")
@ResponseBody
public String postWrite(ItemEntity item,
@SessionAttribute(value = "user", required = false) UserEntity user,
@RequestParam(value = "sizes", required = false) String[] sizes,
@RequestParam(value = "colors", required = false) String[] colors,
@RequestParam(value = "images", required = false) MultipartFile images) throws IOException {
Enum<?> result = this.goodsService.addItem(user, item, images);
ItemColorEntity[] itemColors = new ItemColorEntity[colors.length];
for (int i = 0; i < colors.length; i++) {
itemColors[i] = new ItemColorEntity();
itemColors[i].setItemIndex(item.getIndex());
itemColors[i].setColor(colors[i]);
}
this.goodsService.addItemColors(itemColors);
ItemSizeEntity[] itemSize = new ItemSizeEntity[sizes.length];
for (int i = 0; i < sizes.length; i++) {
itemSize[i] = new ItemSizeEntity();
itemSize[i].setItemIndex(item.getIndex());
itemSize[i].setSize(sizes[i]);
}
this.goodsService.addItemSizes(itemSize);
JSONObject responseObject = new JSONObject();
responseObject.put("gid", item.getIndex()); //gid๋ goodsIndex ์ ์ค์๋ง์ด๋ค.
responseObject.put("result", result.name().toLowerCase());
return responseObject.toString();
}
โน๏ธ Service
์ํ๋ฑ๋กํ๋ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ์ด ๋์ด์์ง ์๊ฑฐ๋ ๊ด๋ฆฌ์๊ฐ ์๋๋ผ๋ฉด ๊ถํ์์์ ๋ฐํ,
์ํ ๋ฑ๋กํ ๊ฐฏ์์๋ฐ๋ผ ์ฑ๊ณต์ฌ๋ถ ๋ฐํ
@Transactional
public Enum<? extends IResult> addItem(UserEntity user, ItemEntity item, MultipartFile images) throws IOException {
if (user == null || !user.isAdmin()) {
return ReviewDeleteResult.NOT_ALLOWED;
}
item.setTitleImageData(images.getBytes());
item.setTitleImageMime(images.getContentType());
item.setTitleImageName(images.getName());
return this.goodsMapper.insertItem(item) > 0
? CommonResult.SUCCESS
: CommonResult.FAILURE;
}
โน๏ธ JavaScript
์์์ ์ต์ ๊ฐ์ ์ ๋ ฅ๋ฐ์๋ onsubmit์ ์ฌ์ฉํด๋ฒ๋ ค์,
์ํ๋ฑ๋กํ๊ธฐ ๋ฒํผ์ ๋ฐ๋ก submit์ ์ง์ ํด์ฃผ๊ณ click event๋ฅผ ์ฌ์ฉํ๋ค.
insert ํ ๋ DB์ ํ์ํ ๊ฐ๋ค์ formData์ append ํด์ค๋ค
ajax ํต์ ์ ์ด์ฉํด Controller ์์ ๋ฐ์ ๊ฒฐ๊ณผ๊ฐ์ ์๋ง๋ ๊ตฌํ์ ํด์ฃผ๊ณ
์ฑ๊ณตํ์ ์์๋ ์ํ์ฝ๊ธฐ ํ์ด์ง๋ก ์ด๋ํ๋๋ก ์์ฑํ๋ค.
(์ํ ์ฝ๊ธฐ ํ์ด์ง๋ ๋ค์ ํฌ์คํ ์ ํ ์์ )
submit.addEventListener('click', e => {
e.preventDefault();
if (form['itemName'].value === '') {
alert('์ํ ์ด๋ฆ์ ์
๋ ฅํด์ฃผ์ธ์.');
form['itemName'].focus();
return false;
}
if (editor.getData() === '') {
alert('์ํ ์์ธํ์ด์ง๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์.');
editor.focus();
return false;
}
const xhr = new XMLHttpRequest();
const formData = new FormData();
for (let file of ImageForm['images'].files) {
formData.append('images', file);
}
formData.append('categoryId', itemCategory.options[itemCategory.selectedIndex].value); // ์ํ ๋ถ๋ฅ
formData.append('itemName', form['itemName'].value);//์ํ ์ด๋ฆ
formData.append('sellerIndex', seller.options[seller.selectedIndex].value);//์ํ ๋ธ๋๋ ๋ค์
formData.append('itemDetail', editor.getData());
formData.append('price', form['itemPrice'].value);
formData.append('count', form['count'].value);
form['colors'].querySelectorAll(':scope > option').forEach(option => {
formData.append('colors', option.value);
});
form['sizes'].querySelectorAll(':scope > option').forEach(option => {
formData.append('sizes', option.value);
});
xhr.open('POST', './write');
xhr.onreadystatechange = () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status >= 200 && xhr.status < 300) {
const responseObject = JSON.parse(xhr.responseText);
if (responseObject['result'] === 'not_allowed') {
alert('์ํ ๋ฑ๋ก์ ๊ถํ์ด ์์ต๋๋ค.');
} else if (responseObject['result'] === 'success') {
alert('์ํ์ด ๋ฑ๋ก๋์์ต๋๋ค!');
window.location.href = './read?gid=' + responseObject['gid'];
ImageForm['image'].value;
}
} else {
alert('์๋ฒ์ ํต์ ํ์ง ๋ชปํ์์ต๋๋ค. ์ ์ ํ ๋ค์ ์๋ํด์ฃผ์ธ์.')
}
}
}
xhr.send(formData);
});
๊ฐ๋ฐ ํ๊ธฐ
์ํ๋ฑ๋ก ์์ฒด์ ๊ตฌํ์ ๋ณด๊ธฐ์ ์ฌ์๋ณด์์ง๋ง, ๊ทธ ์์์ ๋ด๊ฐ ์ํ๋ ๋ฐฉํฅ๋๋ก ์ฝ๋๋ฅผ ์ง ๋ค๋ ๊ฒ์ด ์ผ๋ง๋ ์๊ฐํด์ผํ ๊ฒ ๋ง๊ณ ๋ ผ๋ฆฌ์ ์ธ ๊ตฌ์์ ์ํ๋์ง ๊นจ๋ซ๊ฒ ๋์๋ค.
์ฒ์์ ์ต์ ์ ๋ณด(์์,๋ฐ์ฌ์ด์ฆ, ์ท ์ฌ์ด์ฆ)ํ ์ด๋ธ์ ๋ค ๋ฐ๋ก ๋ง๋ค์ด์ ์ธ๋ํค๋ก ๋ฐ์ ๋ค select option์ผ๋ก ์ ํํ ๊ฐ๋ค๋ง insert ํ๋๋ก ํ๊ณ ์ถ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ค์ ๋ก DB์ insertํ๋ ๊ฒ๊น์ง ์ฑ๊ณตํ์๋๋ฐ, ๊ทธ ๋ค์ ์ผ์ด๋๋ ์๋ง์ ์ค๋ฅ(id ๊ฐ์ด PK๋ผ์ id ์์ฒด๋ก insert๊ฐ ์๋จ, item_index๊ฐ FK๋ผ์ ๊ฐ์ ๋ก insert๊ฐ ์๋จ, ...)๊น์ง๋ ๊ณ ๋ คํ์ง ๋ชปํด์.. DB๋ถํฐ ๊ฐ์์๊ณ ๋ค์ ์์ํ๋ ๊ณผ์ ์ ๋ช๋ฒ์ด๋ ๋ฐ๋ณตํ๋ฉด์ ์์ผ๋ก DB์ค๊ณ ํ๋ ๋ฐฉ๋ฒ์ ์กฐ๊ธ ๋ ๊ณต๋ถํ ๋ค ๊ฐ๋ฐ ์ ์ ๋ ๋ ผ๋ฆฌ์ ์ด๊ณ ์ฒด๊ณ์ ์ผ๋ก DB๋ฅผ ์ค๊ณํ ํ์์ฑ์ด ์๋ค๋๊ฑธ ์ ๋ง ๋๊ผ๋ค..ใ ใ
'Project' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[DIOS] ์ํ ์ญ์ (0) | 2023.06.18 |
---|---|
[DIOS] ์ํ ์์ ํ์ด์ง (0) | 2023.06.18 |
[DIOS] ์ํ ์ฝ๊ธฐ ํ์ด์ง (0) | 2023.05.11 |
[DIOS] ์ผํ๋ชฐ ๋ฆฌ๋ทฐ < Paging | Pagination > ๊ตฌํ (2) | 2023.01.18 |
[DIOS] ๊ฒ์ํ ๋น๋ฐ๋๊ธ ๊ตฌํ (3) | 2023.01.18 |