Spring Framework (18) 게시글 수정 - Day 65

jaehoon ahn·2025년 12월 22일

Spring boot

목록 보기
16/20
post-thumbnail

업데이트 상황 정리

  1. 기존에 있던 이미지 삭제
  2. 기존에 없던곳에 새로운 이미지 추가
  3. 기존에 이미지 있었는데 다른걸로 바꾸는 것

수정, 삭제 버튼 활성화 기준

<!-- 로그인한 회원과 게시글 작성한 회원의 번호가 같은 경우 -->

                <th:block th:if="${board.memberNo == session.loginMember?.memberNo}">
                    <button id="updateBtn">수정</button>
                    <button id="deleteBtn">삭제(GET)</button>
                    <button id="deleteBtn2">삭제(POST)</button>
                </th:block>

location.pathname.replace

→ /board/1/2001

location.pathname.replace(’board’, ‘editBoard’);

→ /editBoard/1/2001/update?cp=1

location.search

⇒ 쿼리스트링 가져오기

location.pathname.replace("board", "editBoard") +
      "/update" +
      location.search

수정 버튼 클릭시 처리

/**
	 * 게시글 수정 화면 전환
	 * 
	 * @param boardCode
	 * @param boardNo
	 * @param loginMember : 로그인한 회원이 작성한 글이 맞는지
	 * @param ra          : 글 작성 실패했을 때, redirect시 메세지 전달하기 위함
	 * @return
	 */
	@GetMapping("{boardCode:[0-9]+}/{boardNo:[0-9]+}/update")
	public String boardUpdate(@PathVariable("boardCode") int boardCode, @PathVariable("boardNo") int boardNo,
			@SessionAttribute("loginMember") Member loginMember, Model model, RedirectAttributes ra) {
		// 수정 화면에 출력할 기존의 제목/내용/이미지 조회
		// -> 게시글 상세 조회 서비스
		Map<String, Integer> map = new HashMap<>();

		map.put("boardCode", boardCode);
		map.put("boardNo", boardNo);

		// BoardService.selectOne(map) 호출 결과값 반환 받기
		Board board = boardService.selectOne(map);
		// memberNo는 안필요한지?
		// selectOne에서 boardLike에 대한 조건을 처리하는데,
		// 필요하지 않은 데이터임 -> 굳이 필요없는 데이터는 안넣어도 됌

		

		String message = null;
		String path = null;

		if (board == null) {
			message = "해당 게시글이 존재하지 않습니다";
			// get방식이기 떄문에, 사용자가 일부로 url을 조작할 수 있기 때문에, 
			// 조건문 처리를 필수적으로 해줘야 한다.
			path = "redirect:/";
			
			ra.addFlashAttribute("message", message);
		} else if(board.getMemberNo() != loginMember.getMemberNo()) {
			// board는 가져왔는데, 로그인한 사람과, 게시글을 작성한 회원의 번호가 같지 않을떄의 상황을 처리
			message = "자신이 작성한 글만 수정할 수 있습니다";
			
			// 해당 글 상세조회 리다이렉트 (/board/1/2000)
			path = String.format("redirect:/board/%d/%d", boardCode, boardNo);
			ra.addFlashAttribute("message", message);
		}
		else {
			path = "board/boardUpdate"; // forward templates/board/boardUpdate.html
			model.addAttribute("board", board);
		}

		return path;
	}
  • 기존에 있는 게시글의 컨텐츠를 받아온 후, forward

로그인한 회원 ≠ 게시글 작성한 회원

로그인한 회원 = 게시글 작성한 회원

게시글 수정

controller

/**
	 * 게시글 수정
	 * 
	 * @param inputBoard      : 커맨드 객체(제목, 내용)
	 * @param images          : 제출된 type="file"인 모든 요소
	 * @param deleteOrderList : 삭제된 이미지 순서가 기록된 문자열 (ex. "1,2,3")
	 * @return
	 */
	@PostMapping("{boardCode:[0-9]+}/{boardNo:[0-9]+}/update")
	public String boardUpdate(@PathVariable("boardCode") int boardCode, @PathVariable("boardNo") int boardNo,
			Board inputBoard, @RequestParam("images") List<MultipartFile> images,
			@RequestParam(value = "deleteOrderList", required = false) String deleteOrderList,
			@RequestParam(value = "cp", required = false, defaultValue = "1") int cp,
			@SessionAttribute("loginMember") Member loginMember, RedirectAttributes ra) throws Exception {

		// 1. 커맨드 객체(inputBoard)에 boardCoe, boardNo, memberNo를 세팅
		inputBoard.setBoardCode(boardCode);
		inputBoard.setBoardNo(boardNo);
		inputBoard.setMemberNo(loginMember.getMemberNo());
		// inputBoard -> 제목, 내용, boardCode, boardNo, 회원번호 세팅됨

		// 2. 게시글 수정 서비스 호출 후 결과 반환 받기
		int result = service.boardUpdate(inputBoard, images, deleteOrderList);

		// 3. 서비스 결과에 따라 응답 제어
		String message = null;
		String path = null;

		if (result > 0) {
			message = "게시글이 수정되었습니다";
			path = String.format("/board/%d/%d?cp=%d", boardCode, boardNo, cp);
			// /board/1/2000?cp=3
		} else {
			message = "수정 실패";
			path = "update";
			// 1/2000/update -> 즉, GetMapping으로 받겠다는 것 => 다시한번 시도해보라는 것
			// GET (수정 화면 전환)

		}
		ra.addFlashAttribute("message", message);

		return "redirect:" + path;
	}

