Lazy Loading은 연관된 엔터티(Entity)를 즉시 불러오지 않고, 해당 엔터티에 실제로 접근될 때까지 로딩을 지연시키는 방법입니다. 예를 들어, 게시글(Notice)과 댓글(Comment)이 있고, 게시글에서 댓글을 Lazy Loading으로 설정했다고 가정해봅시다. 이 경우, 게시글을 불러올 때 연관된 댓글들은 즉시 로딩되지 않습니다. 댓글에 실제로 접근(예: notice.getComments())할 때 데이터베이스에서 댓글 정보를 불러오게 됩니다.
일단 기존 게시판 코드를 전부 변경하였고 그리고 프론트단도 url 같은 경우도 notice로 전부 통일했습니다. session 적용을 할 예정이고요 문제없이 잘 작동됩니다. 추가 기능으로 댓글 기능도 넣어볼게요! 영상 아래 변경된 프론트 코드들도 작성했습니다. 백엔드 코드들은 이전링크를 참고해주세요! ps 일단 제가 프론트 vue쪽은 독학이어서 좀 부족한 부분이 많습니다. 백엔드도 사내 레거시 코드로 공부하거나 인강으로 공부하다보니 또 다른 회사들은 다르게 개발될수 있어서 부족한 부분 피드백 주시면 감사드립니다.
먼저 update가 jparepository에서는 직접적으로 제공하지 않기 때문에 만들어야합니다. service 클래스의 update 입니다.
@Override
public Notice update(Long id,Notice saveNotice) {
//id 찾기
Optional<Notice> findNotice = noticeRepository.findById(id);
//존재여부 확인
if(findNotice.isPresent()==false){
return null;
}
//찾은후 데이터 업데이트 저장
Notice notice=findNotice.get();
notice.setTitle(saveNotice.getTitle());
notice.setContents(saveNotice.getContents());
return noticeRepository.save(notice);
}
그다음은 controller 클래스 update입니다.
@PutMapping("/{id}")
public ResponseEntity<Notice> update(@PathVariable Long id, @RequestBody Notice notice){
return ResponseEntity.ok(noticeService.update(id,notice));
}
테스트코드: service update테스트
@Test
void update() throws Exception {
//생성
Long id = 1L;
Notice existingNotice = new Notice(id, "test","oldTitle", "oldContent", "oldEmail", "oldDate");
Notice updatedNotice = new Notice(id,"test", "newTitle", "newContent", "oldEmail", "oldDate");
//when
when(noticeRepository.findById(id)).thenReturn(Optional.of(existingNotice));
when(noticeRepository.save(any(Notice.class))).thenAnswer(invocation -> invocation.getArgument(0));
Notice result = noticeService.update(id, updatedNotice);
//then
assertThat(result.getId()).isEqualTo(id);
assertThat(result.getTitle()).isEqualTo("newTitle");
assertThat(result.getContents()).isEqualTo("newContent");
}
JpaRepository는 빠른 개발과 표준 CRUD 연산에 초점을 맞춘 반면, EntityManager는 보다 세밀한 데이터베이스 연산과 엔터티 관리에 사용됩니다. 실제 프로젝트에서는 종종 두 인터페이스가 함께 사용되기도 합니다.
정의와 목적:
JpaRepository: Spring Data JPA의 일부로 제공되는 인터페이스로, 주요 CRUD 연산을 위한 여러 메서드를 미리 정의해둔 것입니다. 사용자가 별도의 구현 없이 빠르게 데이터베이스 연산을 수행할 수 있게 해줍니다.
EntityManager: JPA의 핵심 인터페이스로, 엔터티의 생명주기를 관리하며 데이터베이스와의 상호작용을 위한 API를 제공합니다. 보다 세밀한 데이터베이스 연산이 필요한 경우에 사용됩니다.
기능:
JpaRepository: save, findAll, delete, findById 등의 기본 CRUD 연산을 위한 메서드가 미리 정의되어 있습니다. 또한, 쿼리 메서드의 이름 규칙을 따라 메서드를 정의함으로써 직접 쿼리를 작성하지 않고도 데이터베이스 연산을 수행할 수 있습니다.
EntityManager: persist, merge, remove, find, createQuery 등의 메서드를 제공하여 직접 엔터티 객체와 데이터베이스 간의 상호작용을 수행할 수 있습니다. 사용자는 필요에 따라 JPQL (Java Persistence Query Language)나 Criteria API를 사용하여 복잡한 쿼리를 작성할 수 있습니다.
사용 시기:
JpaRepository: 대부분의 표준적인 CRUD 연산이나 간단한 쿼리에 대한 처리를 할 때 사용됩니다. 빠른 개발 속도와 쉬운 유지보수를 위해 많이 활용됩니다.
EntityManager: 특정 엔터티의 생명주기를 세밀하게 관리하거나, 복잡한 쿼리와 데이터베이스 연산을 수행할 필요가 있을 때 사용됩니다.
확장성:
JpaRepository: 기본적인 메서드 외에도 사용자 정의 쿼리를 추가할 수 있습니다. 그러나 복잡한 연산을 수행하기 위해서는 종종 EntityManager를 사용해야 할 수도 있습니다.
EntityManager: 사용자가 필요에 따라 완전히 맞춤화된 데이터베이스 연산을 수행할 수 있게 해줍니다.
제 코드가 JpaReporitory로 해결할수 있는 부분들까지 EntityManager로 작성했다는게 큰 미스였습니다.
그래서 세밀하게 db를 변경 시키는 작업이 아니면 JpaReporitory로 변경하도록 하려고 합니다.
앞서 말씀 드리자면 jpa를 조금 독학으로 하다보니 코드가 조금 중구난방이어서 김영한 개발자님 동영상 강의를 보고 코드를 수정하고 있습니다. ㅠㅠ 독학의 장점은 많은걸 얻을수 있지만 그만큼 잘못된 방법을 얻을수 도 있네요 지금 이방법도 틀릴수 있어서 계속해서 수정은 하도록 하겠습니다.
당장 운영서버에는 적용못하고요. 일단 현재 제 pc에서 잘 작동하면 운영 웹서버에 업로드 예정입니다. 그리고 이번엔 테스트 코드도 함께 작성하였습니다.
문제없이 되었죠. 기존에는 직접적으로 만들어서 EntityMaganger로 했는데요. 암튼 이 변경작업이 생각보다 어렵네요... ㅠㅠㅠㅠ 흠 JpaRepository가 훨씬 편하고 생산성을 높일수 있다고 생각이 듭니다. 천천히 일단 할거고요. 일단 게시판이 완성되면 운영서버에 올리도록 하겠습니다. 관리자 페이지 쪽도 변경을 해야해서 좀 변경할게 많네요. ;;; ㅎㅎ