Controller

package kr.or.ddit.controller.noticeboard.web;

import javax.inject.Inject;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.ServiceResult;
import kr.or.ddit.controller.noticeboard.service.INoticeService;
import kr.or.ddit.vo.NoticeVO;

@Controller
@RequestMapping("/notice")
public class NoticeModifyController {

	@Inject
	private INoticeService noticeService;
	
	**// 수정하기 폼으로 이동**
	@RequestMapping(value="/update.do", method = RequestMethod.GET)
	public String noticeModifyForm(int boNo, Model model) {
		NoticeVO noticeVO = noticeService.selectNotice(boNo);
		model.addAttribute("notice", noticeVO);
		model.addAttribute("status", "u");
		return "notice/form";
	}
	
	**// 수정하기 처리 메소드**
@RequestMapping(value="/update.do", method = RequestMethod.POST)
	public String noticeModify(
			HttpServletRequest req,
			NoticeVO noticeVO, Model model) {
		String goPage = "";
		ServiceResult result = noticeService.updateNotice(req, noticeVO);
		if(result.equals(ServiceResult.OK)) {
			goPage = "redirect:/notice/detail.do?boNo=" + noticeVO.getBoNo();
		}else {
			model.addAttribute("message", "수정에 실패하였습니다!");
			model.addAttribute("noticeVO", noticeVO);
			model.addAttribute("status", "u");
			goPage = "notice/form";
		}
		return goPage;
	}
}

Service

package kr.or.ddit.controller.noticeboard.service;

import javax.inject.Inject;

import org.apache.commons.io.input.TaggedInputStream;
import org.springframework.stereotype.Service;

import kr.or.ddit.ServiceResult;
import kr.or.ddit.controller.noticeboard.web.TelegramSendController;
import kr.or.ddit.mapper.NoticeMapper;
import kr.or.ddit.vo.NoticeVO;

@Service
public class NoticeServiceImpl implements INoticeService {
	
	@Inject
	private NoticeMapper noticeMapper;
	
	TelegramSendController tst = new TelegramSendController();
	
	@Override
	public ServiceResult insertNotice(NoticeVO noticeVO) {
		ServiceResult result = null;
		int status = noticeMapper.insertNotice(noticeVO);
		if(status > 0) {
			// 성공 했다는 메시지를 텔레그램 BOT API를 이용하여 알림!
			try {
				tst.sendGet("조성희", noticeVO.getBoTitle());
			} catch (Exception e) {
				e.printStackTrace();
			}
			result = ServiceResult.OK;
		}else {
			result = ServiceResult.FAILED;
		}
		return result;
	}

	@Override
	public NoticeVO selectNotice(int boNo) {
		noticeMapper.incrementHit(boNo);  //조회수 증가
		return noticeMapper.selectNotice(boNo);
	}

**// 수정하기 처리 서비스**
@Override
	public ServiceResult updateNotice(HttpServletRequest req, NoticeVO noticeVO) {
		ServiceResult result = null;
		int status = noticeMapper.updateNotice(noticeVO);
		if(status > 0) { // 성공
			List<NoticeFileVO> noticeFileList = noticeVO.getNoticeFileList();
			try {
				// 1)수정을 위해서 새로 추가된 파일 데이터를 먼저 업로드 처리한다.
				noticeFileUpload(noticeFileList, noticeVO.getBoNo(), req);
				// 2) 기존 추가되었던 파일들 중, 삭제를 원하는 파일 번호들을 가져온다.
				Integer[] delNoticeNo = noticeVO.getDelNoticeNo();
				if(delNoticeNo != null) {
					// 3) 삭제를 원하는 파일 번호들 하나하나씩을 데이터베이스로 던져서 파일 정보를 얻어 온다음에
					//		데이터베이스에서 데이터를 삭제하고 서버 업로드 경로에 업로드 되어있는 파일 데이터를 삭제한다.
					for (int i = 0; i < delNoticeNo.length; i++) {
						NoticeFileVO noticeFileVO = noticeMapper.selectNoticeFile(delNoticeNo[i]);
						noticeMapper.deleteNoticeFile(delNoticeNo[i]);
						File file = new File(noticeFileVO.getFileSavepath());
						file.delete();
					}
				}
			} catch (IllegalStateException | IOException e) {
				e.printStackTrace();
			}
			
			result = ServiceResult.OK;
		}else {
			result = ServiceResult.FAILED;
		}
		return result;
	}

}

Mapper

package kr.or.ddit.mapper;

import kr.or.ddit.vo.NoticeVO;

