[ 구현 배경 ]
내가 작업하는 애니 리스트 페이지는 카드형 UI라서
한 화면에 많은 데이터를 한 번에 보여주지 않는다.
또한 검색(제목/줄거리), 정렬(최신/오래된/가나다),
페이지 이동이 함께 붙어 있기 때문에,
단순히 selectAll()로 전체를 내려보내는 방식은 금방 한계가 온다.
내가 선택한 방식을 요약하면 아래와 같다.
- 페이지 진입/검색 요청은 동기
→ 서버가 화면으로 보내는 흐름 - 페이지네이션으로 데이터 뽑는 건 비동기
→ JSON으로 필요한 부분만 가져오는 흐름
1. 전체 구조
구성 요소는 총 4개로 나뉜다.
1) AnimeListAction (동기)
- anime.jsp로 이동
- 검색인지 판단
- 검색인데 키워드 없으면 message.jsp 처리
- condition/keyword를 request로 넘겨서 “상태 유지”
2) anime.jsp (View)
- 화면 뼈대 렌더링
- JS에서 AnimeListDataAction을 AJAX로 호출
- 받은 JSON으로 카드 UI + 페이지바 생성
3) AnimeListDataAction (비동기)
JSON으로 “현재 페이지에 필요한 데이터만” 내려줌
검색/정렬/페이지네이션 계산까지 포함해서 내려줌
4) 기존 AnimeListFilter 제거 후 합침
정렬용 서블릿이 있었지만, 비동기 페이지네이션이 시작되면
정렬도 결국 같은 요청에서 처리하는 게 더 깔끔해서
AnimeListDataAction 에 합침
2. 왜 “검색/이동”은 동기로 두었나?
내 프로젝트에서 검색은 단순히 데이터만 바꾸는 게 아니라
“유효성 검증 + 상태 전환” 성격이 있었다.
1) 검색어 없는 검색 요청 차단
condition=ANIME_SEARCH_TITLE인데 keyword가 빈 값이면,
비동기에서 JSON으로 처리해도 되지만 UX/구조상 애매해진다.
나는 이 경우를 명확하게
- “검색 요청 자체가 잘못된 요청”
→ AnimeListAction에서 동기로 차단
→ message.jsp로 안내
즉, 검색 요청의 유효성 검증을 서버 진입부에서 끝내고
정상 요청만 anime.jsp로 보내는 방식이 더 명확했다.
2) 상태 유지가 쉬움
동기 이동을 거치면 request에
- condition (제목검색/줄거리검색/기본목록)
- keyword
를 담아서 anime.jsp로 넘겨줄 수 있다.
그럼 JS는 이 값을 그대로 사용해서
첫 페이지 데이터를 바로 불러올 수 있다.
3. 왜 “페이지네이션 데이터 추출”은 비동기로 했나?
애니 리스트는 카드 UI라서 페이지 이동이 잦고,
데이터도 많아질 가능성이 크다.
동기 페이지네이션으로도 가능하지만
비동기의 이점이 확실했다.
1) 페이지 이동이 빠름
동기: 페이지 버튼 클릭 → 전체 HTML 다시 렌더링
비동기: 페이지 버튼 클릭 → JSON만 가져와서 카드 목록만 교체
2) 정렬/검색/페이지네이션을 “한 번의 API”로 통합 가능
처음엔 정렬용 서블릿(AnimeListFilter)을 따로 두려 했는데,
비동기 페이지네이션을 하게 되면 결국 요청은 이렇게 된다.
- page=?
- condition=?
- keyword=?
- sort=?
이 값들로 “현재 화면이 원하는 데이터”를 딱 가져오는 게 목표라서
정렬도 결국 페이지네이션 요청에 포함시키는 게 가장 깔끔했다.
4. 최종 책임 분리 요약
▼ AnimeListAction (동기)
- “화면 진입 담당”
- 검색 요청 유효성 검증(키워드 없으면 차단)
- condition/keyword 상태 전달
- anime.jsp forward
▼ AnimeListDataAction (비동기 JSON)
- “데이터 제공 담당”
- 검색 조건 반영
- 정렬 반영
- 페이지네이션 계산
- 현재 페이지 데이터만 JSON으로 반환
(animeList + paging)
5. JSON 응답 설계
비동기 페이지네이션은
“리스트만” 보내면 페이지바를 만들 수 없다.
그래서 응답은 두 덩어리로 나눴다.
1) animeList : 현재 페이지에 보여줄 데이터 목록
2) paging : 페이지바 구성에 필요한 메타정보
paging 안에는 이런 값들이 들어간다.
- page / totalPage
- startPage / endPage
- hasPrev / hasNext
- condition / keyword / sort (상태 유지용)
결국 View는 paging만 보고 페이지바를 그릴 수 있고,
animeList만 보고 카드 UI를 그릴 수 있다.
6. 마무리
이 구조의 핵심은 “책임을 분리한 것”이다.
- 동기(페이지 이동/검증): 서버가 요청을 안전하게 정리
- 비동기(JSON 데이터): 화면에 필요한 만큼만 빠르게 교체
이렇게 나누니까 기능이 늘어나도(정렬 추가, 검색 조건 추가)
컨트롤러가 “한 파일에 다 때려박는 구조”로 망가지지 않고 확장 가능해졌다.
'개주 훈련일지 > 🏋️ 전집중 호흡 훈련' 카테고리의 다른 글
| 비밀번호 찾기 UX 개선: 아이디 확인 → 이메일 자동 세팅 → 인증코드 발송(AJAX/Servlet) (0) | 2025.12.31 |
|---|---|
| 동기 검색/이동+비동기 페이지네이션 적용기 (0) | 2025.12.30 |
| 프로필 이미지 변경 최종 확정 구현: temp→final 이동 + 캐시 차감 + 롤백 설계 (0) | 2025.12.25 |
| 프로필 이미지 업로드 UX 개선: 비동기 리사이징 미리보기 + 최종 확정 시 캐시 차감 연계 (0) | 2025.12.24 |
| 이미지 업로드 서블릿 만들기(JSP/Servlet + 자동 리사이즈 + 폴더 분기) (0) | 2025.12.24 |