-
-
Notifications
You must be signed in to change notification settings - Fork 0
entity-derive가 지원하는 모든 속성에 대한 완전한 가이드입니다.
#[entity(...)]를 사용하여 구조체에 적용합니다:
#[derive(Entity)] #[entity( table = "users", schema = "core", sql = "full", dialect = "postgres", uuid = "v7", soft_delete, returning = "full", error = "AppError", events, hooks, commands )] pub struct User { /* ... */ }
| 속성 | 필수 | 기본값 | 설명 |
|---|---|---|---|
table |
예 | — | 데이터베이스 테이블 이름 |
schema |
아니오 | "public" |
데이터베이스 스키마 |
sql |
아니오 | "full" |
SQL 생성 레벨 |
dialect |
아니오 | "postgres" |
데이터베이스 방언 |
uuid |
아니오 | "v7" |
ID 생성용 UUID 버전 |
soft_delete |
아니오 | false |
소프트 삭제 활성화 |
returning |
아니오 | "full" |
RETURNING 절 모드 |
error |
아니오 | sqlx::Error |
커스텀 에러 타입 |
events |
아니오 | false |
생명주기 이벤트 생성 |
hooks |
아니오 | false |
생명주기 훅 트레이트 생성 |
commands |
아니오 | false |
CQRS 커맨드 패턴 활성화 |
데이터베이스 테이블 이름입니다.
#[entity(table = "users")] // → FROM users #[entity(table = "user_profiles")] // → FROM user_profiles
데이터베이스 스키마입니다. 기본값: "public".
#[entity(table = "users")] // → FROM public.users #[entity(table = "users", schema = "core")] // → FROM core.users #[entity(table = "users", schema = "auth")] // → FROM auth.users
SQL 생성 레벨입니다. 기본값: "full".
| 값 | Repository Trait | PgPool 구현 | 사용 사례 |
|---|---|---|---|
"full" |
예 | 예 | 표준 CRUD 엔티티 |
"trait" |
예 | 아니오 | 커스텀 쿼리 (joins, CTE) |
"none" |
아니오 | 아니오 | DTO만, 데이터베이스 없음 |
#[entity(table = "users", sql = "full")] // 전체 자동화 (기본값) #[entity(table = "users", sql = "trait")] // 트레이트만, SQL은 직접 구현 #[entity(table = "users", sql = "none")] // 데이터베이스 레이어 없음
SQL 생성용 데이터베이스 방언입니다. 기본값: "postgres".
| 방언 | 별칭 | 클라이언트 타입 | 상태 |
|---|---|---|---|
"postgres" |
"pg", "postgresql"
|
sqlx::PgPool |
안정 |
"clickhouse" |
"ch" |
clickhouse::Client |
예정 |
"mongodb" |
"mongo" |
mongodb::Client |
예정 |
자동 생성되는 기본 키용 UUID 버전입니다. 기본값: "v7".
| 버전 | 메서드 | 속성 |
|---|---|---|
"v7" |
Uuid::now_v7() |
시간순 정렬, 정렬 가능 (권장) |
"v4" |
Uuid::new_v4() |
랜덤, 널리 호환 |
#[entity(table = "users", uuid = "v7")] // 시간순 정렬 (기본값) #[entity(table = "sessions", uuid = "v4")] // 랜덤 UUID
UUID v7을 사용하는 이유:
- 시간순 정렬: 생성 시간별 자연스러운 정렬
- 더 나은 데이터베이스 인덱스 성능
- 조정이 필요 없음 (시퀀스와 달리)
- 분산 시스템에서 전역 고유
레코드를 삭제하는 대신 삭제로 표시하는 소프트 삭제를 활성화합니다.
#[derive(Entity)] #[entity(table = "documents", soft_delete)] pub struct Document { #[id] pub id: Uuid, #[field(create, response)] pub title: String, #[field(skip)] pub deleted_at: Option<DateTime<Utc>>, // 필수 필드 }
생성되는 메서드:
-
delete()— DELETE 대신deleted_at = NOW()설정 -
hard_delete()— 레코드를 영구적으로 삭제 -
restore()—deleted_at = NULL설정 -
find_by_id()/list()— 자동으로 삭제된 레코드 필터링 -
find_by_id_with_deleted()/list_with_deleted()— 삭제된 레코드 포함
INSERT/UPDATE 후 어떤 데이터를 가져올지 제어합니다. 기본값: "full".
| 모드 | SQL 절 | 사용 사례 |
|---|---|---|
"full" |
RETURNING * |
DB 생성 값 포함 모든 필드 가져오기 (기본값) |
"id" |
RETURNING id |
삽입 확인, 미리 빌드된 엔티티 반환 |
"none" |
(RETURNING 없음) | Fire-and-forget, 가장 빠른 옵션 |
"col1, col2" |
RETURNING col1, col2 |
특정 컬럼 반환 |
#[entity(table = "logs", returning = "none")] // 가장 빠름 #[entity(table = "users", returning = "full")] // DB 생성 값 가져오기 #[entity(table = "events", returning = "id, created_at")] // 커스텀 컬럼
리포지토리용 커스텀 에러 타입입니다. 기본값: sqlx::Error.
#[derive(Debug)] pub enum AppError { Database(sqlx::Error), NotFound, Validation(String), } impl std::error::Error for AppError {} impl std::fmt::Display for AppError { /* ... */ } // 필수: sqlx::Error에서 변환 impl From<sqlx::Error> for AppError { fn from(err: sqlx::Error) -> Self { AppError::Database(err) } } #[derive(Entity)] #[entity(table = "users", error = "AppError")] pub struct User { /* ... */ } // 생성된 리포지토리는 AppError를 사용: // impl UserRepository for PgPool { // type Error = AppError; // ... // }
생명주기 이벤트 열거형을 생성합니다. 자세한 내용은 이벤트를 참조하세요.
#[entity(table = "orders", events)]생성됨:
pub enum OrderEvent { Created(Order), Updated { id: Uuid, changes: UpdateOrderRequest }, Deleted(Uuid), }
생명주기 훅 트레이트를 생성합니다. 자세한 내용은 훅을 참조하세요.
#[entity(table = "users", hooks)]생성됨:
#[async_trait] pub trait UserHooks: Send + Sync { type Error: std::error::Error + Send + Sync; async fn before_create(&self, dto: &mut CreateUserRequest) -> Result<(), Self::Error>; async fn after_create(&self, entity: &User) -> Result<(), Self::Error>; async fn before_update(&self, id: &Uuid, dto: &mut UpdateUserRequest) -> Result<(), Self::Error>; async fn after_update(&self, entity: &User) -> Result<(), Self::Error>; async fn before_delete(&self, id: &Uuid) -> Result<(), Self::Error>; async fn after_delete(&self, id: &Uuid) -> Result<(), Self::Error>; }
CQRS 커맨드 패턴을 활성화합니다. 자세한 내용은 커맨드를 참조하세요.
#[entity(table = "users", commands)] #[command(Register)] #[command(Deactivate, requires_id)]
개별 필드에 적용됩니다.
기본 키 필드를 표시합니다.
동작:
- UUID 자동 생성 (기본 v7,
uuid속성으로 설정 가능) -
ResponseDTO에 항상 포함 -
CreateRequest와UpdateRequest에서 제외
#[id] pub id: Uuid,
자동 생성 필드를 표시합니다 (timestamps, sequences).
동작:
-
From<CreateRequest>에서Default::default()획득 -
CreateRequest와UpdateRequest에서 제외 -
#[field(response)]로Response에 포함 가능
#[auto] #[field(response)] pub created_at: DateTime<Utc>,
DTO 포함을 제어합니다. 여러 옵션을 조합하세요:
#[field(create)] // CreateRequest에만 #[field(update)] // UpdateRequest에만 #[field(response)] // Response에만 #[field(create, response)] // Create와 Response에 #[field(create, update, response)] // 세 가지 모두에 #[field(skip)] // 모든 DTO에서 제외
CreateRequest DTO에 필드를 포함합니다.
#[field(create)] pub email: String, // 생성됨: pub struct CreateUserRequest { pub email: String, }
UpdateRequest DTO에 필드를 포함합니다.
중요: 비선택적 필드는 부분 업데이트를 위해 자동으로 Option<T>로 래핑됩니다.
#[field(update)] pub name: String, // Option 아님 // 생성됨: pub struct UpdateUserRequest { pub name: Option<String>, // 자동으로 래핑됨 }
Response DTO에 필드를 포함합니다.
#[field(response)] pub email: String, // 생성됨: pub struct UserResponse { pub id: Uuid, // 항상 포함 (#[id] 있음) pub email: String, // 포함됨 }
모든 DTO에서 필드를 제외합니다. 민감한 데이터에 사용하세요.
#[field(skip)] pub password_hash: String,
중요: skip은 다른 모든 필드 옵션을 무시합니다. 필드는 다음에만 존재합니다:
- 원본 엔티티 구조체
-
Row구조체 (데이터베이스 읽기용) -
Insertable구조체 (데이터베이스 쓰기용)
쿼리 필터 필드를 생성합니다. 자세한 내용은 필터링을 참조하세요.
#[filter] // 정확히 일치: WHERE field = $n #[filter(eq)] // 위와 동일 #[filter(like)] // 패턴 일치: WHERE field ILIKE $n #[filter(range)] // 범위: WHERE field >= $n AND field <= $m
외래 키 관계입니다. 자세한 내용은 관계를 참조하세요.
#[belongs_to(User)] pub user_id: Uuid,
생성됨: 리포지토리에 find_user() 메서드.
일대다 관계 (엔티티 레벨)입니다. 자세한 내용은 관계를 참조하세요.
#[has_many(Post)] pub struct User { /* ... */ }
생성됨: 리포지토리에 find_posts() 메서드.
부분 뷰 구조체를 생성합니다 (엔티티 레벨).
#[projection(Public: id, name, avatar)] #[projection(Admin: id, name, email, role)] pub struct User { /* ... */ }
생성됨:
UserPublic { id, name, avatar }UserAdmin { id, name, email, role }-
From<User>구현 -
find_by_id_public(),find_by_id_admin()메서드
#[command(...)]를 사용하여 엔티티 레벨에 적용됩니다.
| 구문 | 효과 |
|---|---|
#[command(Name)] |
모든 #[field(create)] 필드 사용 |
#[command(Name: field1, field2)] |
지정된 필드만 사용 (requires_id 추가) |
#[command(Name, requires_id)] |
ID 필드 추가, 다른 필드 없음 |
#[command(Name, source = "create")] |
명시적으로 create 필드 사용 (기본값) |
#[command(Name, source = "update")] |
update 필드 사용 (선택적, requires_id 추가) |
#[command(Name, source = "none")] |
payload 필드 없음 |
#[command(Name, payload = "Type")] |
커스텀 payload 구조체 사용 |
#[command(Name, result = "Type")] |
커스텀 결과 타입 사용 |
#[command(Name, kind = "create")] |
힌트: 엔티티 생성 (기본값) |
#[command(Name, kind = "update")] |
힌트: 엔티티 수정 |
#[command(Name, kind = "delete")] |
힌트: 엔티티 삭제 (() 반환) |
#[command(Name, kind = "custom")] |
힌트: 커스텀 작업 |
자세한 내용은 커맨드를 참조하세요.
#[derive(Entity)] #[entity( table = "posts", schema = "blog", sql = "full", dialect = "postgres", uuid = "v7", soft_delete, returning = "full", events, hooks, commands )] #[has_many(Comment)] #[projection(Summary: id, title, author_id, created_at)] #[command(Publish)] #[command(Archive, requires_id)] pub struct Post { #[id] pub id: Uuid, #[field(create, update, response)] #[filter(like)] pub title: String, #[field(create, update, response)] pub content: String, #[field(create, response)] #[belongs_to(User)] #[filter] pub author_id: Uuid, #[field(update, response)] pub published: bool, #[field(response)] #[filter(range)] pub view_count: i64, #[field(skip)] pub moderation_notes: String, #[field(skip)] pub deleted_at: Option<DateTime<Utc>>, #[auto] #[field(response)] #[filter(range)] pub created_at: DateTime<Utc>, #[auto] #[field(response)] pub updated_at: DateTime<Utc>, }
| 하고 싶은 것... | 속성 |
|---|---|
| 기본 키 자동 생성 | #[id] |
| 랜덤 UUID 사용 | 엔티티에 uuid = "v4"
|
| 시간순 UUID 사용 |
uuid = "v7" (기본값) |
| POST 본문에서 받기 | #[field(create)] |
| PATCH 본문에서 받기 | #[field(update)] |
| API 응답에서 반환 | #[field(response)] |
| 받고 반환 | #[field(create, update, response)] |
| 모든 API에서 숨기기 | #[field(skip)] |
| timestamp 자동 생성 |
#[auto] + #[field(response)]
|
| 읽기 전용 (DB 관리) |
#[field(response)]만 |
| 쓰기 전용 (반환 없음) |
#[field(create)]만 |
| 커스텀 SQL 쿼리 | sql = "trait" |
| DTO만, DB 없음 | sql = "none" |
| 레코드 소프트 삭제 | 엔티티에 soft_delete
|
| 커스텀 에러 타입 | 엔티티에 error = "MyError"
|
| 정확한 값으로 필터 | 필드에 #[filter]
|
| 패턴으로 필터 | 필드에 #[filter(like)]
|
| 범위로 필터 | 필드에 #[filter(range)]
|
| 엔티티 변경 추적 | 엔티티에 events
|
| 생명주기에서 코드 실행 | 엔티티에 hooks
|
| 도메인 커맨드 사용 | 엔티티에 commands + #[command(...)]
|
| 관계 정의 |
#[belongs_to(Entity)] 또는 #[has_many(Entity)]
|
| 부분 엔티티 뷰 | #[projection(Name: fields)] |
🇬🇧 English | 🇷🇺 Русский | 🇰🇷 한국어 | 🇪🇸 Español | 🇨🇳 中文
Getting Started
Features
Advanced
Начало работы
Возможности
Продвинутое
시작하기
기능
고급
Comenzando
Características
Avanzado
入门
功能
高级