회원(User) 엔티티가 있고, 한명의 회원을 조회한다고 한다면 기존에는 엔티티 하나를 조회해서, 엔티티를 DTO로 변환하여 반환하는 식으로 코드를 작성해왔습니다.
PostMan을 이용해서 테스트를 해보겠습니다.
DbInit 클래스를 이용해 초기 데이터를 셋팅해주었습니다. 총 3명의 회원이 있고, 서버를 실행할때마다 테이블을 전부 삭제하고 다시 생성하는 ddl_auto : create 옵션을 사용중이므로 회원의 PK 값은 1부터 증가할 것입니다.
user1이 조회가 잘 되는지 확인해보겠습니다.
정상적으로 조회가 되는 것을 볼 수 있습니다.
이번에는 도메인 클래스 컨버터 기능을 이용해서 조회하는 코드를 작성해보겠습니다.
아까 테스트한 코드와 굉장히 비슷하게 생겼지만, User 엔티티를 파라미터로 받는다는 점이 달라졌습니다.
HTTP 요청으로 회원의 PK의 값을 받아서, repository를 이용해 엔티티를 찾아서 반환해줍니다.\
이게 정말 가능한지 테스트 해보겠습니다.
기능이 잘 동작하는 것을 확인할 수 있습니다. 편리하게 회원을 조회할 수 있는 기능이지만 약간 아쉬운 부분이 있는 기능입니다.
도메인 클래스 컨버터로 엔티티를 파라미터로 받는 경우에는, 단순 조회용으로만 이 엔티티를 사용해야합니다.
트랜잭션이 없는 범위에서 엔티티를 조회했기때문에, 엔티티를 변경해도 DB에 반영되지 않기 때문입니다.
단순히 회원 한명의 정보를 조회해서 반환하는 로직이라면, 충분히 사용할만한 기능인 것 같습니다.
기존에 페이징과 정렬을 이용하기 위해서 Pageable 인터페이스를 이용하여 페이징과 정렬을 해왔습니다.
기존의 방식대로 페이징을 처리한다면 PageRequest를 사용해서 페이징을 해야했습니다.
지금 페이징의 조건으로, page: 0, size: 3, sort(정렬): 비밀번호 내림차순 조건을 주었습니다.
PageRequest의 객체를 생성하고, findAll을 호출할때 넣어줘서 페이징을 진행합니다.
테스트를 해보겠습니다.
페이징의 조건에 맞게 데이터를 가지고 있는것을 볼 수 있습니다.
DTO 리스트를 반환하지 않고, Page에 한번 감싸서 데이터를 넘기게 되면, Pageable이 어떤 데이터를 가지고 있는지 확인이 가능합니다.
Pageable 인터페이스를 보면, 지정해준 정렬여부와 페이지의 사이즈, 현재 페이지를 반영하고 있는 것을 볼 수 있습니다.
그렇다면 매번 이렇게 PageRequest 객체를 생성하고 매번 넣어줘야 할까요?
당연히 그렇다면 이 글을 쓰고 있지도 않을겁니다!
Pageable 역시 파라미터로 받아서 그대로 넘겨줄 수 있는 방법이 있습니다.
Pageable 인터페이스를 파라미터로 받고, 쿼리 스트링으로 조건들을 지정해서 바인딩 해줄 수 있습니다.
Pageable은 인터페이스이므로, 실제로는 PageRequest 객체가 생성되서 제공됩니다.
예시 -> /users?page=0&size=3&sort=pwd,desc
하나씩 쪼개서 어떤 의미인지 설명해드리겠습니다.
정렬기준의 경우 ASC가 기본값이므로, 오름차순 정렬은 키워드 생략이 가능합니다.
정말 이렇게 가능한지 테스트를 해보겠습니다.
지정한 조건대로 0페이지부터, 2개의 데이터를 회원번호 내림차순으로 잘 가져온것을 볼 수 있습니다.
Pageable의 값도 지정한대로 잘 바인딩되어 있는것을 확인할 수 있습니다.
이렇게 Pageable을 파라미터로 받아 값을 바인딩하는 방법으로는 위에서 살펴본 쿼리스트링 방식과 2가지 방법이 더 있습니다. 마지막으로 그 방법들을 확인해보겠습니다.
yml 또는 properties와 같은 설정파일에 글로벌로 설정이 가능합니다.
설정한대로 데이터가 1개만 나온것을 볼 수 있습니다.
글로벌 설정보다 개별설정(쿼리스트링또는 애너테이션 사용)이 우선하기 때문에, 개별설정이 없는 경우에 글로벌 설정이 적용됩니다.
마지막 방법은 @PageableDefault를 사용하는 방법입니다.
쿼리스트링을 이용한 방법과 같이 현재 페이지, 한 페이지에 노출할 데이터 개수, 정렬조건 등을 지정할 수 있습니다.
예상한대로 데이터가 나오는 것을 확인할 수 있습니다.
저번 포스팅에 다루지 않았었는데, JPA를 사용하는 입장에서 엔티티를 화면에 반환하면 좋지 않다는 것을 알고 계실 것입니다. 그래서 대부분 엔티티를 DTO로 변환해서 반환하거나, Projection 등을 이용해 DTO를 직접 생성해서 반환하기도 하는데요.
Page의 content가 엔티티리스트를 그대로 반환한다면 좋지 않기때문에, Page 인터페이스는 map( ) 함수를 제공합니다.
Page의 map( )도 stream의 map과 굉장히 유사합니다.
이 코드가 실행되면 Page<User> -> Page<UserDTO>로 화면에 반환하게 됩니다.