--- title: 개체 description: defineObject를 사용하여 고유한 필드를 가진 사용자 정의 테이블인 새 레코드 유형을 선언합니다. icon: table --- 사용자 정의 **개체**는 워크스페이스에 앱이 추가하는 새로운 레코드 유형입니다. 엽서(Post Card), 송장(Invoice), 구독(Subscription) 등 도메인에 특화된 어떤 것이라도 될 수 있습니다. 각 개체는 스키마(필드, 관계, 기본값)와 동기화 및 배포 간에도 유지되는 안정적인 범용 식별자를 선언합니다. ```ts src/objects/post-card.object.ts import { defineObject, FieldType } from 'twenty-sdk/define'; enum PostCardStatus { DRAFT = 'DRAFT', SENT = 'SENT', DELIVERED = 'DELIVERED', RETURNED = 'RETURNED', } export default defineObject({ universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05', nameSingular: 'postCard', namePlural: 'postCards', labelSingular: 'Post Card', labelPlural: 'Post Cards', description: 'A post card object', icon: 'IconMail', fields: [ { universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b', name: 'content', type: FieldType.TEXT, label: 'Content', description: "Postcard's content", icon: 'IconAbc', }, { universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac', name: 'recipientName', type: FieldType.FULL_NAME, label: 'Recipient name', icon: 'IconUser', }, { universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266', name: 'recipientAddress', type: FieldType.ADDRESS, label: 'Recipient address', icon: 'IconHome', }, { universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e', name: 'status', type: FieldType.SELECT, label: 'Status', icon: 'IconSend', defaultValue: `'${PostCardStatus.DRAFT}'`, options: [ { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' }, { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' }, { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' }, { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' }, ], }, { universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433', name: 'deliveredAt', type: FieldType.DATE_TIME, label: 'Delivered at', icon: 'IconCheck', isNullable: true, defaultValue: null, }, ], }); ``` ## 핵심 요점 * `universalIdentifier`는 배포 전반에서 고유하고 안정적이어야 합니다. * 각 필드는 `name`, `type`, `label` 및 고유하고 안정적인 `universalIdentifier`가 필요합니다. * `fields` 배열은 선택 사항입니다. 사용자 정의 필드 없이도 개체를 정의할 수 있습니다. * 여기에서 정의된 인라인 필드는 `objectUniversalIdentifier`가 **필요하지 않습니다** — 상위 개체에서 상속됩니다. 소유하지 않은 개체에 필드를 추가하려면 [`defineField()`](/l/ko/developers/extend/apps/data/extending-objects)를 사용하세요. * `yarn twenty dev:add object`를 사용하여 새 개체를 스캐폴딩할 수 있으며, 이름, 필드, 관계 설정 과정을 안내합니다. [Architecture → Scaffolding entities](/l/ko/developers/extend/apps/getting-started/scaffolding)를 참조하세요. **기본 필드는 자동으로 추가됩니다.** 사용자 정의 개체를 정의하면 Twenty가 `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy`, `deletedAt`와 같은 표준 필드를 자동으로 생성합니다. 이 필드들은 `fields` 배열에 선언할 필요가 없습니다 — 사용자 정의 필드만 선언하면 됩니다. 동일한 이름으로 필드를 선언하여 기본 필드를 재정의할 수 있지만, 이는 거의 바람직하지 않습니다. ## 기본값 리터럴 문자열 기본값은 문자열 **내부에서** 작은따옴표로 감싸야 합니다. 즉, `defaultValue: "'Draft'"`처럼 작성해야 하며, `defaultValue: "Draft"`처럼 작성하면 안 됩니다. 그래서 위의 `status` 필드는 `` `'${PostCardStatus.DRAFT}'` ``를 사용합니다. 따옴표로 감싸지 않은 문자열은 레코드가 생성될 때 평가되는 계산형 기본값으로 예약되어 있습니다. * `'uuid'` — UUID를 생성합니다 (`UUID` 필드용). * `'now'` — 현재 타임스탬프입니다 (`DATE_TIME` 필드용). 동일한 규칙이 복합 기본값의 문자열 하위 필드(예: `ACTOR` 필드의 `{ source: "'MANUAL'" }`)와 `SELECT`/`MULTI_SELECT` 값에도 적용됩니다. 따옴표로 감싸지 않은 리터럴 문자열 기본값은 앱을 빌드할 때 경고를 발생시킵니다. ## Null 허용 여부 `isNullable`는 필드가 `NULL`을 허용하는지 여부를 제어합니다. 기본값은 `true`이며, 선택적 필드의 경우 생략하면 됩니다. 데이터베이스 수준에서 필드를 필수로 만들려면 `isNullable: false`로 설정하세요. `isNullable`에 대한 변경 사항은 기존 필드를 업데이트하는 동기화를 포함해 모든 동기화 시 적용되므로, 매니페스트를 수정하고 다시 동기화하여 필드의 Null 허용 여부를 전환할 수 있습니다. **기존 필드를 널 불가(non-nullable)로 변경하려면 기본값이 필요합니다.** 필드를 `isNullable: false`로 변경할 때는 널이 아닌 `defaultValue`도 함께 제공해야 합니다. 기본값은 `NOT NULL` 제약 조건이 적용되기 전에 기존의 `NULL` 행들을 모두 채웁니다. 기본값이 없으면 동기화가 실패하며 `Default value cannot be null for non-nullable fields` 오류가 발생합니다. 릴레이션 필드와 `TS_VECTOR` 필드는 항상 널 허용이므로 `isNullable` 설정이 이들 필드에는 영향을 주지 않습니다. ```ts { universalIdentifier: 'b1a7c0de-1234-4f00-9abc-000000000000', name: 'reference', type: FieldType.TEXT, label: 'Reference', isNullable: false, defaultValue: "'N/A'", } ``` ## 다음 단계 * **이 개체를 다른 개체와 연결** — 양방향 관계 패턴은 [Relations](/l/ko/developers/extend/apps/data/relations)를 참조하세요. * **다른 앱의 개체에 필드 추가** — `defineField()`에 대해서는 [Extending Objects](/l/ko/developers/extend/apps/data/extending-objects)를 참조하세요. * **UI에 이 개체 표시** — 사이드바에 배치하려면 [Views](/l/ko/developers/extend/apps/layout/views) 및 [Navigation Menu Items](/l/ko/developers/extend/apps/layout/navigation-menu-items)를 참조하세요.