public interface NoticeMapper {
	public int insertNotice(NoticeVO noticeVO);
	public void incrementHit(int boNo);
	public NoticeVO selectNotice(int boNo);
	public int updateNotice(NoticeVO noticeVO);
	**public NoticeFileVO selectNoticeFile(Integer integer);
	public void deleteNoticeFile(Integer integer);**
}

NoticeMapper (SQL)

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "<https://mybatis.org/dtd/mybatis-3-mapper.dtd>">
 <mapper namespace="kr.or.ddit.mapper.NoticeMapper">
 	
 	<!-- 공지사항 등록하는 쿼리 -->
 	<insert id="insertNotice" parameterType="noticeVO" useGeneratedKeys="true">
 		<selectKey keyProperty="boNo" resultType="int" order="BEFORE">
 			select seq_notice.nextval from dual
 		</selectKey>
 		insert into notice(
 			bo_no, bo_title, bo_content, bo_writer, bo_date
 		)values(
 			#{boNo}, #{boTitle}, #{boContent}, #{boWriter}, sysdate
 		)
 	</insert>
 	
 	<!-- 조회수 증가 쿼리 -->
 	<update id="incrementHit" parameterType="int">
 		update notice
 		set
 			bo_hit = bo_hit + 1
 		where bo_no = #{boNo}
 	</update>
 	
 	<!-- 상세보기 쿼리 -->
 	<select id="selectNotice" parameterType="int" resultType="noticeVO">
 		select
 			bo_no, bo_title, bo_content, bo_writer,
 			to_char(bo_date, 'yy-mm-dd hh24:mi:ss') bo_date, bo_hit
 		from notice
 		where bo_no = #{boNo}
 	</select>
 	
 	**<!-- 수정하기 쿼리 -->**
 	<update id="updateNotice" parameterType="noticeVO">
 		update notice
 		set
 			bo_title = #{boTitle},
 			bo_content = #{boContent},
 			bo_date = sysdate
 		where bo_no = #{boNo}
 	</update>

**<!-- 삭제 할 해당 파일에 대한 정보 얻기 쿼리 -->**
<select id="selectNoticeFile" parameterType="int" resultType="noticeFileVO">
 		select
 			file_no, bo_no, file_name, file_size, file_fancysize, file_mime, file_savepath, file_downcount
 		from noticefile
 		where file_no = #{fileNo}
 	</select>

 	**<!-- 해당 번호에 파일 삭제 -->**
 	<delete id="deleteNoticeFile" parameterType="int">
 		delete from noticefile
 		where file_no = #{fileNo}
 	</delete>
 </mapper>

JSP 페이지

<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib uri="<http://tiles.apache.org/tags-tiles>" prefix="tiles" %>
<%@ taglib uri="<http://java.sun.com/jsp/jstl/core>" prefix="c" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AdminLTE 3 | Simple Tables</title>

<link rel="stylesheet" href="<https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback>">
<link rel="stylesheet" href="${pageContext.request.contextPath }/resources/plugins/fontawesome-free/css/all.min.css">
<link rel="stylesheet" href="${pageContext.request.contextPath }/resources/dist/css/adminlte.min.css">
<script src="${pageContext.request.contextPath }/resources/plugins/jquery/jquery.min.js"></script>
<script src="${pageContext.request.contextPath }/resources/ckeditor/ckeditor.js"></script>
</head>
<c:if test="${not empty message }">
<script type="text/javascript">
	alert("${message}");
	<c:remove var="message" scope="request"/>
	<c:remove var="message" scope="session"/>
</script>
</c:if>
<body class="hold-transition sidebar-mini">
	<div class="wrapper">
		<!-- header 영역 -->
		<tiles:insertAttribute name="header"/>
		<div class="content-wrapper">
			<!-- content 영역 -->
			<tiles:insertAttribute name="content"/>
		</div>
		<!--  footer 영역 -->
		<tiles:insertAttribute name="footer"/>

		<aside class="control-sidebar control-sidebar-dark">
		</aside>
	</div>

	<script src="${pageContext.request.contextPath }/resources/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
	<script src="${pageContext.request.contextPath }/resources/dist/js/adminlte.min.js"></script>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="<http://java.sun.com/jsp/jstl/core>" prefix="c" %>
<section class="content-header">
	<c:set value="등록" var="name"/>
	<c:if test="${status eq 'u' }">
		<c:set value="수정" var="name"/>
	</c:if>
	<div class="container-fluid">
		<div class="row mb-2">
			<div class="col-sm-6">
				<h1>공지사항 ${name }</h1>
			</div>
			<div class="col-sm-6">
				<ol class="breadcrumb float-sm-right">
					<li class="breadcrumb-item"><a href="#">DDIT HOME</a></li>
					<li class="breadcrumb-item active">공지사항 ${name }</li>
				</ol>
			</div>
		</div>
	</div>
