DEV 52

Update 쿼리를 호출할 때 주의사항 2가지

일반적으로는 Entity에 대한 수정사항은 변경감지를 통해서 진행됩니다. 하지만 여러 Entity에 대해서 update를 한 번에 처리해야하는 경우도 있습니다. @Repository public interface MemberJpaRepository extends JpaRepository { int addTokens(@Param("name") String name, @Param("amount") Integer amount); } select 쿼리와 달리 update 쿼리는 2가지를 신경써야 합니다. 1. @Modifying annotation을 추가해주어야 합니다. 2. Update 쿼리는 DB에 직접 호출됩니다. @Modifying가 없으면 테스트 코드 작성과정에서 검증될 가능성이 높기 때문에 큰 문제가..

DEV/Spring Data JPA 2023.09.24

Page<Entity>를 API의 응답으로 리턴하는 방법

pagination을 사용해서 조회한 Entity 정보를 API의 응답으로 제공할 때, 의외로 잘 모르시는 부분이 있습니다. Entity를 API의 응답으로 그대로 노출하면 안되기 때문에 아래와 같이 변환하시는 경우가 있습니다. Page memberList = memberJpaRepository.findPageByName("name", PageRequest.of(0, 10)); List memberDto = memberList.getContent() .stream() .map(m -> new MemberReadResponse(m.getId(), m.getName())) .collect(Collectors.toList()); response = new MemberResponseDto(memberDto, m..

DEV/Spring Data JPA 2023.09.24

COUNT와 Pagination, 필요없을 수 있습니다

데이터의 갯수가 정말 많을 때에 Pagination을 사용해서 데이터를 조회하곤합니다. 화면에 한 번에 조회할 수 있는 데이터의 갯수는 한정적이기 때문입니다. 아래 사진의 히트맵에서도 정상 트랜잭션의 갯수는 51402개, 에러 트랜잭션의 갯수는 305개입니다. 이러한 트랜잭션 데이터를 히트맵이 아니라 LIST로 표현할 때에는 Pagination을 적용한 화면으로 설계를 하곤합니다. 하지만 어떤 데이터가 가장 중요할까? 또는 첫 번째 페이지만으로 충분한 인사이트를 줄 수 있지 않을까?라고 접근하면 생각보다 쉽게 문제를 성능문제를 풀 수도 있습니다. 트랜잭션 데이터를 조회할 때의 주요 관심사는 주로 2가지입니다. 1. 정상이지만 느린 트랜잭션 2. 에러 트랜잭션 이 두가지 경우는 각각 아래의 필터 조건을 사..

DEV/INSIGHT 2023.09.24

Join과 Pagination 함께 사용할 때 Count 쿼리 최적화

JOIN을 해서 pagination까지 제공해야하는 경우가 있습니다. @Repository public interface MemberJpaRepository extends JpaRepository { @Query(value = "select m from Member m left join m.team t where t.id = :teamId") Page findPageByName(String name, Pageable pageable); } 그런데 이 때 JOIN을 사용하는 COUNT 쿼리가 발생할 수 있습니다. select count(m) from Member m left join m.team t left outer join은 COUNT 결과 갯수에 영향을 주지 않음에도, 이미 충분히 무거운 count ..

DEV/Spring Data JPA 2023.09.24

COUNT 쿼리, Page<T> vs Slice<T>

데이터를 조회할 때 pagination을 사용해야하는 경우가 있습니다. 전형적인 pagination에서는 데이터의 전체 건수가 필요합니다. 현재 조회하고 있는 데이터가 몇 번째 페이지에 속한 데이터인지 알 수 있어야하기 때문입니다. 그런데 모바일 환경에서는 무한스크롤방식의 UXUI가 많아지면서 전체 데이터 건수는 필요없는 경우가 있습니다. Spring에서는 아래와 같이 Count 조회를 하지 않는 Slice와 Count 조회를 하는 Page를 구분해서 제공하고 있습니다. public interface Page extends Slice { int getTotalPages(); long getTotalElements(); } Slice는 다음 페이지의 존재 여부를 확인하기 위해, 요청받은 데이터 조회 건수 ..

DEV/Spring Data JPA 2023.09.24

데이터 조회의 반환값 T vs Optional<T>

repository 계층에서 반환 타입은 어떤 타입으로 해야할까요? 먼저 EntityManager에서 getSingleResult를 조회했을 때 값이 없는 경우에는 NotResultException이 발생합니다. @Test public void findEntityNotExists(){ //given assertThrows(NoResultException.class, () -> em.createQuery("select m from Member m where m.name = :name", Member.class) .setParameter("name", "asdasdasd") .getSingleResult()); } Spring-data-jpa에서는 NoResultException을 catch해서 null로 ..

DEV/Spring Data JPA 2023.09.24

메서드 이름으로 데이터 조회하기 vs JPQL 직접 작성해서 데이터 조회하기

@Repository public interface MemberJpaRepository extends JpaRepository { List findByNameAndEmail(String name, String email); @Query("select m from Member m where m.name = :name and m.email = :email") List findUser(@Param("name") String name, @Param("email") String email); } findByNameAndEmail은 JpaRepository를 extends한 인터페이스에서 메서드 이름으로 데이터를 조회할 조건을 지정하는 방식입니다. 이 방법은 내부적으로 JPQL을 생성해주는 Spring Data J..

DEV/Spring Data JPA 2023.09.24

어떤 기능을 먼저 만들어야할까?

저는 회사에서 로그 모니터링 서비스를 만들고 있습니다. 와탭의 로그 모니터링 서비스는 약 1년 9개월동안 성장해왔습니다. 감사하게도 로그 모니터링에 니즈가 있는 대형 고객사들를 비교적 빠른 시간 내에 만날 수 있었습니다. 게다가 On-Premise가 필요하다는 고객과 SaaS가 필요하다는 고객이 모두 있었으며, 자체적으로 로그 모니터링 시스템을 개발했던 회사와 모니터링 최대 경쟁사인 DataDog의 제품을 사용하던 고객도 있었습니다. 덕분에 최근 1년동안, 매우 많이 힘들기는 했지만, 로그 모니터링 서비스로서의 최소한의 기능은 갖추어졌다고 생각합니다. 며칠전 같이 로그 모니터링 서비스를 개발하는 동료분들과 경쟁사의 로그 모니터링 제품을 비교 분석해본 적이 있습니다. DataDog, Sumo Logic, ..

DEV/INSIGHT 2023.09.20