# Spring Data JPA: DB 님, 안 쓰는 컬럼은 빼고 주세요 (JPA Projection)

# JPA Repository로 조회하기

👩‍🎓 이런 글을 보시는 분들은 대부분 JPA Repository의 기본 조회 요령을 아실 것 같습니다만, 그래도 기본 전제는 공유해야 글에 좋겠죠.

✨ **JPA Repository는** 기본적으로 몇 가지 조회 메서드를 제공하고, 또 **<mark>네이밍 규칙만 따르면</mark> 알맞게 동작하는 <mark>커스텀 조회 메서드</mark>를 추가할 수 있습니다**. 다음은 네이밍 규칙의 간단한 예시입니다.

```java
findImSoCoolByUsername(String username);
```

* `find`로 시작: 조회하겠단 뜻입니다.
    
* `ImSoCool`: 몇 가지 키워드 또는 구분할 아무 말을 적는 영역입니다.
    
* `By`부터는 `SQL`의 `WHERE`절에 가까운 역할입니다.
    

쉽죠? 정리하면 이런 느낌이에요.

`find` + `몇_가지_키워드_또는_구분할_아무_말` + `By` + `필드_이름_등` + `(필드_목록 등 매개변수);`

그러면 조회 동작을 알아서 수행해 줍니다! 아주 편리하죠.

```java
// 예시 코드
public interface ExampleRepository extends JpaRepository<ExampleEntity, Long> {
    // 페이징을 하고, List 타입으로 목록 조회하는 메서드 예시
    List<ExampleEntity> findByStatus(Status status, Pageable pageable);
}
```

반환하는 행 수에 관한 제어는 이런 정도만 먼저 알아 둡시다.

* 단건 조회 반환 타입은 `Optional<엔티티타입>` 사용을 권합니다.
    
* 목록 조회 반환 타입은 `List<엔티티타입>`, `Page<엔티티타입>` 등을 권합니다.  
    (`Page<엔티티타입>` 반환은 조회 구간 퍼포먼스에 두 배 이상 안 좋을 수 있어요.)
    
* `Page<엔티티타입>`으로 반환하는 게 아니어도 인자에 `Pageable`을 추가하면 페이징이 됩니다.
    

---

# 🎦 Projection(프로젝션)이란?

프로젝션이라는 것은 수학이나 프로그래밍 등에서도 아래 그림처럼 일면(一面)이 투영되는 것을 뜻하죠.

