### **📌 EF Core의 변경 추적(Change Tracking) 기능이란?**
Entity Framework Core(이하 EF Core)의 **변경 추적(Change Tracking)** 기능은 **데이터베이스에서 가져온 엔터티의 상태 변화를 자동으로 감지하고 추적하는 기능**이야.
즉, **개발자가 SQL을 직접 작성하지 않아도, 엔터티 객체의 변경 사항을 감지하여 자동으로 데이터베이스에 반영해 주는 기능**이야.
---
## **🟢 변경 추적(Change Tracking)의 기본 동작 원리**
EF Core는 `DbContext`를 통해 데이터베이스와 상호작용하는데, `DbContext` 내부에서 엔터티의 상태를 추적하는 **Change Tracker**가 작동해.
EF Core는 `DbContext`에 의해 관리되는 객체들의 상태를 추적하고, `SaveChanges()` 또는 `SaveChangesAsync()`를 호출할 때, 변경된 내용을 데이터베이스에 반영해.
### **🔹 변경 추적 기능을 사용한 기본 예제**
```csharp
using (var context = new AppDbContext())
{
// 기존 사용자 데이터를 가져옴
var user = await context.Users.FirstOrDefaultAsync(u => u.Id == 1);
// 엔터티의 속성 값 변경
user.Name = "Updated Name";
// SaveChanges 호출 시 변경 사항을 자동 감지하여 UPDATE SQL 실행
await context.SaveChangesAsync();
}
```
**🟢 동작 과정**
1. `context.Users.FirstOrDefaultAsync()`로 데이터를 가져오면, EF Core는 해당 엔터티를 **추적(Tracking) 상태**로 유지함.
2. `user.Name = "Updated Name";` 처럼 속성을 변경하면, EF Core는 **이전 값과 비교하여 변경 사항을 인식**함.
3. `SaveChangesAsync()`를 호출하면, 변경된 속성을 포함한 `UPDATE` SQL이 자동 실행됨.
---
## **🟢 EF Core의 변경 추적 상태 (EntityState)**
EF Core는 엔터티의 상태를 **5가지 상태(EntityState)로 관리**해.
| 상태 (EntityState) | 설명 |
|------------------|------------------------------------------------------------|
| **Added** | 새로 추가된 엔터티 (`DbSet.Add()`) |
| **Modified** | 변경된 엔터티 (속성이 변경됨) |
| **Deleted** | 삭제된 엔터티 (`DbSet.Remove()`) |
| **Unchanged** | 데이터베이스에서 로드되었지만 변경되지 않음 |
| **Detached** | `DbContext`에서 추적되지 않음 |
### **🔹 변경 상태 확인 예제**
```csharp
using (var context = new AppDbContext())
{
var user = await context.Users.FirstOrDefaultAsync(u => u.Id == 1);
Console.WriteLine(context.Entry(user).State); // Unchanged (처음 가져온 상태)
user.Name = "New Name";
Console.WriteLine(context.Entry(user).State); // Modified (속성 변경됨)
}
```
---
## **🟢 변경 추적 기능과 로깅(logger) 기능과의 관계**
변경 추적 기능 자체는 **로깅(logging) 기능과 직접적인 관련은 없지만, 변경 사항을 감지하여 로깅하는 데 사용할 수 있어.**
즉, EF Core의 변경 추적을 활용하여 **변경된 데이터(이전 값 → 변경 후 값)를 로깅할 수 있음.**
### **🔹 예제: 변경된 데이터 로그 기록하기**
```csharp
using (var context = new AppDbContext())
{
var user = await context.Users.FirstOrDefaultAsync(u => u.Id == 1);
user.Name = "Updated Name";
// 변경된 필드 추적
var entry = context.Entry(user);
foreach (var prop in entry.Properties)
{
if (prop.IsModified)
{
Console.WriteLine($"Property {prop.Metadata.Name} changed: {prop.OriginalValue} -> {prop.CurrentValue}");
}
}
await context.SaveChangesAsync();
}
```
**출력 예시 (로그 기록)**
```
Property Name changed: Old Name -> Updated Name
```
✅ **이렇게 하면 변경된 필드와 값을 확인하고 로깅할 수 있음.**
---
## **🟢 변경 추적 기능의 실제 활용 예시**
### **1️⃣ 변경 사항 자동 적용**
EF Core는 `SaveChanges()`를 호출하면, 변경된 사항을 자동으로 감지하고 데이터베이스에 `INSERT`, `UPDATE`, `DELETE` 문을 실행해.
```csharp
var product = new Product { Name = "Laptop", Price = 1200 };
context.Products.Add(product);
await context.SaveChangesAsync(); // INSERT 실행
```
### **2️⃣ 변경 사항 감지 후 수동 적용**
변경 추적 기능을 비활성화하고 직접 `EntityState`를 지정할 수도 있어.
```csharp
var product = new Product { Id = 1, Name = "Tablet", Price = 900 };
context.Entry(product).State = EntityState.Modified;
await context.SaveChangesAsync(); // UPDATE 실행
```
✅ **이렇게 하면 데이터베이스에서 다시 가져오지 않고도 변경 사항을 저장 가능**
---
## **🟢 변경 추적을 비활성화할 수 있을까?**
네! 변경 추적 기능은 비활성화할 수도 있어.
특히 **읽기 전용 쿼리나 대량 데이터 처리 시 성능을 높이기 위해 비활성화**하는 경우가 많아.
### **🔹 변경 추적 비활성화 예제 (`AsNoTracking()`)**
```csharp
var users = await context.Users.AsNoTracking().ToListAsync();
```
✅ **이렇게 하면 EF Core가 변경 사항을 추적하지 않아서 성능이 향상됨.**
❌ 하지만 `SaveChanges()`를 호출해도 데이터가 변경되지 않음.
### **🔹 한 번만 수정할 때 변경 추적 비활성화**
```csharp
var user = new User { Id = 1, Name = "Updated Name" };
context.Users.Attach(user);
context.Entry(user).Property(x => x.Name).IsModified = true;
await context.SaveChangesAsync(); // 변경된 필드만 UPDATE 실행
```
✅ **이 방법은 메모리 절약 효과가 있음.**
---
## **🟢 EF Core의 변경 추적 기능을 사용해야 할까?**
| 경우 | 변경 추적 (Tracking) 사용 여부 |
|------|------------------------------|
| **CRUD 작업** | ✅ 사용 (자동 변경 감지, `SaveChanges()` 활용) |
| **대량 데이터 조회 (읽기 전용)** | ❌ `AsNoTracking()` 사용하여 비활성화 |
| **대량 업데이트, 삭제** | ❌ 변경 추적 대신 `ExecuteSqlRaw()` 사용 추천 |
| **트랜잭션 내에서 변경 관리** | ✅ 사용 (트랜잭션 롤백 시 변경 사항 자동 관리) |
**💡 결론:**
- **자주 변경되는 데이터** → **변경 추적 기능 활용** (`SaveChanges()` 사용)
- **읽기 전용 작업** → **`AsNoTracking()`으로 비활성화하여 성능 최적화**
- **대량 업데이트/삭제** → **SQL 직접 실행 방식(`ExecuteSqlRaw()`)이 더 유리**
---
## **📌 정리**
1. **EF Core의 변경 추적(Change Tracking) 기능은 엔터티 객체의 상태 변화를 감지하고 자동으로 DB에 반영하는 기능.**
2. **트랜잭션 내에서 변경을 자동으로 관리할 수 있어 유지보수성이 높아짐.**
3. **자동 변경 감지 기능은 편리하지만, 성능 최적화를 위해 `AsNoTracking()`을 활용할 수도 있음.**
4. **대량 데이터 처리 시에는 변경 추적을 비활성화하는 것이 성능 면에서 더 유리할 수 있음.**
5. **로깅과 함께 활용하면 변경된 필드 및 값의 이력을 추적하는 데 유용함.**
---
### **❓ 궁금한 점**
혹시 변경 추적 기능을 특정한 시나리오에서 사용해야 할지 고민이 되는 부분이 있어?
예를 들면 **대량 데이터 업데이트나, 특정 테이블에만 변경 추적을 적용하는 방법** 같은 부분이 궁금하면 더 설명해줄게! 😊
'저도공부를하긴한답니다?' 카테고리의 다른 글
Dapper 방식 (0) | 2025.03.05 |
---|---|
병행 방법 (0) | 2025.03.05 |
db io, orm, gitea (0) | 2025.03.04 |
[TIL] 체크리스트 혹은 질문리스트 (0) | 2025.02.24 |
[TIL] 슬슬 너무 질질 끌어서 짜증나는데 EC2 생성으로 바로 넘어갔는데 프리티어라서 아니 (0) | 2025.02.12 |