# 삭제 규칙
모듈의 여러 엔티티 간 관계를 생성할 때, **레코드를 삭제**할 때 어떤 참조 무결성을 사용할지 정의해야 합니다. **참조 무결성**은 엔티티 A의 레코드가 삭제되었을 때 해당 엔티티 A의 레코드를 참조하고 있는 엔티티 B의 레코드가 어떻게 될지를 지정합니다.
아래 엔티티 다이어그램은 Customer(주 엔티티 A)와 Order(관련 엔티티 B)의 관계를 정의하고 있습니다. Customer는 여러 개의 Order를 가질 수 있으며, Order는 하나의 Customer에만 속합니다. [참조 속성](https://success.outsystems.com/ja-jp/documentation/11/building_apps/data_management/data_modeling/entity_relationships/)(데이터베이스 용어로는 외래 키에 해당)은 엔티티 **Order**의 속성 **CustomerId**입니다.

이 예시에서는 **참조 무결성**을 지정함으로써 Customer가 삭제되었을 때 Customer의 Order가 어떻게 될지 정의합니다.
두 엔티티 간 관계에서 **참조 무결성**을 지정하려면, 관련 엔티티의 **참조 속성**을 편집하고 **Delete Rule** 속성의 값을 `Protect`, `Delete`, `Ignore` 중 하나로 설정해야 합니다.

**Protect**
**Delete Rule**을 `Protect`로 설정하면, 관련 엔티티 내에 관련 레코드가 있는 경우 주 엔티티의 레코드는 삭제되지 않습니다.
이 동작은 참조 속성으로 생성된 데이터베이스 제약조건에 의해 보장됩니다. 관련 엔티티에 관련 레코드가 아직 있는 주 엔티티의 레코드를 삭제하려고 하면, Platform Server가 데이터베이스 예외를 반환하고 작업은 실행되지 않습니다.
**Delete(삭제)**
**Delete Rule**을 `Delete`로 설정한 경우, 주 엔티티의 레코드를 삭제하면 관련 엔티티 내의 관련 레코드도 모두 삭제됩니다. 이 메커니즘은 일반적으로 "계단식 삭제"로 알려져 있습니다.
이 동작은 참조 속성으로 생성된 데이터베이스 제약조건에 의해 보장됩니다.
**Ignore**
**Delete Rule**을 `Ignore`로 설정한 경우, 관련 엔티티 내의 관련 레코드를 유지한 채로 주 엔티티의 레코드를 삭제할 수 있습니다.
`Ignore` 값에서는 참조 무결성이 보장되지 않으므로, 데이터베이스 제약조건이 발생하지 않습니다. 따라서 **Delete Rule** 속성의 값을 이전 값에서 `Ignore`로 변경한 경우, 해당 자동 인덱스는 삭제됩니다(속성 중 하나를 수동으로 변경한 경우 제외).
확장에 의해 공개된 외부 엔티티를 외부 키 속성이 참조하는 경우, 참조 무결성을 보장할 수 없으므로 사용 가능한 **Delete Rule** 속성의 값은 `Ignore`뿐입니다.
엔티티 모델을 설계할 때, 여러 관계의 Delete Rule을 적절히 설정하여 시스템이 각 사용 사례에서 예상대로 작동하도록 해야 합니다. 사용 사례에 따라 적절한 선택을 하는 데 도움이 되는 각 옵션의 예시와 고려사항을 아래에 제시합니다.
## 'Protect'의 예시
`Protect` 값은 최종 사용자가 애플리케이션 화면에서 직접 엔티티 데이터를 삭제할 수 있는 경우에 자주 사용됩니다.
다음과 같은 비즈니스 시나리오를 고려해 봅시다.
- 최종 사용자가 **Customers**를 삭제할 수 있는 애플리케이션 화면이 있습니다.
- **Customer**는 여러 개의 **Order**를 가질 수 있으며, **Order**는 하나의 **Customer**에만 속합니다.
- 관련된 Order가 있는 경우, **Customer**를 삭제할 수 없습니다.
참조 속성 **CustomerId**의 **Delete Rule** 속성을 `Protect`로 설정하면, 최종 사용자는 관련 Order가 남아 있는 Customer를 삭제할 수 없습니다.

관련 Order가 남아 있는 Customer를 삭제하려고 하면 데이터베이스 예외가 발생하고, 작업은 실행되지 않습니다.

이 경우, Customer를 삭제하려면 해당 Customer가 주문한 Order를 먼저 모두 삭제해야 합니다.
이 방법은 delete 문을 개별적으로 제어하고 최적화할 수 있으며, 데이터 무결성도 확보되므로 성능이 우수합니다. 더 높은 제어와 성능을 얻으려고 하면 구현 비용이 높아지므로, 둘 중 하나를 우선시해야 합니다.
### 장점
- 관련 엔티티에서 참조하고 있는 주 엔티티의 레코드는 삭제할 수 없으므로, 항상 데이터 모델의 무결성이 유지됩니다.
### 제약
- 로직 내에서 삭제 순서가 적절하도록 조정해야 합니다. 관련 엔티티의 레코드를 먼저 삭제한 다음에 주 엔티티의 레코드를 삭제해야 합니다.
- 모델에 새 관련 엔티티를 추가할 때마다, 해당 관련 엔티티도 삭제 사이클 로직에 포함시켜야 합니다.
## 'Delete'의 예시
`Delete` 값은 데이터 제거 메커니즘을 구현할 때 모델 전체에 걸쳐 자동 계단식 삭제를 수행해야 하는 경우에 자주 사용됩니다.
일반적으로 데이터 제거 메커니즘은 비동기 프로세스(타이머 또는 BPT)에 의해 처리되므로, 성능에는 영향을 미치지 않습니다.
다음과 같은 비즈니스 시나리오를 고려해 봅시다.
- 5년 이상 지난 종료된 **Order**를 모두 삭제합니다.
- **Order**에는 **OrderItem**이 하나 이상 있고, **OrderItem**은 하나의 **Order**에만 속합니다.
- **Order**가 삭제되었을 때, 관련된 **OrderItem**도 모두 삭제되어야 합니다.
참조 속성 **OrderId**의 **Delete Rule** 속성을 `Delete`로 설정하면, Order가 삭제되었을 때 관련된 OrderItem도 모두 자동으로 삭제됩니다.

### 장점
- 항상 데이터 모델의 무결성이 유지됩니다. 주 엔티티의 레코드를 삭제하면 관련 엔티티의 관련 레코드도 모두 삭제되므로, 관련 엔티티에서 레코드가 참조되지 않게 됩니다.
- 주 엔티티 수준에서만 레코드를 삭제하면 되므로, 삭제 로직의 개발과 유지보수가 간단합니다.
- 참조 속성의 **Delete Rule**을 `Delete`로 설정하기만 하면 되므로, 새로운 관련 엔티티를 모델에 추가할 때 개발 노력이 적게 듭니다.
### 제약
- 이 방법은 관련 레코드의 수에 따라 성능이 저하될 수 있습니다. 삭제 작업마다 관련 엔티티의 관련 레코드를 확인하기 때문에, delete 문의 실행에 시간이 걸립니다. 따라서 엔티티 모델이 복잡하고 성능이 중요한 경우(최종 사용자가 애플리케이션 화면에서 직접 엔티티 데이터를 삭제할 수 있는 경우 등), 이 방법은 권장되지 않습니다.
## 'Ignore'의 예시
Ignore 값은 기록 데이터 아카이브 메커니즘을 구현할 때, 주 엔티티의 레코드는 삭제하지만 주 레코드의 세부 정보가 관련되지 않음을 고려하여 관련 엔티티의 레코드를 모두 유지해야 하는 경우에 자주 사용됩니다.
다음과 같은 비즈니스 시나리오를 고려해 봅시다.
- **Order**에 대해 수행된 모든 작업의 로그가 **OrderHistory**에 기록됩니다.
- 하나의 **OrderHistory** 레코드는 하나의 **Order**에만 관련되고, 하나의 **Order**에는 관련된 **OrderHistory** 레코드가 하나 이상 있습니다.
- 5년 이상 지난 종료된 **Order**를 모두 삭제합니다. 단, 컴플라이언스 상의 이유로 **OrderHistory** 레코드를 10년 동안 유지해야 합니다.
참조 속성 **OrderId**의 **Delete Rule** 속성을 `Ignore`로 설정함으로써, Order를 삭제하고 관련된 OrderHistory 레코드는 유지할 수 있습니다.

### 장점
- 관련 엔티티에 영향을 미치지 않고 주 엔티티의 레코드를 삭제할 수 있습니다.
### 제약
- 이 방법을 사용하면 데이터 모델이 불일치하게 됩니다. 관련 레코드는 유지되지만, 주 레코드의 세부 정보를 얻을 수 없고 식별자만 얻을 수 있게 됩니다.
- 참조 속성의 **Delete Rule** 속성 값을 이전 값에서 `Ignore`로 변경한 경우, 해당 자동 인덱스는 삭제됩니다. 참조 속성을 쿼리 필터로 사용하는 경우, 새 인덱스를 수동으로 추가해야 합니다.