PrismaORM GetPayload Generic Typing

Prisma GetPayload 기반 쿼리 결과 타입 정의 가이드

1. 문서 목적

이 문서는 Prisma Client 사용 시
Prisma.<Model>GetPayload<T> 타입을 어떻게, 왜, 어디까지 사용해야 하는지를 명확히 규정하기 위한 문서다.

특히 다음 문제를 방지하는 것을 목표로 한다.


2. 문제 정의: Prisma 모델 타입은 쿼리 결과 타입이 아니다

Prisma는 기본적으로 다음 두 가지를 제공한다.

import { TicketHistory } from '@prisma/client';

이 타입은 다음을 의미한다.

즉, 이 타입은 “테이블 정의” 이지 쿼리 결과 가 아니다.

그럼에도 불구하고 이 타입을 Service / UseCase / Controller에서 그대로 사용하는 경우가 많고,
이 시점부터 타입 안정성은 사실상 포기 상태가 된다.


3. GetPayload<T>의 역할과 책임

3.1 정체성

Prisma.<Model>GetPayload<T>

이 타입은 다음을 의미한다.

Prisma Client가 특정 쿼리를 실행했을 때 반환하는 결과 객체의 정확한 타입

여기서 중요한 점은:


3.2 제네릭 T의 의미

T는 Prisma query argument의 타입적 부분집합이다.

{
  select?: ...
  include?: ...
}

4. 예제 분석

export type TicketHistoryWithRecordingConsents =
  Prisma.TicketHistoryGetPayload<{
    include: {
      recordingConsent: {
        select: {
          phone: true;
          consent: true;
        };
      };
    };
  }>;

이 타입은 다음을 타입 레벨에서 선언한다.

즉, 이 타입은 다음 Prisma 쿼리와 1:1 대응한다.

prisma.ticketHistory.findMany({
  include: {
    recordingConsent: {
      select: { phone: true, consent: true },
    },
  },
});

이 대응 관계가 깨지는 순간, 타입 정의는 잘못된 것이다.


5. includeselect의 역할 분리

5.1 include

5.2 select

5.3 자주 발생하는 오해


6. Nullable 관계에 대한 인식

Prisma에서 관계는 기본적으로 nullable이다.

recordingConsent: {
  phone: string;
  consent: boolean;
} | null

| null타입 오류가 아니라 현실 반영이다.

타입은 거짓말을 하지 않는다.
거짓말을 하는 건 개발자다.


7. 사용 위치 가이드라인

7.1 사용해야 하는 곳

이 타입은 **“조회 결과 명세”**로 사용한다.


7.2 사용하면 안 되는 곳

GetPayload는 Prisma에 종속된 타입이다.
도메인으로 올라오는 순간, 의존성 역전 원칙이 깨진다.


8. 네이밍 규칙 (강제)

다음과 같은 이름은 피한다.

TicketHistoryWithSomething

이름만 보고:

판단이 불가능하다.

권장 패턴

TicketHistoryWithRecordingConsentRow
TicketHistoryRecordingConsentProjection
TicketHistoryWithRecordingConsentForAdminQuery

**“쿼리 컨텍스트” 또는 “읽기 목적”**이 반드시 드러나야 한다.


9. 이 타입의 본질

정리하면 이 타입은:

이다.

이 타입은 오직 하나다.

“이 쿼리가 반환하는 데이터의 계약서”

쿼리가 바뀌면 타입도 바뀌어야 한다.
타입이 고정되길 원한다면, 그건 이미 DTO 계층의 책임이다.


10. 결론

타입은 편의를 위해 존재하지 않는다.
의도를 고정하기 위해 존재한다.


다음으로 이어갈 수 있는 주제는 명확하다.

On this page
Prisma GetPayload 기반 쿼리 결과 타입 정의 가이드
  • 1. 문서 목적
  • 2. 문제 정의: Prisma 모델 타입은 쿼리 결과 타입이 아니다
  • 3. GetPayload의 역할과 책임
    1. 3.1 정체성
    2. 3.2 제네릭 T의 의미
  • 4. 예제 분석
  • 5. include와 select의 역할 분리
    1. 5.1 include
    2. 5.2 select
    3. 5.3 자주 발생하는 오해
  • 6. Nullable 관계에 대한 인식
  • 7. 사용 위치 가이드라인
    1. 7.1 사용해야 하는 곳
    2. 7.2 사용하면 안 되는 곳
  • 8. 네이밍 규칙 (강제)
    1. 권장 패턴
  • 9. 이 타입의 본질
  • 10. 결론