JPA Projection

황인우·2025년 2월 27일

프로젝트 중 팀원 한명이

Projection 이란 개념을 사용하면서 설명해주었다.

(프로젝트 코드)

@Repository
public interface AuthenticationRepository extends JpaRepository<Authentication, Long> {
    Optional<Authentication> findByUserId(Long userId);

    @Query("""
        SELECT 
            u.id AS id, 
            u.nickname AS nickname, 
            u.email AS email, 
            a.lastLogin AS lastLogin
        FROM Authentication a
        JOIN a.user u
        WHERE a.lastLogin BETWEEN :startDate AND :endDate
          AND u.isDeleted = false
    """)
    List<DormantAccountProjection> findDormantAccountsInDateRange(
            @Param("startDate") LocalDateTime startDate,
            @Param("endDate") LocalDateTime endDate
    );
}

Projection 은 JPA 에서 엔티티를 조회할 때

특정 필드만 조회하는 방법을 말한다.

전체를 조회하지 않기 때문에 성능 개선에 도움이 된다.


좀 더 간단한 예시

// 간단한 사용자 엔티티, 4개의 필드를 가지고 있다.
@Entity
public class SiteUser {
    Long id;
    String username;
    String email;
    String address;
}

// Projection 인터페이스
public interface UserProjection {
    Long getId();
    String getUsername();
}

// Projection을 사용해 전체 사용자 엔티티에서 id 와 username 만 조회
public interface UserRepository extends JpaRepository<SiteUser, Long> {
    Optional<UserProjection> findProjectionById(Long id);
}

// 조회한 사용자 엔티티를 가공할 서비스 클래스
@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;

    public UserProjection findUser(Long id) {
        return userRepository.findProjectionById(id).orElseThrow();
    }
}

DB에서 엔티티를 조회할 때

꼭 필요한 필드만 조회할 수 있다는 개념을 처음 알게 되었다.

하지만 그렇다고 모든 경우에 각각 메서드를 만들 수는 없으니,

어떤 정보가 자주 사용되고 자주 사용되지 않는지

비즈니스 로직과 엔티티을 두고

유지보수성과 성능 사이의 고민이 많이 필요한 것 같다.





*추가 : Projection은 무조건 사용할 수록 좋을까?

단순히 코드가 복잡해진다 말고 다른 단점은 없을까?

찾아보니

1. JPA의 기본 최적화 기능을 활용하지 못한다.

Lazy Loading, 캐싱, Batch Fetching 등의 기능은 엔티티에만 적용되기 때문에 Projection 과 전체 엔티티를 조회하는 성능이 크지 않을 수 있다.

2. 엔티티 수정이 필요한 경우

Projection 으로 조회한 데이터는 엔티티가 아니기 때문에

영속성 컨텍스트에서 관리되지 않아 수정하려면 다시 엔티티를 조회해야 한다.


등의 단점이 있었다.

그래서

수정 등이 없는 간단한 조회 요청을 구현할 때에

좀 더 적극적으로 사용해볼 수 있을 것 같다.

0개의 댓글