Blog 게시글 만들기 (10) - 게시판 DELETE 기능 만들기

bethe·2022년 9월 11일
0

Springboot

목록 보기
41/46

POST 요청으로 하는 update와 delete

update(PUT)와 delete(DELETE)는 JS를 사용해야 하는데 지금은 JS를 배우기 전이라 내 실력으로는 할 수 없다.
하지만 Http 1.1부터 POST가 Http 4가지 메서드를 모두 지원했기 때문에

@PostMapping("/boards/{id}/delete")
@PostMapping("/boards/{id}/update")

주소를 이렇게 설정해 Post요청으로 update와 delete를 시도해 볼 수 있다. 임시로 주소를 이렇게 정했지만, 원래는 주소에 동사가 들어가면 안된다.



📝 게시글 DELETE 기능 만들기

1. Mapper

	<delete id="delete">
		DELETE FROM boards WHERE id = #{id}
	</delete>

2. Controller

1) deleteBoards메서드 작성

	@PostMapping("/boards/{id}/delete")
	public String deleteBoards(@PathVariable Integer id) {
		boardsDao.delete(id);
		return "redirect:/";
	}

그런데 우리는 POSTMAN으로 POST요청을 하여 delete를 한다. 이 경우 id가 없는 번호로 삭제가 요청될 수 있다...!

✔️ 영속화하여 delete 하기
id가 없는 경우 delete를 실행하면 오류가 나지 않고 0행이 수정되었다는 결과가 나온다. (결과값 0)
문제는 delete를 해본 뒤 결과값을 보고 다시 처리하는 방법이 좋지 않다는 점이다.
일단 영속화(select)를 해서 delete를 하는 것이 좋다.

💡 영속화가 유리한 이유 : 트랜잭션
DB에서 가장 데이터 부하가 심할 때는 트랜잭션이 일어날 때다.
데이터를 READ할 때는 누구나 접근 가능하나, 트랜잭션을 할 때에는 데이터의 동기화를 위해 다른 사용자가 트랜잭션을 실행하지 못하게 막기 때문이다.
👉 따라서 트랜잭션이 일어나지 않게 두 번의 연산(select, delete)이 일어나도 영속화를 한 뒤 delete를 하는 것이 낫다.


2) 영속화

	@PostMapping("/boards/{id}/delete")
	public String deleteBoards(@PathVariable Integer id) {
		
		//영속화
		Boards boardsPS = boardsDao.findById(id);
		if(boardsPS == null) { // if는 비정상 로직을 타겟 해서 걸러내는 필터 역할을 하는 게 좋음
			return "redirect:/boards/"+id;
		}
		
		boardsDao.delete(id);
		return "redirect:/";
	}
  • return의 경로는 변수를 받는 메서드가 아니라 경로이므로 return "redirect:/boards/"+id;으로 적어줘야 한다.

영속화를 하여 행을 모두 불러온 뒤 지워야 하므로 mapper도 수정

	<select id="findById"
		resultType="site.metacoding.red.domain.boards.Boards">
		SELECT id, title, content, usersId, createdAt
		FROM boards
		WHERE id = #{id}
	</select>

3) 인증체크

@PostMapping("/boards/{id}/delete")
	public String deleteBoards(@PathVariable Integer id) {

		Users principal = (Users) session.getAttribute("principal");
		
		// 영속화 : 하나의 코드로 떼어서 사용하기 위해 principal 뒤에 적었음 (boardsPS와 if문 묶음)
		Boards boardsPS = boardsDao.findById(id);
		if (boardsPS == null) { // if는 비정상 로직을 타겟 해서 걸러내는 필터 역할을 하는 게 좋음
			return "redirect:/boards/" + id;
		}

		// 인증 체크
		if (principal == null) {
			return "redirect:/loginForm";
		}
   }

4) 권한체크

principal의 Id()boardsPS의 userId를 비교

	@PostMapping("/boards/{id}/delete")
	public String deleteBoards(@PathVariable Integer id) {

		Users principal = (Users) session.getAttribute("principal");
		
		// 영속화 : 하나의 코드로 떼어서 사용하기 위해 principal 뒤에 적었음 (boardsPS와 if문 묶음)
		Boards boardsPS = boardsDao.findById(id);
		if (boardsPS == null) { // if는 비정상 로직을 타겟 해서 걸러내는 필터 역할을 하는 게 좋음
			return "redirect:/boards/" + id;
		}

		// 인증 체크
		if (principal == null) {
			return "redirect:/loginForm";
		}

		// 권한 체크 ( 세션 principal.getId() 와 boardsPS의 userId를 비교)
		if (principal.getId() != boardsPS.getUsersId()) {
			return "redirect:/boards/" + id;
		}
		
		boardsDao.delete(id);
		return "redirect:/";
	}


📝 DELETE UI (삭제버튼 만들기)

1. form태그로 버튼 디자인

	<form>
		<button class="btn btn-warning">수정하러가기</button>
	</form>
	
	<form>
		<button class="btn btn-danger">삭제</button>
	</form>

버튼을 가로로 배치하고 싶다.

🔥 이 때 form태그에 두 개의 button을 넣는 건 안 된다. 서로 다른 action을(update, delete) 가질 예정이기 때문이다.


2. flex로 가로 배치하기

	<div class="d-flex">
		<form>
			<button class="btn btn-warning">수정하러가기</button>
		</form>
		
		<form>
			<button class="btn btn-danger">삭제</button>
		</form>
	</div>


3. form태그에 action, method 지정

		<form action="/boards/${boards.id}/delete" method="post">
			<button class="btn btn-danger">삭제</button>
		</form>
  • detail에 boards를 담은 Model을 불러온 상태기 때문에 ${boards.id}로 id 설정 가능
  • 원래는 주소의 delete를 지우고 method="delete"로 해야함

4. 권한 인가시에만 delete 가능하도록 jsp 수정

	<c:if test="${principal.id == boards.usersId}">
		<div class="d-flex">
			<form>
				<button class="btn btn-warning">수정하러가기</button>
			</form>
			
			<form action="/boards/${boards.id}/detail" method="post">
				<button class="btn btn-danger">삭제</button>
			</form>
		</div>
	</c:if>
profile
코딩을 배우고 기록합니다. 읽는 사람이 이해하기 쉽게 쓰려고 합니다.

0개의 댓글