Spring Data JPA에서 중요한 개념 중 하나인 'Projection'에 대해서 공부를 하고 작성해 본다

Projection 어노테이션은 Spring Data REST에서 제공하는 기능으로, 특정 리소스의 표현을 커스터마이징 할 때 사용한다.
이 어노테이션을 활용하면 엔티티의 일부 필드를 추출하거나, 필드를 합치거나, 복잡한 값을 단순화하는 등의 작업을 할 수 있다.
이를 통해 API 응답에 특정 형태의 데이터를 제공하도록 커스텀 뷰를 정의할 수 있다.
@Projection 어노테이션에는 위에 사진처럼 'name'과 'types'이라는 속성이 있다.
- 'name' : 프로젝션의 이름이다. 이 이름은 클라이언트가 API 호출 시 URL에 사용하여 특정 프로젝션을 요청할 수 있다.
- 'types' : 프로젝션을 적용할 엔티티의 클래스이다. 프로젝션은 이 클래스 타입의 객체에 적용된다.
Projections의 사용 이유
데이터베이스에서 모든 필드를 가져와서 사용하는 것이 아니라, 필요한 데이터만 선택적으로 가져올 수 있다. 이를 통해서 불필요한 데이터 전송을 줄여 성능을 향상할 수 있다. 또한 특정 데이터를 숨기는데도 사용될 수 있다.
@Projection이 없다고 해서 특정 필드를 반환할 수 없는 것은 아니다. Spring Data JPA는 기본적으로 엔티티의 모든 필드를 반환한다. 하지만 특정 필드만 반환하거나, 데이터를 커스터마이징하여 반환하는 데는 여러 가지 방법이 있다.
- DTO 사용 : 서비스나 컨트롤러 레벨에서 DTO를 사용하여 필요한 데이터만 포함하고 반환할 수 있다.
- @Query 사용 : 리포지터리 인터페이스에 '@Query'를 사용하여 JPQL이나 SQL을 직접 작성하는 방법도 있다.
- @JsonView 사용 : Jackson 라이브러리를 사용할 때 '@JsonView'를 사용하여 JSON 출력 시 특정 필드를 포함하거나 제외할 수 있다.
@Projection 사용 시 장점
- 커스텀 뷰 제공 : 일부 필드만 필요할 때, 서버에서 해당 필드만 선택해서 전달할 수 있다. 이렇게 하면 불필요한 데이터를 받아 처리하는 부하를 줄일 수 있다.
- 성능 향상 : 필요한 필드만 선택하는 게 전체 엔티티를 가져오는 것보다 성능면에서 효율적이다
- 응답의 유연성 : 요구하는 데이터 형태에 따라 여러 프로젝션을 만들어 유연하게 응답할 수 있다.
- 데이터 보안 : 특정 필드(비밀번호, 신용카드 번호 등)를 공개하지 않도록 제어할 수 있다.
- 데이터 중복 최소화 : 프로젝션을 통해 중복된 데이터 전송을 피하고 데이터 전송량을 최소화할 수 있다.
- 가독성 : Projection 클래스나 인터페이스를 보면 어떤 데이터가 클라이언트에게 제공되는지 쉽게 이해할 수 있다.
@Projection 사용 예시
// User Entity
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
private String email;
private String password;
// 게터 세터 ...
}
User 엔티티 클래스를 만든다
// UserProjection Interface
@Projection(name = "withoutPassword", types = User.class)
public interface UserProjection {
String getFirstName();
String getLastName();
String getEmail();
}
'User' 엔티티에서 'firstname' , 'lastname' 그리고 'email'만 반환하는 프로젝션 인터페이스를 만든다
// UserRepository Interface
@RepositoryRestResource(excerptProjection = UserProjection.class)
public interface UserRepository extends JpaRepository<User, Long> {
}
@RepositoryRestResource 어노테이션을 사용하여 'excerptProjection'을 'UserProjection'으로 설정하면 이 레포지터리를 통해 가져온 'User' 엔티티는 'UserProjection'에 따라 프로젝션이 적용되어 반환된다.
Spring Data JPA에서 중요한 개념 중 하나인 'Projection'에 대해서 공부를 하고 작성해 본다