Service

// 게시글 수정 서비스
	@Override
	public int boardUpdate(Board inputBoard, List<MultipartFile> images, String deleteOrderList) throws Exception{
		// 1. 게시글 부분(제목/내용) 수정
		// 제목/내용 -> BOARD 테이블, BOARD_IMG 테이블
		// 테이블이 다르기 때문에 따로따로 진행해야함
		int result = mapper.boardUpdate(inputBoard);

		// 수정 실패 시 바로 리턴
		if (result == 0)
			return 0;

		// 2. 기존 0 -> 삭제된 이미지(deleteOrderList)가 있는 경우
		if (deleteOrderList != null && !deleteOrderList.equals("")) {
			Map<String, Object> map = new HashMap<>();
			map.put("deleteOrderList", deleteOrderList);
			map.put("boardNo", inputBoard.getBoardNo());

			// BOARD_IMG에 존재하는 행을 삭제하는 SQL 호출
			result = mapper.deleteImage(map);

			String[] delete = deleteOrderList.split(",");

			if (result == 0) {
				// 삭제 실패한 경우
				throw new RuntimeException();
			} else if (delete.length != result) {
				// 업로드된 갯수와 삭제하려던 갯수가 다른 경우
				throw new RuntimeException();
			}
			// 3. 선택한 파일이 존재할 경우
			// (클라이언트가 실제로 업로드한 이미지가 있는 경우)

			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(inputBoard.getBoardNo()).imgOrder(i).uploadFile(images.get(i)).build();

					uploadList.add(img);
					
					// 4. 업로드 하려는 이미지 정보(img) 이용해서
					// 수정을 할지, 삽입을 할지 결정을 해야함
					// 게시판에서 기존에 있는 사진에 다른 사진을 넣던지(수정), 아예 업로드 안됐던 곳에 사진을 업로드(삽입)
					// 1) 기존에 이미지가 있었다면 -> 새 이미지로 변경 -> 수정
					result = mapper.updateImage(img);
					// 즉, BOARD_IMG에서 수정이 됐다면 1, 없다면 0
					if(result == 0) {
						// 수정 실패 == 기존에 해당하는 순서(IMG_ORDER)에 이미지가 없었음
						// -> 삽입 수행
						
						// 2) 기존에 존재하지 않으므로, 새 이미지 추가
						
						result = mapper.insertImg(img);
					}
				}
				// 수정 또는 삽입이 실패한 경우
				if(result == 0) {
					throw new RuntimeException(); // 롤백
				}
			}
			if(uploadList.isEmpty()) {
				// 선택한 파일이 없을 경우
				// 즉, 클라이언트가 업로드한 이미지가 없을 경우
				// 1) 제목, 내용만 수정한 경우
				// 2) 이미지를 삭제한 경우
				return result;
			}
			// 수정, 새 이미지 파일을 서버에 저장
			for(BoardImg img : uploadList) {
				img.getUploadFile().transferTo(new File(folderPath + img.getImgRename()));
				
			}
		}
		
		return result;
	}

삭제

controller

// 삭제할 때 BOARD_DEL_FL, 즉 진짜 삭제하지말고 UPDATE하라는 것
	// /editBoard/2/1997/delete?cp=1
	@RequestMapping("{boardCode:[0-9]+}/{boardNo:[0-9]+}/delete")
	public String boardDelete(Board board, @SessionAttribute("loginMember") Member loginMember,
			@RequestParam(value = "cp", required = false, defaultValue = "1") int cp, RedirectAttributes ra)
			throws Exception {
		
		int result = service.boardDelete(board, loginMember);

		String message = null;
		String path = null;

		if (result > 0) {
			// 삭제 성공
			message = "삭제에 성공했습니다!";
			path = "/board/" + String.format("%d?cp=%d", board.getBoardCode(), cp);
		} else {
			// 삭제 실패
			message = "삭제에 실패했습니다...";
			path = "/board/" + String.format("%d/%d?cp%d", board.getBoardCode(), board.getBoardNo(), cp);
		}
		ra.addFlashAttribute("message", message);
		return "redirect:" + path;
	}

service

/**
	 * 게시물 삭제
	 */
	@Override
	public int boardDelete(Board board, Member loginMember) throws Exception{
		Map<String, Integer> map = new HashMap<>();
		map.put("memberNo", loginMember.getMemberNo());
		map.put("boardNo", board.getBoardNo());

		return mapper.boardDelete(map);
	}

0개의 댓글