HooneyLog
© 2026 Seunghoon Shin. All rights reserved.
모든 게시글
Backend
2026. 3. 28.•
12

Prisma에는 임베디드 엔티티가 없다? 복합 객체를 다루는 최선의 방법

Seunghoon Shin
작성자 Seunghoon Shin풀스택 개발자

Prisma에는 임베디드 엔티티가 없다? 복합 객체를 다루는 최선의 방법

1. 문제의 배경

TypeORM을 사용하다 보면 @Entity() 내부에 @Column(type => Address) 같은 식으로 공통된 필드 집합을 재사용하는 임베디드 엔티티(Embedded Entities) 기능을 자주 활용하게 됩니다. 예를 들어 User 테이블과 Company 테이블에 공통으로 들어가는 '주소(도로명, 상세주소, 우편번호)' 정보를 하나의 클래스로 묶어 관리하는 방식이죠.

하지만 Prisma를 처음 접하면 당황하게 됩니다. schema.prisma 파일에는 이처럼 다른 모델의 필드들을 '포함' 시키는 기능이 명시적으로 존재하지 않기 때문입니다. "그럼 주소 필드 5개를 매번 복사해서 써야 하나요?"라는 의문이 생기는 시점이 바로 이때입니다.

2. 해결 방안 탐색

Prisma에서 복합 객체(Composite Objects)를 다루기 위해 우리는 주로 세 가지 대안을 고려합니다.

  1. 필드 직접 나열 (Flat Structure): 단순하지만 중복이 발생합니다.
  2. 1:1 관계 설정 (Relation): 데이터가 정규화되지만 조인(Join) 비용이 발생합니다.
  3. JSON 타입 활용 (PostgreSQL JSONB): 하나의 컬럼에 객체 형태로 쏟아붓습니다.
  4. Composite Types (MongoDB 전용): MongoDB를 쓴다면 Prisma도 공식적으로 임베디드 문법을 지원합니다. (RDB는 미지원)

우리는 RDB(PostgreSQL/Supabase) 환경에서 가장 현실적이고 강력한 대안인 1:1 관계와 JSON 타입을 집중적으로 살펴보겠습니다.

3. 핵심 개념 및 아키텍처

1) 1:1 관계 (추천하는 정석적인 방법)

데이터베이스의 정규화 원칙을 따르면서도 객체지향적인 설계를 유지할 수 있습니다.

2) JSONB 타입 활용 (유연함이 필요할 때)

PostgreSQL의 강력한 기능인 JSONB를 사용하여 스키마 제약 없이 복합 객체를 저장합니다.

4. 구현 및 트러블슈팅

1) 1:1 관계 구현 (RDB 방식)

// schema.prisma model User { id Int @id @default(autoincrement()) email String @unique address Address? // 1:1 관계 } model Address { id Int @id @default(autoincrement()) city String street String zipCode String user User @relation(fields: [userId], references: [id]) userId Int @unique // 반드시 unique여야 1:1이 성립합니다. }

2) JSON 타입을 이용한 유사 임베딩

만약 주소의 필드가 자주 바뀌거나 정규화가 과하다고 느껴진다면 JSONB 컬럼을 사용합니다. 단, 이 경우 Prisma의 강력한 타입 지원을 100% 받으려면 별도의 TypeScript 타입 캐스팅이 필요합니다.

model User { id Int @id @default(autoincrement()) // PostgreSQL의 JSONB 타입을 사용합니다. address Json? }

5. 결과 및 Trade-off

방식장점단점
1:1 관계타입 안전성이 완벽함, SQL 쿼리로 필드 검색 용이조회 시 include 필요, 테이블 개수 증가
JSON 타입테이블이 깔끔함, 스키마 변경에 유연함내부 필드에 대한 강력한 타입 검증이 어려움
Composite Types임베딩 기능 그 자체MongoDB에서만 작동함 (RDB 미지원)

💡 실무 가이드

  • 데이터가 검색이나 필터링의 대상인가? 👉 무조건 1:1 관계를 맺으세요. (where: { address: { city: 'Seoul' } } 가능)
  • 단순히 정보를 저장하고 보여주기만 하면 되는가? 👉 JSON 타입을 고려해 보세요.

6. 마치며

Prisma는 RDB 환경에서 "암시적인 임베딩"보다는 "명시적인 관계"를 지향하는 도구입니다. TypeORM의 임베디드 엔티티가 그리울 수 있겠지만, 1:1 관계와 include를 활용하면 오히려 데이터의 무결성을 더 완벽하게 지킬 수 있습니다.

현재 프로젝트가 MongoDB 기반이라면 Prisma의 type 키워드를 사용하여 완벽한 임베딩을 즐기시고, Supabase 같은 PostgreSQL 환경이라면 1:1 관계를 통한 정공법을 선택하시길 추천합니다!

← 이전 글NestJS 아키텍처 가이드: 3-Layer부터 CQRS까지 실무 패턴 총정리
다음 글 →백엔드 개발자의 영원한 고민: Raw SQL, Query Builder, ORM 완벽 비교 및 레포지토리 패턴