BackEnd๐Ÿงต

Spring ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ฒ˜๋ฆฌ

hae02y 2023. 9. 9. 20:38
๋ฐ˜์‘ํ˜•

ํŽ˜์ด์ง€๋„ค์ด์…˜?

ํŽ˜์ด์ง•์€ ๊ฒŒ์‹œ๊ธ€, ๋Œ“๊ธ€ ๋“ฑ์„ ํ‘œ์ถœํ•  ์–‘์ด ๋งŽ์•„์งˆ๋•Œ, ์•„์ฃผ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•œ๋‹ค. ํŽ˜์ด์ง•์„ ํ†ตํ•ด์„œ ๋งŽ์€ ์ •๋ณด ์ฆ‰, ์ˆ˜๋ฐฑ ์ˆ˜์ฒœ๊ฐœ์˜ ๊ฒŒ์‹œ๊ธ€๋“ฑ์˜ ์ •๋ณด๋ฅผ ํŽ˜์ด์ง€๋กœ ๋‚˜๋ˆ ์„œ ํšจ๊ณผ์ ์œผ๋กœ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๊ฒŒ ํ•œ๋‹ค.

์ด๋Ÿฐ ํŽ˜์ด์ง•์„ ์œ„ํ•ด์„œ๋Š” page๊ด€๋ จ ์ฟผ๋ฆฌ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์ง€๋งŒ, Spring Data JPA์—์„œ ํšจ๊ณผ์ ์ธ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค.

 

JpaRepository ์˜ ๋ถ€๋ชจ์ธํ„ฐํŽ˜์ด์Šค์ธ PagingAndSortingRepository์—์„œ ํŽ˜์ด์ง•๊ณผ Sorting ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

findAll() ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ์‚ดํŽด๋ณด๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•œ๋‹ค.

 

  • Pageable : ํŽ˜์ด์ง•์„ ์ œ๊ณตํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค
  • Page : ํŽ˜์ด์ง•์˜ findAll()์˜ ๊ธฐ๋ณธ์ ์ธ ๋ฐ˜ํ™˜ ๋ฉ”์„œ๋“œ๋กœ ์—ฌ๋Ÿฌ ๋ฐ˜ํ™˜ํƒ€์ž…์ค‘ ํ•˜๋‚˜

 

์ฆ‰, JpaRepository<>๋ฅผ ์‚ฌ์šฉํ• ๋•Œ findAll() ๋ฉ”์„œ๋“œ๋ฅผ Pageble ์ธํ„ฐํŽ˜์ด์Šค๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„˜๊ธฐ๋ฉด ํŽ˜์ด์ง•์„ ์‚ฌ์šฉํ• ์ˆ˜์žˆ๋‹ค.

 

์ฝ”๋“œ

Controller

/**  
* ์Šคํ”„๋ง์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ๋ฅผ 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•œ๋‹ค. -> ์ด๋ฅผ ์œ„ํ•ด์„œ controller์ชฝ์—์„œ page-1 ์„ ํ•ด์„œ ์˜ฌ๋ฐ”๋ฅธ ๋ฒˆํ˜ธ๋ฅผ ์กฐํšŒํ• ์ˆ˜์žˆ๊ฒŒ ํ•ด์คŒ.  
* @param page : ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ์œ„ํ•œ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ  
* @param size : ํ•œ ํŽ˜์ด์ง€์— ํ‘œ์‹œ๋˜์–ด์•ผ ํ•  ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜(row)  
* @return  
*/
@GetMapping  
public ResponseEntity getLicenses(@RequestParam int page,  
@RequestParam int size){  
Page<License> pageLicenses = licenseService.findLicenses(page, size);  
List<License> licenses = pageLicenses.getContent();  

return new ResponseEntity<>(  
new MultiResponseDto<>(licenses,pageLicenses),HttpStatus.OK  
);  
}

Service

/**  
* ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ฒ˜๋ฆฌ๊ฐ€ ๋œ ์ž๊ฒฉ์ฆ ์ •๋ณด ๋ชฉ๋ก์„ ๋ฆฌํ„ด  
* @param page  
* @param size  
* @return  
*/  
public Page<License> findLicenses(int page, int size) {  
return licenseRepository.findAll(PageRequest.of(page-1, size, Sort.by("id").ascending()));  
} 
//page-1 ์„ ํ•˜๋Š” ์ด์œ ๋Š” page+1์ด ๋˜์–ด์žˆ์œผ๋ฏ€๋กœ.
//id๋กœ sorting ์˜ค๋ฆ„์ฐจ์ˆœ(ascending)

MultiResponseDto

@Getter  
public class MultiResponseDto<T> {  

private List<T> data; // ์‘๋‹ต ๋ฐ์ดํ„ฐ ๋ชฉ๋ก ๋‹ด๋Š” ํ•„๋“œ  
private PageInfo pageInfo; // ํŽ˜์ด์ง€ ์ •๋ณด ๋‹ด๋Š” ํ•„๋“œ  

public MultiResponseDto(List<T> data, Page page) {  

this.data = data;  

// ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— 1๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ๊ฑธ๋กœ ๋ณ€๊ฒฝ  
this.pageInfo = new PageInfo(page.getNumber() + 1,  
page.getSize(), page.getTotalElements(), page.getTotalPages());  
}  
}

PageInfo

@AllArgsConstructor  
@Getter  
public class PageInfo {  

private int page;  
private int size;  
private long totalElements;  
private long totalPage;  

}

๊ฒฐ๊ณผ

 

ํŽ˜์ด์ง• ๋ฐ˜ํ™˜ํƒ€์ž…

Page<T> type

  • Page<T> ํƒ€์ž…์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด offset๊ณผ totalPage๋ฅผ ์ด์šฉํ•ด์„œ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ• ์ˆ˜์žˆ๋‹ค.
  • Page<T> ๋Š” ์ผ๋ฐ˜์ ์ธ ๊ฒŒ์‹œํŒ ํ˜•ํƒœ์˜ ํŽ˜์ด์ง•์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.
  • ์œ„์˜ ์˜ˆ์ œ ์ฝ”๋“œ์— ์ž‘์„ฑ๋œ๊ฒƒ์ด Pageํƒ€์ž…์œผ๋กœ ๋‚˜ํƒ€๋‚ธ๊ฒƒ์ด๋‹ค.
  • Page<T> ํƒ€์ž…์€ count์ฟผ๋ฆฌ๋ฅผ ํฌํ•จํ•˜๋Š” ํŽ˜์ด์ง•์œผ๋กœ count์ฟผ๋ฆฌ๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜์–ด ํ•จ๊ป˜ ๋‚˜๊ฐ„๋‹ค.

 

Slice<T> type

  • slice ํƒ€์ž…์„ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ๋ฐ›์œผ๋ฉด ๋”๋ณด๊ธฐ ํ˜•ํƒœ์˜ ํŽ˜์ด์ง•์œผ๋กœ ๋‚˜ํƒ€๋‚œ๋‹ค.

 

List<T> type

@GetMapping("/users") 
public List<User> getAllUsers(Pageable pageable) { 
return userRepository.findAll(pageable); }
  • List ๋ฐ˜ํ™˜ ํƒ€์ž…์€ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ count ์ฟผ๋ฆฌ ์—†์ด ๊ฒฐ๊ณผ๋งŒ ๋ฐ˜ํ™˜๋œ๋‹ค.
๋ฐ˜์‘ํ˜•