[Spring Boot] 38. 스프링부트 블로그 v2 (JPA) (8) 회원 정보 수정 (+dirty)

김주희's avatar
Apr 06, 2025
[Spring Boot] 38. 스프링부트 블로그 v2 (JPA) (8) 회원 정보 수정 (+dirty)

1. update-form 화면 연결

@GetMapping("/user/update-form") public String updateForm() { User sessionUser = (User) session.getAttribute("sessionUser"); if (sessionUser == null) throw new RuntimeException("인증이 필요합니다."); // ViewResolver(view를 찾아줌)의 prefix에 /templates/라고 되어있기 때문. suffix = .mustache return "user/update-form"; }
 

2. 게시글 수정하기 전

1. 미리 화면에 들어있어야 하는 것

  1. username은 미리 입력되어 있어야 한다.
  1. username은 수정 불가능하므로 disabled를 통해 비활성해야 한다.
  1. password는 미리 입력되어 있으면 안된다.
  1. email은 미리 입력되어 있어야 한다.

2. 수정 가능한 것

  1. password와 email은 수정 가능하다.
notion image
 

3. 화면에 미리 뿌리기

  1. 기존의 방식대로 request로 담아서 화면에 뿌리는 것도 가능하다.
  1. 그러나 session에서 가져오면 굳이 request에 담을 필요 없이 가져올 수 있다.
  1. 이때 pw는 뿌리면 안되고 username 과 email만 가능하다.
notion image
 

3. 게시글 수정하기

1. UserRepository

  1. update를 위한 respository 메서드는 필요하지 않다.
  1. 유저 id로 조회하는 기능을 em.find를 통해 만든다.
public User findById(Integer id) { return em.find(User.class, id); }
 

2. UserController

  1. 회원 정보 수정은 로그인한 유저만이 가능하므로 인증 체크를 해준다.
  1. update를 위해서는 updateDTO의 password와 email 그리고 update 쿼리의 where 절에 걸리게 되는 id를 session으로부터 받아 service로 넘긴다.

 
@PostMapping("/user/update") public String update(UserRequest.UpdateDTO updateDTO) { User sessionUser = (User) session.getAttribute("sessionUser"); if (sessionUser == null) throw new RuntimeException("인증이 필요합니다."); // update user_tb set password = ?, email = ? where id = ? User user = userService.회원정보수정(updateDTO, sessionUser.getId()); // 세션 동기화 (수정된 객체를 받아서 덮어씌운다) session.setAttribute("sessionUser", user); return "redirect:/"; }
 

3. UserService

  1. 게시글을 findById 메서드에 의해 em.find로 찾게 된다.
  1. 이때 PC에 캐싱되지 않은 null인 경우 select문을 통해 DB에서 조회하게 된다.
  1. PC를 거쳐 DB에서 조회되면 객체는 영속화 된다.
  1. user 객체가 조회되지 않을 경우 없는 데이터를 굳이 업데이트할 필요가 없기 때문에 RuntimeException으로 미리 처리한다.
    1. null인 상태에서는 영속성 컨텍스트의 관리 대상이 아니므로 업데이트를 해도 의미가 없고 DB에 반영되지도 않는다.
    2. null 상태에서 수정한다는 것은 비영속 객체 즉 고립된 상태의 객체를 처리하고자 하는 것이다.
    3. 고립이란 더 이상 EntityManager가 관리하지 않는 객체를 의미한다.
 
더티체킹 : 더티한 것들을 PC에 놔둠 상태변경된 것들을 가지고 update 즉시 쿼리가 날라가는게 아니라 메서드가 종료될때 checking 이때 transactional이 안걸려있으면 select한다고 생각해서 update가 안됨
@Transactional public User 회원정보수정(UserRequest.UpdateDTO updateDTO, Integer id) { User user = userRespository.findById(id); // 조회됨 -> 영속화된 객체 if (user == null) throw new RuntimeException("회원을 찾을 수 없습니다."); // 없는 데이터를 업데이트할 필요 없음 (고립X) user.update(updateDTO.getPassword(), updateDTO.getEmail()); // (PC를 거쳐서 DB에서 조회한)영속화된 객체의 상태가 변경된다. return user; } // 함수가 종료될 때 dirty checking -> 상태가 변경되면 update query
 

User

// 회원정보 수정하는 의미있는 setter public void update(String password, String email) { this.password = password; this.email = email; }
 

4. Dirty

 
Share article

jay0628