[SpringBoot] 게시판 정렬 기능 구현하기[3]

Euiyeon Park·2025년 2월 9일
post-thumbnail

✨ 구현을 통한 학습 목표

  1. ✅ createdAt 컬럼 사용하기
  2. ✅ 정렬 기능
  3. 검색 기능
  4. 최대로 조회 가능한 데이터 개수 제한

✨ 최근 작성된 순서로 게시글 조회하기 - 정렬

  • 학습 목표와 요구사항을 봤을 때,
    정렬 기능최대로 조회 가능한 데이터 개수 제한을 보고
    무작정 페이지네이션으로 처리했었다.

  • 그런데 블로그를 작성하면서 생각하니,
    '우선은 정렬 기능만 구현하라는 건가?' 싶어서 수정했다.

  • 최근 작성된 순서로 게시글을 정렬하기 위해서는 createdAt 컬럼을 이용해야 한다.

💫 1. @Query를 사용한 정렬

📂 Controller.java

  • 게시글 전체 조회를 할 때 페이지네이션을 고려하지 않고, 정렬 기능만 구현한다면
    컨트롤러 레이어는 간단하게 작성할 수 있다.
    // 게시글 전체 조회 - 페이지네이션❌, 정렬⭕
    @GetMapping("/posts")
    public ResponseEntity<List<PostResponse>> getAllPosts(){
        return postService.getAllPosts();
    }

📂 Repository.java

  • JPQL을 사용해 전체 게시글을 조회하되, createdAt 컬럼을 기준으로 내림차순한다.
    @Query("SELECT p FROM Post p ORDER BY p.createdAt DESC")
    List<Post> findAll();

📂 Service.java

  • 레포지토리에서 findAll()로 조회한 모든 게시글을 Response DTO 형태로 변환하고 반환하면 끝!
    // 게시글 전체 조회 - 페이지네이션❌, 정렬⭕
    @Transactional(readOnly = true)
    public ResponseEntity<List<PostResponse>> getAllPosts(){
        List<PostResponse> postResponses = postRepository.findAll().stream()
                .map(PostResponse::new)
                .toList();
        return ResponseEntity.status(HttpStatus.OK).body(postResponses);
    }

💫 2. JPA Query Method를 사용한 정렬

📂 Repository.java

  • Spring Data JPA의 쿼리 메서드를 사용해 자동으로 쿼리 생성한다.
    List<Post> findAllByOrderByCreatedAtDesc();

📂 Service.java

  • Query Method를 사용할 경우, 서비스 레이어에서 사용하는 메서드만 변경하면 끝!
    // 게시글 전체 조회 - 페이지네이션❌, 정렬⭕
    @Transactional(readOnly = true)
    public ResponseEntity<List<PostResponse>> getAllPosts(){
        List<PostResponse> postResponses = postRepository.findAllByOrderByCreatedAtDesc().stream()
                .map(PostResponse::new)
                .toList();
        return ResponseEntity.status(HttpStatus.OK).body(postResponses);
    }

✨ @Query와 Query Method 더 알아보기

💫 @Query와 JPQL(Java Persistence Query Language)

JPQL

  • JPQL은 SQL과 유사하지만 테이블이 아니라 엔티티 객체를 대상으로 작성하는 쿼리 언어
  • JPQL은 테이블이 아닌 엔티티 클래스와 필드를 기준으로 작성한다.
  • 복잡한 조회 로직을 구성할 수 있으며, JOIN, GROUP BY, HAVING 등의 사용이 가능하다.

@Query

  • @Query는 Spring Data JPA에서 사용자 정의 JPQL을 작성할 때 사용하는 어노테이션
  • @Query를 사용하면 JPA가 제공하는 메서드 대신 명시적으로 정의한 쿼리를 실행할 수 있다.

[참고] @Param

  • @Param은 JPQL 또는 네이티브 쿼리에서 사용되는 바인딩 변수와 메서드 매개변수를 연결하는 역할
	@Query("SELECT u FROM User u WHERE u.username = :username")
	List<User> findByUsername(@Param("username") String username);

💫 Query Method

  • Query Method는 Spring Data JPA가 메서드 이름을 분석해 자동으로 SQL을 생성하는 기능
  • 메서드 네이밍만으로 원하는 데이터를 조회할 수 있다.
  • 개발자가 직접 SQL을 작성하지 않아도 되므로 간결한 코드 유지가 가능하다.

쿼리 메서드 동작 방식

  1. findBy, findAllBy, countBy, existBy 등의 키워드를 사용해 데이터를 조회한다.
  2. 뒤에 엔티티 필드명을 조합해 조건을 지정할 수 있다.
  3. Spring Data JPA가 네이밍을 분석해 SQL을 자동으로 생성한다.

쿼리 메서드 네이밍 규칙

📍Ref. priming님의 tistory

기본 조회

메서드SQL 변환
findByUsername(String username)WHERE username = ?
findByAgeGreaterThan(int age)WHERE age > ?
findByEmailContaining(String email)WHERE email LIKE %?%

AND, OR 조건

메서드SQL 변환
findByUsernameAndAge(String usernanme, int age)WHERE username = ? AND age = ?
findByUsernameOrEmail(String username, String email)WHERE username = ? OR email = ?

정렬

메서드SQL 변환
findByUsernameOrderByCreatedAtDesc(String username)WHERE username = ? ORDER BY created_at DESC
findAllByOrderByCreatedAtAsc()ORDER BY created_at ASC

범위 조건

메서드SQL 변환
findByUsername(String username)WHERE username = ?
findByAgeGreaterThan(int age)WHERE age > ?
findByEmailContaining(String email)WHERE email LIKE %?%

NULL값 처리

메서드SQL 변환
findByEmailIsNull()WHERE email IS NULL
findByEmailIsNotNull()WHERE email IS NOT NULL

LIMIT 처리(Top, First)

메서드SQL 변환
findTop3ByOrderByCreatedAtDesc()ORDER BY created_at DESC LIMIT 3
findFirstByOrderByAgeASC()ORDER BY age ASC LIMIT 1

💫 @Query(w. JPQL) vs Query Method 비교

비교 항목@Query(w. JPQL)Query Method
쿼리 생성 방식JPQL을 직접 작성Spring Data JPA가 자동 생성
유지보수성엔티티 변경 시 수동 수정 필요엔티티 변경 시 자동 반영
복잡한 쿼리복잡한 쿼리 작성 가능JOIN, GROUP BY 등의 작성이 어려움
성능 차이JPQL 최적화Spring Data JPA 최적화
  • 단순한 조회 및 정렬 : findBy, findAllByOrderBy 등 쿼리 메서드 사용
  • 복잡한 쿼리(JOIN, GROUP BY, HAVING 등) : @Query(w. JPQL) 사용
profile
"개발자는 해결사이자 발견자이다✨" - Michael C. Feathers

0개의 댓글