14. 게시글 삽입
✅ 글쓰기 버튼 클릭 시

EditBoardController
@Controller
@RequiredArgsConstructor
@RequestMapping("editBoard")
@Slf4j
public class EditBoardController {
private final EditBoardService service;
@GetMapping("{boardCode:[0-9]+}/insert")
public String boardInsert(@PathVariable("boardCode") int boardCode) {
return "board/boardWrite";
}
@PostMapping("{boardCode:[0-9]+}/insert")
public String boardInsert(
@PathVariable("boardCode") int boardCode,
@ModelAttribute Board inputBoard,
@SessionAttribute("loginMember") Member loginMember,
@RequestParam("images") List<MultipartFile> images,
RedirectAttributes ra
) throws IllegalStateException, IOException {
inputBoard.setBoardCode(boardCode);
inputBoard.setMemberNo(loginMember.getMemberNo());
int boardNo = service.boardInsert(inputBoard, images);
String path = null;
String message = null;
if(boardNo > 0) {
path = "/board/" + boardCode + "/" + boardNo;
message = "게시글이 작성 되었습니다!";
} else {
path = "insert";
message = "게시글 작성 실패..";
}
ra.addFlashAttribute("message", message);
return "redirect:" + path;
}
}
DB 함수 vs MyBatis

DB 수행(CREATE ~ END까지)

BoardServiceImpl
@Value("${my.board.web-path}")
private String webPath;
@Value("${my.board.folder-path}")
private String folderPath;
@Override
public int boardInsert(Board inputBoard, List<MultipartFile> images) throws IllegalStateException, IOException {
int result = mapper.boardInsert(inputBoard);
if(result == 0) return 0;
int boardNo = inputBoard.getBoardNo();
List<BoardImg> uploadList = new ArrayList<>();
for(int i=0; i < images.size(); i++) {
if( !images.get(i).isEmpty() ) {
String originalName = images.get(i).getOriginalFilename();
String rename = Utility.fileRename(originalName);
BoardImg img = BoardImg.builder()
.imgOriginalName(originalName)
.imgRename(rename)
.imgPath(webPath)
.boardNo(boardNo)
.imgOrder(i)
.uploadFile(images.get(i))
.build();
uploadList.add(img);
}
}
if(uploadList.isEmpty()) {
return boardNo;
}
result = mapper.insertUploadList(uploadList);
if(result == uploadList.size()) {
for(BoardImg img : uploadList) {
img.getUploadFile()
.transferTo(new File(folderPath + img.getImgRename()));
}
} else {
throw new BoardInsertException("이미지가 정상 삽입되지 않음");
}
return boardNo;
}
BoardInsertException (throw)
public class BoardInsertException extends RuntimeException {
public BoardInsertException() {
super("게시글 삽입 중 예외 발생");
}
public BoardInsertException(String message) {
super(message);
}
}
edit-board-mapper.xml
<insert id="insertUploadList" parameterType="list">
INSERT INTO "BOARD_IMG"
<foreach collection="list" item="img"
open="(" close= ")" separator=" UNION ">
SELECT NEXT_IMG_NO(),
#{img.imgPath},
#{img.imgOriginalName},
#{img.imgRename},
#{img.imgOrder},
#{img.boardNo}
FROM DUAL
</foreach>
</insert>

boardWrite.js
const previewList = document.querySelectorAll(".preview");
const inputImageList = document.querySelectorAll(".inputImage");
const deleteImageList = document.querySelectorAll(".delete-image");
const backupInputList = new Array(inputImageList.length);
const changeImageFn = (inputImage, order) => {
const maxSzie = 1024 * 1024 * 10;
const file = inputImage.files[0];
if(file == undefined){
console.log("파일 선택 취소됨");
const temp = backupInputList[order].cloneNode(true);
inputImage.after(temp);
inputImage.remove();
inputImage = temp;
inputImage.addEventListener("change", e => {
changeImageFn(e.target, order);
})
return;
}
if(file.size > maxSzie){
alert("10MB 이하의 이미지를 선택해주세요");
if(backupInputList[order] == undefined
|| backupInputList[order].value == ''){
inputImage.value = "";
return;
}
const temp = backupInputList[order].cloneNode(true);
inputImage.after(temp);
inputImage.remove();
inputImage = temp;
inputImage.addEventListener("change", e => {
changeImageFn(e.target, order);
})
return;
}
const reader = new FileReader();
reader.readAsDataURL(file);
reader.addEventListener("load", e => {
const url = e.target.result;
previewList[order].src = url;
backupInputList[order] = inputImage.cloneNode(true);
});
}
for(let i=0 ; i<inputImageList.length ; i++){
inputImageList[i].addEventListener("change", e => {
changeImageFn(e.target, i);
})
deleteImageList[i].addEventListener("click", () => {
previewList[i].src = "";
inputImageList[i].value = "";
backupInputList[i].value = "";
});
}
document.querySelector("#boardWriteFrm")
.addEventListener("submit", e => {
const boardTitle = document.querySelector("[name='boardTitle']");
const boardContent = document.querySelector("[name='boardContent']");
if(boardTitle.value.trim().length == 0){
alert("제목을 작성해 주세요");
boardTitle.focus();
e.preventDefault();
return;
}
if(boardContent.value.trim().length == 0){
alert("내용을 작성해 주세요");
boardContent.focus();
e.preventDefault();
return;
}
});