Skip to content

[Refactor/#160] 공지 커서 목록 쿼리를 하나로 통합 - #161

Merged
jjunh33 merged 2 commits into
mainfrom
refactor/#160-merge-notice-slice-queries
Oct 22, 2026
Merged

jjunh33 merged 2 commits into
mainfrom
refactor/#160-merge-notice-slice-queries

Conversation

@jjunh33

@jjunh33 jjunh33 commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator

#️⃣연관된 이슈

🎯 해결하려는 문제가 무엇인가요?

공지 커서 목록이 첫 페이지용 findFirstSlice와 다음 페이지용 findNextSlice 두 쿼리로 나뉘어 있습니다. 카테고리 조건과 정렬은 같고 커서 조건만 다른데, 조건을 바꿀 때마다 두 곳을 똑같이 고쳐야 합니다. 물품 목록(ItemJpaRepository.findSlice)은 이미 커서 파라미터가 null이면 첫 페이지로 동작하는 하나의 쿼리를 씁니다.

❓ 왜 해결해야 하나요?

목록 조건(예: 제목 검색)을 추가하려면 두 쿼리를 함께 고쳐야 하고, 한쪽만 고치면 첫 페이지와 다음 페이지의 필터가 어긋납니다. 쿼리 하나로 모으면 이 위험이 사라집니다. 급한 작업은 아니고 유지 보수를 위한 정리입니다.

⭐ 어떻게 해결했나요?

  • NoticeJpaRepository: findFirstSlice/findNextSlice를 findSlice 하나로 합쳤습니다. 커서가 없으면(:cursorId IS NULL) 커서 조건이 빠져 첫 페이지가 되고, 있으면 기존과 같은 세 단계 키셋 조건(pinned → createdAt → id)으로 다음 페이지를 읽습니다. 카테고리 조건과 정렬은 그대로입니다.
  • cursorPinned를 Boolean으로: null을 받을 수 있게 기본형 boolean에서 래퍼로 바꿨습니다.
  • NoticeRepositoryImpl: 커서가 있으면 pinned·createdAt·id를 풀어서, 없으면 세 값 모두 null로 findSlice를 한 번 호출합니다. 분기하던 삼항식이 사라집니다.

동작을 바꾸지 않는 리팩토링입니다.

🧩 이 PR의 한계 & 트레이드오프

  • MySQL로 확인하지 못했습니다. 로컬에 Docker가 없어 H2 임시 테스트(커밋하지 않음)로만 확인했습니다. null로 바인딩한 Boolean/LocalDateTime 파라미터가 IS NULL과 비교식에서 문제없는지는 dev에서 확인이 필요합니다. 물품 쿼리가 같은 패턴을 문자열·정수로 이미 쓰고 있어 위험은 낮다고 봅니다.
  • 커서의 세 값은 함께 넘겨야 합니다. 쿼리는 cursorId만 보고 첫 페이지 여부를 정하므로, 세 값 중 일부만 null인 호출은 의도와 다르게 동작합니다. 호출부(NoticeRepositoryImpl)가 항상 세 값을 함께 넘기도록 했고, 이 규칙은 쿼리 위 주석에 적었습니다.
  • 한 쿼리 안에 "첫 페이지"와 "다음 페이지"가 섞여 읽기가 조금 어려워집니다. 대신 물품 목록과 같은 패턴이 됩니다.
  • 새 테스트는 추가하지 않았습니다.
  • [Feat/#142] 게시판(공지) 관리자 API 보완 - 고정 여부 반영 및 동시 수정 제어 #143, #145와 충돌합니다. #143이 같은 파일(NoticeJpaRepository.java)에 관리자 목록 search 쿼리를 추가해서, 이 PR과 [Feat/#142] 게시판(공지) 관리자 API 보완 - 고정 여부 반영 및 동시 수정 제어 #143 중 나중에 머지되는 쪽이 이 파일의 충돌(서로 다른 쿼리를 나란히 두는 단순한 충돌)을 정리해야 합니다.

⛓️ 기존 기능에 미치는 영향

  • API 경로·요청·응답, 정렬, 커서 형식이 모두 그대로입니다. 학생 앱 공지 목록의 동작이 같습니다.
  • NoticeJpaRepository(infrastructure:db 내부)의 메서드가 findFirstSlice/findNextSlice → findSlice로 바뀝니다. 이를 쓰는 곳은 NoticeRepositoryImpl뿐입니다.
  • 스키마 변경·마이그레이션은 없습니다.

🔀 Edge Case & 실패 시나리오

상황 결과
커서 없음 (첫 페이지) 커서 조건이 빠져 정렬 순서의 앞에서부터 조회
커서 있음 커서 위치 다음부터 조회 (기존과 동일)
pinned가 같은 공지끼리 createdAt이 같음 id 내림차순으로 구분 (기존과 동일)
삭제된 공지 두 경우 모두 제외
카테고리 필터 + 커서 두 경우 모두 필터가 적용됨

📋 검토한 대안과 선택 이유

  • 두 쿼리 유지: 지금 상태. 조건을 추가할 때 두 곳을 고쳐야 하는 문제가 남습니다.
  • ItemJpaRepository처럼 커서 값을 개별 파라미터 null 가드로 합치기(채택): 쿼리 하나로 모이고 물품과 같은 패턴입니다.
  • Specification/QueryDSL 등 동적 쿼리: 이 정도 분기에 새 도구를 들이는 것은 과하다고 보고 제외했습니다.

💬 리뷰 포인트

  • [r] 합친 JPQL이 dev(MySQL)에서 정상 기동·조회되는지. 특히 첫 페이지(커서 null)와 다음 페이지 모두
  • [c] 커서 세 값을 함께 넘겨야 한다는 전제를 쿼리 주석과 호출부에 두는 방식으로 충분한지
  • [a] findSlice 이름

@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jjunh33
jjunh33 merged commit f8f2943 into main Oct 22, 2026
1 check passed
@jjunh33
jjunh33 deleted the refactor/#160-merge-notice-slice-queries branch October 22, 2026 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

공지 커서 목록 쿼리를 하나로 통합

2 participants