</section>

<section class="content">
	<div class="row">
		<div class="col-md-12">
			<div class="card card-primary">
				<form action="/notice/insert.do" method="post" id="noticeForm" enctype="multipart/form-data">
					<c:if test="${status eq 'u' }">
						<input type="hidden" name="boNo" id="boNo" value="${notice.boNo }">
					</c:if>	 			
					<div class="card-header">
						<h3 class="card-title">공지사항 ${name }</h3>
						<div class="card-tools"></div>
					</div>
					<div class="card-body">
						<div class="form-group">
							<label for="inputName">제목을 입력해주세요</label> 
							<input type="text" id="boTitle" name="boTitle" class="form-control" value="${notice.boTitle }" placeholder="제목을 입력해주세요">
						</div>
						<div class="form-group">
							<label for="boContent">내용을 입력해주세요</label>
							<textarea id="boContent" name="boContent" class="form-control" rows="14">${notice.boContent }</textarea>
						</div>
						<div class="form-group">
							<div class="custom-file">
								<label for="inputDescription">파일 선택</label> 
								<input type="file" class="custom-file-input" name="boFile" id="boFile" multiple="multiple">
								<label class="custom-file-label" for="boFile">파일을 선택해주세요</label>
							</div>
						</div>
					</div>
					<c:if test="${status eq 'u' }">
						<div class="card-footer bg-white">
							<ul class="mailbox-attachments d-flex align-items-stretch clearfix">
								<c:if test="${not empty notice.noticeFileList }">
									<c:forEach items="${notice.noticeFileList }" var="noticeFile">
										<li>
											<span class="mailbox-attachment-icon">
												<i class="far fa-file-pdf"></i>
											</span>
				
											<div class="mailbox-attachment-info">
												<a href="#" class="mailbox-attachment-name">
													<i class="fas fa-paperclip"></i> ${noticeFile.fileName }
												</a>
												<span class="mailbox-attachment-size clearfix mt-1">
													<span>${noticeFile.fileFancysize }</span>
													<span class="btn btn-default btn-sm float-right attachmentFileDel" id="span_${noticeFile.fileNo }">
														<i class="fas fa-times"></i>
													</span>
												</span>
											</div>
										</li>
									</c:forEach>
								</c:if>
								
							</ul>
						</div>
					</c:if>
					<div class="card-footer bg-white">
						<div class="row">
							<div class="col-12">
								<!-- 
									등록일때는 목록, 등록 
									수정일때는 취소, 수정
								-->
								<input type="button" id="insertBtn" value="${name }" class="btn btn-primary float-right">
								<c:if test="${status eq 'u' }">
									<input type="button" id="cancleBtn" value="취소" class="btn btn-success float-right">
								</c:if>
								<c:if test="${status ne 'u' }">
									<input type="button" id="listBtn" value="목록" class="btn btn-success float-right">
								</c:if>
							</div>
						</div>
					</div>
				</form>
			</div>
		</div>
	</div>
</section>

<script>
$(function(){
	CKEDITOR.replace("boContent", {
		footnotesPrefix: "a",
		filebrowserUploadUrl: '/imageUpload.do'
	});
	
	var listBtn = $("#listBtn");
	var insertBtn = $("#insertBtn");
	var cancleBtn = $("#cancleBtn");
	var noticeForm = $("#noticeForm");
	
	listBtn.on("click", function(){
		location.href = "/notice/list.do"
	})
	
	insertBtn.on("click", function(){
		var title = $("#boTitle");		// 제목
		var content = CKEDITOR.instances.boContent.getData(); //내용
		
		if(title == null || title == ""){
			alert("제목을 입력해주세요.")
			return false;
		}
		
		if(content == null || content == ""){
			alert("내용을 입력해주세요.")
			return false;
		}
		
		if($(this).val() == "수정"){
			noticeForm.attr("action", "/notice/update.do");
		}
			
		noticeForm.submit();
	});
	
	cancleBtn.on("click", function(){
		var boNo = $("#boNo").val();
		location.href = "/notice/detail.do?boNo=" +boNo
	});
	
// 파일 지우는 이벤트
	$(".attachmentFileDel").on("click", function(){
		var id = $(this).prop("id");
		var idx = id.indexOf("_");
		var noticeFileNo = id.substring(idx + 1);  // fileNo 얻어오기
		var ptrn = "<input type='hidden' name='delNoticeNo' value='%V'/>";
		noticeForm.append(ptrn.replace("%V", noticeFileNo));
		$(this).parents("li:first").hide();
	});	
})
</script>

여가서 x 버튼을 누르면