개발/[Spring] 블로그 만들기

[코드로 배우는 스프링 웹 프로젝트] 27강. 게시물의 삭제와 첨부파일

ee2ee2 2022. 10. 3. 09:04
728x90
반응형

해당 프로젝트는 코드로 배우는 스프링 웹 프로젝트(개정판)을 기반으로 진행됩니다.


게시물을 삭제할 때는 게시물의 포함된 첨부파일 역시 삭제되어야 한다. 단순히 데이터베이스 상에서 삭제만 이뤄지는 것이 아닌 실제 폴더 내의 파일도 같이 삭제되어야하기 때문에 삭제 작업의 순서를 고려해야 한다.

먼저, 데이터 베이스의 삭제 작업을 처리한 후 실제 파일을 삭제하도록 할 것이다.


27.1 첨부파일 삭제 처리

첨부파일 관련 SQL은 BoardAttachMapper 인터페이스와 XML 파일에 작성해왔다. BoardAttachMapper 인터페이스에 deleteAll 인터페이스를 추가해보자.

BoardAttachMapper.java

package org.zerock.mapper;

import java.util.List;

import org.zerock.domain.BoardAttachVO;

public interface BoardAttachMapper {

	public void insert(BoardAttachVO vo);
	
	public void delete(String uuid);
	
	//게시글 조회시, 게시글에 첨부된 첨부파일 조회용 메소드
	public List<BoardAttachVO> findByBno(Long bno);
	
	public void deleteAll(Long bno);
}

BoardAttachMapper.xml

<mapper namespace="org.zerock.mapper.BoardAttachMapper">

	<insert id="insert">
		INSERT INTO tbl_attach (uuid, uploadpath, fileName, filetype, bno)
		VALUES (#{uuid}, #{uploadPath}, #{fileName}, #{fileType}, #{bno})
	</insert>
	
	<delete id="delete">
		DELETE FROM tbl_attach WHERE uuid=#{uuid}
	</delete>
	
	<select id="findByBno" resultType="org.zerock.domain.BoardAttachVO">
		SELECT * FROM tbl_attach WHERE bno=#{bno}
	</select>
	
	<delete id="deleteAll">
		DELETE TBL_ATTACH WHERE bno=#{bno}
	</delete>
</mapper>

27.1.1 BoardServiceImpl의 변경

첨부파일 삭제와 실제 게시물의 삭제가 같이 처리되도록 트랜잭션 하에 deleteAll()을 호출하도록 구현한다.

	@Transactional
	@Override
	public boolean remove(Long bno) {
		log.info("delete...." + bno);
		
		attachMapper.deleteAll(bno);
		
		return mapper.remove(bno) == 1;	//삭제가 정상적으로 이뤄지면 1 반환
	}

27.1.2 BoardController의 파일 삭제

BoardController는 데이터베이스의 삭제를 먼저 호출하고, 이후 파일을 삭제해야 한다. 파일 삭제를 위해서는 해당 게시물의 첨부파일 목록이 필요하므로, 아래와 같은 순서로 게시글의 삭제 작업을 처리해보자.

  1. 해당 게시물의 첨부파일 정보를 미리 준비.
  2. 데이터베이스 상에서 해당 게시물과 첨부파일 데이터 삭제
  3. 첨부파일 목록을 이용해서 해당 폴더에서 섬네일 이미지(이미지 파일인 경우에만)와 일반 파일을 삭제

BoardController.java 클래스 일부

	//글 삭제 메소드
	@PostMapping("/remove")
	public String remove(@RequestParam("bno") Long bno, Model model, RedirectAttributes rttr, @ModelAttribute("cri") Criteria cri) {
		log.info("/remove..");
		
		List<BoardAttachVO> attachList = service.getAttachList(bno);
		
		if(service.remove(bno)) {
			//delete Attach Files
			deleteFiles(attachList);
			
			rttr.addFlashAttribute("result", "success");
		}

		return "redirect:/board/list"  + cri.getListLink();	
	}
	
	private void deleteFiles(List<BoardAttachVO> attachList) {
		if(attachList == null || attachList.size() == 0) {
			return;
		}
		
		log.info("delete attach files........................");
		log.info(attachList);
		
		attachList.forEach(attach -> {
			try {
				Path file = Paths.get("C:\\upload\\"+attach.getUploadPath()+"\\"+attach.getUuid()+"_"+attach.getFileName());
				
				Files.deleteIfExists(file);
				
				if(Files.probeContentType(file).starstWith("image")) {
					Path thumbNail = Paths.get("C:\\upload\\"+attach.getUploadPath()+"\\s_"+attach.getUuid()+"_"+attach.getFileName());
					
					Files.delete(thumbNail);
				}
			} catch(Exception e) {
				log.error("delete file error.." + e.getMessage());
			} //end catch
		}); //end forEach
	}

실행결과

게시물의 삭제 진행 (1202185번 글 삭제)

1202185번 글 삭제

실제 데이터 베이스에서도 첨부 파일의 기록이 삭제됨을 확인.

실제 폴더에서도 첨부 파일의 기록이 삭제됨을 확인.

삭제 전 등록되어있는 첨부파일 리스트
게시글 삭제 후 실제 폴더에서 첨부파일이 삭제됨을 확인

반응형