유저가 체크리스트를 완료 처리를 요청하면 isComplete 상태를 DB에 true 반영하는 코드입니다.

// Service Code
public void completeChecklist(User user, ChecklistCompleteRequest request) {
String checklistId = request.checklistId();
if (request.type().equals("DAILY")) {
completeDailyChecklist(user, Long.parseLong(checklistId));
}
}
private void completeDailyChecklist(User user, Long checklistId) {
UserChecklist userChecklist = userChecklistRepository.findByUserAndChecklistId(user, checklistId)
.orElseThrow(() -> new IllegalArgumentException("해당하는 체크리스트가 없습니다"));
**// 문제 발생하는 코드**
**userChecklistRepository.completeChecklist(userChecklist.getId());**
}
-------------------------------------------------------------------------
// Jpa Repository Code
@Modifying
@Query("UPDATE UserChecklist uc SET uc.isComplete = true WHERE uc.id = :checklistId")
void completeChecklist(@Param("checklistId") Long checklistId);
여기서 특이한 점은 객체 상태를 바꾸는게 아닌 직접 Update 쿼리를 날려 영속성 컨텍스트를 무시하고 DB에 값을 반영한다는 내용입니다. 여기까지 코드를 봤을 때 문제가 있는 점은 없습니다.
완료 시각을 저장해야 하는 상황이 생겼고 아래와 같이 코드를 추가했습니다.

// Service Code
public void completeChecklist(User user, ChecklistCompleteRequest request) {
String checklistId = request.checklistId();
if (request.type().equals("DAILY")) {
completeDailyChecklist(user, Long.parseLong(checklistId));
}
}
private void completeDailyChecklist(User user, Long checklistId) {
UserChecklist userChecklist = userChecklistRepository.findByUserAndChecklistId(user, checklistId)
.orElseThrow(() -> new IllegalArgumentException("해당하는 체크리스트가 없습니다"));
userChecklistRepository.completeChecklist(userChecklist.getId());
**userChecklist.updateCompletionDate(); // 추가!!**
}
userChecklist.updateCompletionDate() 메서드가 추가되고 나서 문제가 발생.
isComplete = true로 잘 바뀌었는데 갑자기 값이 반영되지 않고 isComplete = false로 값이 저장됐습니다.

영속성 컨텍스트(1차 캐시)와 직접적인 DB 업데이트의 상호작용 방식
userChecklistRepository.findByUserAndChecklistId()를 통해 UserChecklist 엔티티가 영속성 컨텍스트에 로드. 이 시점의 isComplete 값은 false
userChecklistRepository.completeChecklist() 메서드에 사용된 @Query 어노테이션은 영속성 컨텍스트를 거치지 않고 직접 DB 업데이트하여 isComplete 컬럼 값을 true 변경합니다.
→ 이때 영속성 컨텍스트는 여전히 isComplete = false 상태
userChecklist.updateCompletionDate() 메서드가 호출되어 영속성 컨텍스트 내의 UserChecklist 엔티티의 completionDate 필드가 변경됩니다.
영속성 컨텍스트는 여전히 isComplete = false 상태