![엑스축과 와이축으로 된 좌표평면에서 벡터가 화살표 모양으로 하나 표현되어 있고, 이 벡터가 엑스 축에 대해서 수직으로 그림자를 내리고 있습니다. 이 그림자 쪽에는 "엑스에 대한 부분적인 투영"이라고 쓰여 있어요. 영어로는 파셜 프로젝션 투 엑스입니다. 표기는 영어로 되어 있어요.](https://cdn.hashnode.com/res/hashnode/image/upload/v1699848680192/231266e0-a4bf-454b-855d-dbd88a7a0fff.png align="center")

위 그림은 벡터(방향과 크기가 있는 선)에서 `x`**<mark>축에 대해서만 값이 궁금할 때</mark>**`x`축 관점에서 본 벡터를 표현했습니다. 그리고 이 해석을 수학에서 '**프로젝션**(projection)'이라고 불러요. 그러면 보통 벡터의 원래 길이보다 짧은, '부분적인' 길이가 됩니다.

**우리에게 <mark>필요한 부분에 대해서만</mark> 값을 산출한 셈이죠.**

데이터베이스에서의 프로젝션도 비슷하게 생각해 볼까요? "우리에게 필요한 부분에 대해서만" 바라보겠다! **<mark>테이블의 전체가 아니라, 필요한 일부 컬럼만</mark>** 바라보고 싶다! 이것을 프로젝션이라는 이름으로 부르고 있습니다. 아래 그림처럼요.

![약간 입체화된 그림입니다. 이 그림에서 뒤쪽 패널에는 오리진 테이블이라는 텍스트가 위에 떠 있고, 패널은 전체적으로 회색 계열로 옅게 표현돼 있습니다. 거기에는 다섯 개의 컬럼으로 된 테이블이 있어요. 그 패널의 앞쪽으로는 색채를 띤 세 컬럼이 앞으로 복사돼 있어요. 그러니까 오리진 테이블의 다섯 개의 컬럼 중 왼쪽 세 컬럼만 앞쪽으로 색채를 띤 채 복사되어 있죠. 이 색채를 띤 세 컬럼이 프로젝션입니다. 프로젝션이라는 글씨가 세 컬럼의 아래에 쓰여 있어요.](https://cdn.hashnode.com/res/hashnode/image/upload/v1699836034941/510ee5f7-0713-4f39-a688-f8fa7b70642e.png align="center")

## JPA Projection으로 조회하기 (녯날 버죤)

자바 16 미만(또는 14 Preview 미만)에서는 `record`라는 MZ한 클래스 유형 대신 일반 클래스나 `interface`를 사용했습니다. <mark>게터(</mark>`getter`<mark>) 양식을 그대로 적용</mark>했죠.

```java
// 별도 애노테이션 없어도 됩니다.
public interface ExampleProjection {
    Long getId(); // id
    String getName(); // name
    String getNickname(); // nickname
    ExampleStatus getStatus(); // status (enum)
}
```

이런 표기는 작은 예시에선 편하고 쉬워 보여도 많은 컬럼 표기에는 불편했을 거예요. 그래도 만들고 나면, 사용할 땐 이렇게 간단하게 반환 타입으로 쓰기만 하면 알아서 부분적인 조회가 됐습니다.

```java
public interface ExampleRepository extends JpaRepository<ExampleEntity, Long> {
    List<ExampleProjection> findAllExamplesByStatus(ExampleStatus status, Pageable pageable);
}
```

`Optional<Projection>`이든 `List<Projection>`이든 `Page<Projection>`이든 잘 작동합니다!

## 요즘 세대의 JPA Projection

JDK 16 공식 릴리스 이상 또는 JDK 14~15에서 Preview로 사용할 수 있는 `record`를 쓸 수 있죠.

**정말 이걸로 완성?!** 🥳 **이것은 나를 놀라게 하다.**

```java
@Builder
public record ExampleProjection(Long id, String name, String nickname) {
}
```

😲 엥, 다 만들었어요 🥳 이거 정말 엔티티 클래스에서 복붙만 해도 금방 만들겠네요? MZ 세대의 인텔리제이와 함께라면 왠지 휠 클릭이나 다중 키보드 커서로 더 빨리 만들 것 같아요. **이것은 쉬운! 나는 이제 프로젝션을 쉽게 만들다!**

## 📦 프로젝션 모아 두기

스타일에 따라선 파일을 낱개로 여러 개 만드는 것보다 어느 정도 단위로 모아서 관리하는 분들도 있어요.

```java
public final class ExampleProjections {
    // not open any constructors
    private ExampleProjections() {}

    @Builder
    public record ExampleListViewProjection( ... ) {}

    @Builder
    public record ExampleDetailViewProjection( ... ) {}
}
```

이때 탑레벨 클래스는 `final` 클래스로 상속이 안 되게 하고, 생성자는 `private`으로 선언해서 객체 생성이 없게 하면 좋을 것 같아요.

대신 그렇게 중요한 조치는 아니기 때문에 편의상 (아이콘 바꾸려고라도) 탑레벨 `record` 안에 내부 `record` 구성으로 하기도 하죠. `record`는 어차피 `final` 클래스고 빈 레코드 객체 생성은 (함수도 안 만들었을 테니까) 특별한 의미가 없어서 안 할 거거든요.

```java
public record ExampleProjections() {
    @Builder
    public record ExampleListViewProjection( ... ) {}

    @Builder
    public record ExampleDetailViewProjection( ... ) {}
}
```

이런 건 모두 취향 차이니까, 팀 내에서 스타일을 정해서 해 보면 좋겠습니다!

🕶 프로젝션 만들기, 생각보다 쉽죠?

---

자료는 모두 DALL·E, excalidraw, Power Point 등을 통해 스스로 만들었습니다. (그래서 영어가 어색할 수 있습니다.) 어색한 영어 문장은 남대문 열렸다고 알려 주듯 살짝 말씀해 주시면 얼른 고쳐 보겠습니다. 그러면 다들 모쪼록 착한 개발 하세요.
