이번 챕터에서는 인증 체크와 JPA 의 더티 체킹을 활용하여 코드를 작성하였습니다.
1. 서비스 레이어 수정
public Board 게시글수정화면(int id, User sessionUser) {
Board board = boardRepository.findById(id);
if (board.getUser().getId() != sessionUser.getId()) {
throw new Exception403("게시글 수정 권한이 없습니다.");
}
return board;
}
2. Controller 수정 화면 요청 처리
@GetMapping("/board/{id}/update-form")
public String updateForm(@PathVariable("id") int id, HttpServletRequest request) {
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null) {
throw new Exception401("로그인 되지 않은 사용자입니다.");
}
Board board = boardService.게시글수정화면(id, sessionUser);
request.setAttribute("model", board);
return "board/update-form";
}
세션 체크를 서비스 레이어에서 수행하면 예상하지 못한 에러를 방지할 수 있습니다. 게시글 수정 전에는 반드시 인증을 확인해야 합니다.
게시글을 다 썼는데 확인 버튼을 누르고 나서야 로그인 하라며 페이지 이동 시키면…ㅠ
2.1 BoardRequest 내용 추가
@Data
public static class UpdateDTO {
private String title;
private String content;
}
이미 SaveDTO 가 있는데 굳이 UpdateDTO 를 만들어야 되나 생각할 수 있습니다.
요청메서드는 비슷하게 생겨도 중복 생성하기가 필요한 이유는
업데이트 부분의 일부만 변경하고자 하는 일이 생길 수 있기 때문이다.
3. 게시글 수정 로직(Service)
JPA 는 트랜잭션을 지원하는 쓰기지연을 통해
영속성 컨텍스트에 변경사항이 생길 때 마다 SQL 저장소에 SQL 을 생성 및 저장한다.
현재 변경 사항을 데이터베이스에 반영하는 것이 플러시이다.
@Transactional
public void 게시글수정(int id, BoardRequest.UpdateDTO updateDTO, User sessionUser) {
// 1. 게시글 조회 (없으면 404)
Board board = boardRepository.findById(id);
// 2. 권한체크
if (board.getUser().getId() != sessionUser.getId()) {
throw new Exception403("게시글을 수정할 권한이 없습니다");
}
// 3. 게시글 수정
board.setTitle(updateDTO.getTitle());
board.setContent(updateDTO.getContent());
}// flush() 자동 호출됨 (더티체킹)
위의 코드는트랜잭션을 커밋하여 자동으로 플러시를 하는 방법입니다.
현재 DB 와의 변경사항을 저장해야 하는 상황에서 flush() 를 호출하지 않은 채로 트랜잭션을 커밋해버리면 DB에 변경사항이 저장되지 않는 문제가 발생합니다.
이를 방지하기 위해서 트랜잭션을 커밋할 때 자동으로 플러시가 호출됩니다.
3.1 테스트코드 확인
@Test
public void updateByIdV2_test() {
// given
int id = 1;
Board board = boardRepository.findById(id);
// when
board.setTitle("제목10");
board.setContent("내용10");
// 트랜잭션이 종료되면 flush()
em.flush();
}
4. 컨트롤러 수정
@PostMapping("/board/{id}/update")
public String update(@PathVariable("id") int id, BoardRequest.UpdateDTO updateDTO) {
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null) {
throw new Exception401("로그인 되지 않은 사용자입니다.");
}
boardService.게시글수정(id, updateDTO, sessionUser);
return "redirect:/board/" + id;
}
매개변수가 변경되었다.
스프링부트 게시판 시리즈 v2 -1. https://inblog.ai/hj/27190 (User 테이블 생성 및 쿼리 수정) -2. https://inblog.ai/hj/27193 (User, Board 테이블 조인 과 JPQL) -3. https://inblog.ai/hj/27224 (회원 가입) -4. https://inblog.ai/hj/27225 DTO 를 통한 리팩토링 -5. https://inblog.ai/hj/27310 로그인, 로그아웃 -6. https://inblog.ai/hj/27316 서비스 레이어 추가 및 DTO 활용 -7. https://inblog.ai/hj/27430 예외처리 핸들러 설정과 User 서비스 리팩토링 -8. https://inblog.ai/hj/27431 Board 기능 리팩토링 -9. https://inblog.ai/hj/27560 게시글 수정, 더티체킹(flush) -10. https://inblog.ai/hj/27561 인터셉터, AOP 사용 / 마무리
Share article