목차
위의 게시글 상세보기 화면에서, 빨간색 동그라미를 친 삭제하기 버튼을 눌러봅니다.
위와 같은 Confirm 창이 뜨고, 확인을 누른다면 게시글 삭제 기능을 수행합니다.
요구사항 분석
- 게시글 상세보기 페이지에서, 현재 로그인된 사용자와 일치하는 사용자가 게시글 삭제를 요청한다면 게시글을 삭제합니다.
- 게시글 삭제가 완료되면, 삭제된 게시글의 카테고리에 해당하는 게시물 목록 페이지로 이동합니다.
구현
- BoardController.java
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/boards")
public class BoardApiController {
private final BoardService boardService;
@DeleteMapping("/{id}")
public BaseResponse<String> delete(@PathVariable("id") Long id) {
boardService.delete(id);
return new BaseResponse<>(SUCCESS);
}
}
클라이언트에서는 삭제 버튼을 누르면 /api/v1/boards/{id}로 DELETE 요청합니다.
@PathVariable 어노테이션으로 게시물번호를 읽어서 삭제 처리를 진행할 수 있습니다.
BoardService의 delete() 메소드를 호출하여 게시물번호를 넘겨주었습니다.
- BoardService.java
/** 게시물 삭제 */
@Transactional
public void delete(Long id) {
//활동점수 감소
Board board = boardRepository.findWithMemberById(id).orElseThrow(() -> new BaseException(NOT_FOUND_BOARD));
board.getMember().pointMinus(10);
boardRepository.delete(board);
}
Board 엔티티를 BoardRepository의 findWithMemberById() 메소드를 호출하여 조회합니다. findWithMemberById 메소드는
@EntityGraph(attributePaths = {"member"})
해당 속성을 추가하여 Member 엔티티까지 같이 조회하게 합니다.
이유는 Board 엔티티의 member 필드가 Lazy로딩 되어있기 때문에, EntityGraph나 fetch join을 쓰지 않는다면 작성자의 활동점수를 내려주기 위하여 Member 엔티티를 조회하려고 select 쿼리를 한번 더 DB에 날리기때문에, N+1 문제가 발생하기 때문입니다.
따라서 위와 같이 Board 엔티티를 조회할 때 작성자 Member 엔티티까지 같이 조회하여, 편하게 미리 Member 엔티티에 만들어둔 pointMinus() 메소드를 호출하여 활동점수를 감소시키도록 하였습니다.
작성자의 활동점수를 감소시킨 뒤, BoardRepository의 delete() 메소드를 호출하여 해당 게시물을 삭제해주었습니다.
삭제할 때, Board 테이블을 참조하는 테이블들은 모두 삭제되도록 미리 Cascade 설정을 적절하게 잘 해두어서 게시물을 삭제하면 관련된 게시물도 삭제되도록 하였습니다.
위와 같은 작업을 거치게 된다면 다음과 같은 쿼리문이 발생하여야 합니다.
1. Board, Member 조인 select 쿼리
2. 회원의 활동점수를 감소시켜주는 update 쿼리
3. 게시물을 삭제해주는 delete 쿼리
+ 게시물 관련 데이터 delete 쿼리
테스트
정말 위와 같이 기본적인 3개의 쿼리가 발생하는지 확인해보도록 하겠습니다.
로그인하여 게시물 상세보기 페이지에서 삭제하기 버튼 클릭 후, 확인을 누르고 로그를 확인해봅니다.
1. Board, Member 조인 select 쿼리
select
board0_.board_id as board_id1_4_0_,
member1_.member_id as member_id1_12_1_,
board0_.comment_count as comment_count2_4_0_,
board0_.content as content3_4_0_,
board0_.first_category as first_category4_4_0_,
board0_.like_count as like_count5_4_0_,
board0_.member_id as member_id10_4_0_,
board0_.second_category as second_category6_4_0_,
board0_.subject as subject7_4_0_,
board0_.views as views8_4_0_,
board0_.write_date as write_date9_4_0_,
board0_1_.academy_image as academy_image1_0_0_,
board0_1_.address as address2_0_0_,
board0_1_.homepage as homepage3_0_0_,
board0_1_.phone as phone4_0_0_,
board0_1_.representative_name as representative_nam5_0_0_,
board0_2_.academy_name as academy_name1_9_0_,
board0_2_.core_technology as core_technology2_9_0_,
board0_2_.curriculum_end_date as curriculum_end_dat3_9_0_,
board0_2_.curriculum_period as curriculum_period4_9_0_,
board0_2_.curriculum_start_date as curriculum_start_d5_9_0_,
board0_2_.recruitment_end_date as recruitment_end_da6_9_0_,
board0_2_.recruitment_period as recruitment_period7_9_0_,
board0_2_.recruitment_start_date as recruitment_start_8_9_0_,
board0_2_.recruits_count as recruits_count9_9_0_,
board0_2_.url as url10_9_0_,
board0_3_.must_read as must_read1_13_0_,
case
when board0_1_.board_id is not null then 1
when board0_2_.board_id is not null then 2
when board0_3_.board_id is not null then 3
when board0_.board_id is not null then 0
end as clazz_0_,
member1_.academy_member_id as academy_member_id11_12_1_,
member1_.email as email2_12_1_,
member1_.email_accept as email_accept3_12_1_,
member1_.join_date as join_date4_12_1_,
member1_.login_id as login_id12_12_1_,
member1_.nickname as nickname5_12_1_,
member1_.point as point6_12_1_,
member1_.profile_image as profile_image7_12_1_,
member1_.status as status8_12_1_,
member1_.user_role as user_role9_12_1_,
member1_.username as username10_12_1_
from
board board0_
left outer join
academy board0_1_
on board0_.board_id=board0_1_.board_id
left outer join
curriculum board0_2_
on board0_.board_id=board0_2_.board_id
left outer join
notice board0_3_
on board0_.board_id=board0_3_.board_id
left outer join
member member1_
on board0_.member_id=member1_.member_id
where
board0_.board_id=?
2. 회원의 활동점수를 감소시켜주는 update 쿼리
update
member
set
academy_member_id=?,
email=?,
email_accept=?,
join_date=?,
login_id=?,
nickname=?,
point=?,
profile_image=?,
status=?,
user_role=?,
username=?
where
member_id=?
3. 게시물을 삭제해주는 delete 쿼리
delete
from
board
where
board_id=?
위와 같이 3가지의 기본적인 쿼리가 발생하고, Board 엔티티와 관련된 엔티티들을 삭제 처리해주기 위한 select 쿼리와 delete 쿼리문이 발생한 것을 확인할 수 있습니다.
마음같아선 이 delete 쿼리들이 더 발생하는것도 처리하고싶지만, 아직 방법을 잘 몰라서 일단 Cascade 설정으로 이렇게 구현하였고 추후 방법을 알게된다면 해당 포스팅을 수정하도록 하겠습니다 :)
'개발 기록' 카테고리의 다른 글
AOP를 활용해서 메서드 실행시간 측정하기 (4) | 2024.09.08 |
---|---|
Spring Security 없이 확장성을 고려한 OAuth2.0 소셜 로그인 개발(1) - 구글 Client ID, Client Secret 발급받기 (0) | 2024.08.11 |
사이드 프로젝트 [국비의 모든것] - 게시글 작성 구현 (0) | 2023.06.12 |
사이드 프로젝트 [국비의 모든것] - 게시글 추천, 댓글 추천 기능 구현 (0) | 2023.06.12 |
사이드 프로젝트 [국비의 모든것] - 게시물 단건 조회(2) 계층형 댓글 조회 구현 (0) | 2023.06.11 |
개발을 하며 만났던 문제들과 해결 과정, 공부한 내용 등을 기록합니다.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!