메인 콘텐츠로 건너뛰기
Twenty 앱의 데이터 레이어는 워크스페이스에 앱이 추가하는 데이터입니다. 앱이 선언하는 새로운 레코드 타입, 기존 개체에 추가하는 열, 그리고 이러한 레코드들이 서로 연결되는 방식이 여기에 포함됩니다.
┌──────────────────────────────────────────────────┐
│ Object — a record type, e.g. PostCard            │
│    ├─ Field     (name, type, label)              │
│    ├─ Field                                      │
│    └─ Relation  (link to another object)         │
└──────────────────────────────────────────────────┘

            ├── lives in your app, OR


┌──────────────────────────────────────────────────┐
│ Standard / other apps' objects                   │
│    └─ Field added by your app via defineField    │
└──────────────────────────────────────────────────┘

이 섹션에서 다루는 내용

개체

defineObject — 자체 필드를 가진 새로운 레코드 타입을 선언합니다.

객체 확장하기

defineField — 표준 개체 또는 다른 앱의 개체에 필드를 추가합니다.

관계

개체 간의 양방향 MANY_TO_ONE / ONE_TO_MANY 연결입니다.

엔터티 한눈에 보기

엔터티목적정의 방식
객체고유한 필드를 가진 새로운 사용자 정의 레코드 타입(예: PostCard, Invoice)defineObject()
필드객체의 열 독립형 필드를 사용하면 직접 생성하지 않은 객체도 확장할 수 있습니다(예: Company에 loyaltyTier 추가).defineField()
관계두 객체 사이의 양방향 연결 — 양쪽 모두 필드로 선언됩니다.FieldType.RELATION을 사용하는 defineField()
색인객체 중 하나에 대해 반복적으로 실행되는 쿼리를 빠르게 하기 위한 데이터베이스 색인defineIndex()
SDK는 빌드 시 AST 분석을 통해 이를 감지하므로, 파일 구성은 전적으로 여러분에게 달려 있습니다. 권장 컨벤션은 src/objects/, src/fields/, src/indexes/입니다. 안정적인 universalIdentifier UUID가 배포 간 모든 것을 하나로 연결합니다.

색인(선택 사항)

앱은 반복적인 쿼리를 빠르게 유지하기 위해 객체와 함께 색인을 포함하여 배포할 수 있습니다. 가장 일반적인 사례는 자주 읽는 상태 열 또는 외래 키 열입니다.
src/indexes/post-card-status.index.ts
import { defineIndex } from 'twenty-sdk/define';

import {
  POST_CARD_UNIVERSAL_IDENTIFIER,
  STATUS_FIELD_UNIVERSAL_IDENTIFIER,
} from '../objects/post-card.object';

export default defineIndex({
  universalIdentifier: 'b6e9d2a1-5a4c-46ca-9d52-42c8f02d1ff0',
  objectUniversalIdentifier: POST_CARD_UNIVERSAL_IDENTIFIER,
  fields: [
    {
      universalIdentifier: 'b6e9d2a1-5a4c-46ca-9d52-42c8f02d1ff1',
      fieldUniversalIdentifier: STATUS_FIELD_UNIVERSAL_IDENTIFIER,
    },
  ],
});

고유 색인

defineIndex는 단일 열 및 다중 열 고유성 모두에 대해 isUnique: true를 허용합니다. 이것이 권장 기본 요소이며, defineField({ isUnique: true })는 사용이 중단(deprecated)되었고 향후 릴리스에서 제거될 예정입니다.
defineIndex({
  universalIdentifier: '…',
  objectUniversalIdentifier: PERSON_UNIVERSAL_IDENTIFIER,
  isUnique: true,
  fields: [{ universalIdentifier: '…', fieldUniversalIdentifier: EMAIL_FIELD_UNIVERSAL_IDENTIFIER }],
});

기타 제약 조건

  • 부분 WHERE 절은 관리자 제어 하에 유지되며, 앱에서 이를 선언할 수 없습니다.
  • 각 객체에는 사용자 정의 색인이 최대 10개까지 허용됩니다(프레임워크 자체 색인은 포함되지 않음).
fields 배열의 순서는 Postgres가 사용하는 순서대로 지정하세요. 전화번호부처럼 가장 왼쪽 열이 먼저 오도록 합니다. 색인은 공짜가 아닙니다. 테이블에 대한 모든 쓰기 작업은 색인을 갱신합니다. 해당 색인을 필요로 하는 쿼리가 있을 때에만 색인을 추가하세요.
Application Config 또는 Roles & Permissions를 찾고 계신가요? 이러한 항목은 앱이 추가하는 데이터가 아니라 앱 자체를 설명하며, Config 아래에 있습니다. Connections(Linear, GitHub, Slack OAuth)를 찾고 계신가요? 이들은 로직 함수 내부에서 호출되기 위한 것이며, Logic 아래에 있습니다.