Projection 어노테이션은 Spring Data REST에서 제공하는 기능으로, 특정 리소스의 표현을 커스터마이징 할 때 사용한다.
이 어노테이션을 활용하면 엔티티의 일부 필드를 추출하거나, 필드를 합치거나, 복잡한 값을 단순화하는 등의 작업을 할 수 있다.
이를 통해 API 응답에 특정 형태의 데이터를 제공하도록 커스텀 뷰를 정의할 수 있다.
@Projection 어노테이션에는 위에 사진처럼 'name'과 'types'이라는 속성이 있다.
- 'name' : 프로젝션의 이름이다. 이 이름은 클라이언트가 API 호출 시 URL에 사용하여 특정 프로젝션을 요청할 수 있다.
- 'types' : 프로젝션을 적용할 엔티티의 클래스이다. 프로젝션은 이 클래스 타입의 객체에 적용된다.
Projections의 사용 이유
데이터베이스에서 모든 필드를 가져와서 사용하는 것이 아니라, 필요한 데이터만 선택적으로 가져올 수 있다. 이를 통해서 불필요한 데이터 전송을 줄여 성능을 향상할 수 있다. 또한 특정 데이터를 숨기는데도 사용될 수 있다.
@Projection이 없다고 해서 특정 필드를 반환할 수 없는 것은 아니다. Spring Data JPA는 기본적으로 엔티티의 모든 필드를 반환한다. 하지만 특정 필드만 반환하거나, 데이터를 커스터마이징하여 반환하는 데는 여러 가지 방법이 있다.
- DTO 사용 : 서비스나 컨트롤러 레벨에서 DTO를 사용하여 필요한 데이터만 포함하고 반환할 수 있다.
- @Query 사용 : 리포지터리 인터페이스에 '@Query'를 사용하여 JPQL이나 SQL을 직접 작성하는 방법도 있다.
- @JsonView 사용 : Jackson 라이브러리를 사용할 때 '@JsonView'를 사용하여 JSON 출력 시 특정 필드를 포함하거나 제외할 수 있다.
@Projection 사용 시 장점
- 커스텀 뷰 제공 : 일부 필드만 필요할 때, 서버에서 해당 필드만 선택해서 전달할 수 있다. 이렇게 하면 불필요한 데이터를 받아 처리하는 부하를 줄일 수 있다.
- 성능 향상 : 필요한 필드만 선택하는 게 전체 엔티티를 가져오는 것보다 성능면에서 효율적이다
- 응답의 유연성 : 요구하는 데이터 형태에 따라 여러 프로젝션을 만들어 유연하게 응답할 수 있다.
- 데이터 보안 : 특정 필드(비밀번호, 신용카드 번호 등)를 공개하지 않도록 제어할 수 있다.
- 데이터 중복 최소화 : 프로젝션을 통해 중복된 데이터 전송을 피하고 데이터 전송량을 최소화할 수 있다.
- 가독성 : Projection 클래스나 인터페이스를 보면 어떤 데이터가 클라이언트에게 제공되는지 쉽게 이해할 수 있다.
@Projection 사용 예시
// User Entity @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String firstName; private String lastName; private String email; private String password; // 게터 세터 ... }
User 엔티티 클래스를 만든다
// UserProjection Interface @Projection(name = "withoutPassword", types = User.class) public interface UserProjection { String getFirstName(); String getLastName(); String getEmail(); }
'User' 엔티티에서 'firstname' , 'lastname' 그리고 'email'만 반환하는 프로젝션 인터페이스를 만든다
// UserRepository Interface @RepositoryRestResource(excerptProjection = UserProjection.class) public interface UserRepository extends JpaRepository<User, Long> { }
@RepositoryRestResource 어노테이션을 사용하여 'excerptProjection'을 'UserProjection'으로 설정하면 이 레포지터리를 통해 가져온 'User' 엔티티는 'UserProjection'에 따라 프로젝션이 적용되어 반환된다.