목차
요구사항
설명
- ✅ 많은 양의 데이터를 효율적으로 표시하기 위해 데이터를 여러 페이지로 나눕니다.
- ✅ 페이지 번호와 페이지 크기를 쿼리 파라미터로 전달하여 요청하는 항목을 나타냅니다.
- ✅ 전달받은 페이지 번호와 크기를 기준으로 쿼리를 작성하여 필요한 데이터만을 조회하고 반환
조건
- ✅ 등록된 일정 목록을 페이지 번호와 크기를 기준으로 모두 조회
- ✅ 조회한 일정 목록에는 작성자 이름이 포함
- ✅ 범위를 넘어선 페이지를 요청하는 경우 빈 배열을 반환
- ✅ Paging 객체를 활용할 수 있음
요구 구현
가독성을 위해 다른 구현 코드는 넣지 않고 페이지네이션 기능을하는 코드만 넣었습니다.
ScheduleController
@GetMapping("/pages")
@ResponseBody
public List<ScheduleResponseDto> pagination (
@RequestParam("pageNum") int pageNum,
@RequestParam("pageSize") int pageSize
) {
Paging paging = new Paging(pageNum, pageSize);
return scheduleService.pagination(paging);
}
- 쿼리 파라미터로 값을 전달받기 위해 @RequestParam을 사용하였습니다. ("pageNum", "pageSize" : 생략 가능)
- 페이지 번호와 크기 2가지를 받아야하므로, `pageNum`과 `pageSize` 2개의 변수를 활용하였습니다.
- 여러 개의 데이터를 반환받아야하므로 반환타입은 List입니다.
ScheduleService
public interface ScheduleService {
List<ScheduleResponseDto> pagination (Paging paging);
}
- 추후 다른 Service를 고려하여, 인터페이스를 통해 서비스 클래스가 구현하도록 설계했습니다. (객체지향 다형성)
ScheduleServiceImpl
@Service
public class ScheduleServiceImpl implements ScheduleService{
private final ScheduleRepository scheduleRepository;
public ScheduleServiceImpl(ScheduleRepository scheduleRepository) {
this.scheduleRepository = scheduleRepository;
}
@Override
public List<ScheduleResponseDto> pagination(Paging paging) {
return scheduleRepository.pagination(paging);
}
}
- 처리해야할 서비스 로직이 없으므로, repository로 `Paging` 객체를 넘겨줍니다.
ScheduleRepository
public interface ScheduleRepository {
List<ScheduleResponseDto> pagination(Paging paging);
}
JdbcTemplateScheduleRepository
@Repository
public class JdbcTemplateScheduleRepository implements ScheduleRepository{
private final JdbcTemplate jdbcTemplate;
public JdbcTemplateScheduleRepository(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public List<ScheduleResponseDto> pagination(Paging paging) {
String sql = "select * from schedule ORDER BY updateAt DESC LIMIT ? OFFSET ?";
int pageLimit = paging.getPageSize();
int pageOffset = (paging.getPageNum()-1) * paging.getPageSize();
return jdbcTemplate.query(sql, scheduleRowMapper(), pageLimit, pageOffset);
}
}
- 몇 번 페이지 : `(pageNum - 1) * pageSize`
- 몇 개의 데이터 : `pageSize`
트러블 슈팅
1. BeanCreationException 오류
설명
@RestController
@RequestMapping("/schedules")
public class ScheduleController {
...
@GetMapping
public List<ScheduleResponseDto> findAllSchedule() {
return scheduleService.findAllSchedules();
}
...
@GetMapping
@ResponseBody
public List<ScheduleResponseDto> pagination (
@RequestParam("pageNum") int pageNum,
@RequestParam("pageSize") int pageSize
) {
Paging paging = new Paging(pageNum, pageSize);
return scheduleService.pagination(paging);
}
다음과 같이 동일 url("/schedules")에서 동일한 `@GetMapping`을 사용하여, 서버를 작동시켰을 때, 다음과 같이`BeanCreationException` 오류가 발생하였습니다.
문제
Spring MVC는 내부적으로 `RequestMappingHandlerMapping`이라는 컴포넌트를 사용하여 각 컨트롤러의 `@RequestMapping`, `@GetMapping`, `@PostMapping` 등의 정보를 등록하고 관리합니다.
Spring은 애플리케이션이 시작될 때, 모든 `@Controller` 혹은 `@RestController` 빈을 스캔합니다.
각 메서드에 붙은 `@RequestMapping`, `@GetMapping` 등의 어노테이션 정보를 기반으로, URL + HTTP Method + 조건(예: params) 조합을 키로 하여 내부 매핑 테이블을 구성합니다.
@GetMapping("/schedules")
public List<ScheduleResponseDto> findAllSchedule()
@GetMapping("/schedules")
public List<ScheduleResponseDto> pagination(@RequestParam int pageNum, ...)
둘 다 `GET /schedules`로 매핑되므로, 내부적으로는 같은 키가 두 번 등록되며 충돌이 발생합니다.
URL 매핑 충돌로 인해 `BeanCreationException`이 발생하였습니다.
해결
다른 하나의 메서드의 경로("/pages)를 추가하여 문제를 해결하였습니다.
'Project' 카테고리의 다른 글
[Project] Lv_6 스케줄 프로젝트 (0) | 2025.05.13 |
---|---|
[Project] Lv_5 스케줄 프로젝트 (0) | 2025.05.13 |
[Project] Lv_3 스케줄 프로젝트 (2) | 2025.05.12 |
[Project] Lv_3 스케줄 프로젝트 : ERD 재설계 (0) | 2025.05.12 |
[Project] Lv_1 스케줄 프로젝트 (0) | 2025.05.11 |