C# 아키텍처 마스터리 — 클린 아키텍처에서 EF Core (파트 8)
Source: Dev.to
Clean Architecture에서 EF Core의 역할
-
EF Core가 무엇인가
- 영속성 메커니즘
- 데이터 매핑 도구
- 인프라스트럭처 관점
-
EF Core가 아닌 것
- 도메인 모델
- 비즈니스 규칙 엔진
- 아키텍처 기반
EF Core가 내부로 새어나가면 Clean Architecture가 무너진다.
EF Core가 위치하는 곳
Infrastructure
└─ Persistence
├─ DbContext
├─ EntityConfigurations
└─ Repositories
Domain과 Application 레이어는 절대 다음을 참조해서는 안 된다:
DbContextDbSet- EF Core 어트리뷰트
- EF Core LINQ 확장
엄격한 경계: DbContext 누수 금지
// ❌ DbContext leaking inward
class CreateOrderUseCase
{
private readonly AppDbContext _db;
}
결과
- 강한 결합
- 영속성을 인식한 비즈니스 로직
- 테스트 불가능한 Use Case
인터페이스에 의존하고 EF Core에 의존하지 말 것
public interface IOrderRepository
{
Task SaveAsync(Order order);
Task GetByIdAsync(OrderId id);
}
인프라스트럭처 구현
class EfOrderRepository : IOrderRepository
{
private readonly AppDbContext _db;
public async Task SaveAsync(Order order)
{
_db.Orders.Add(order);
await _db.SaveChangesAsync();
}
}
EF Core는 리포지토리 추상화 뒤에 격리된다.
시니어 가이드라인: 도메인이 EF Core를 주도하도록
-
피해야 할 것
- EF 전용으로 만든 빈약한 엔티티
- 어디에든 공개 세터
- 영속성에 의존하는 불변 조건
-
선호할 것
- 풍부한 도메인 모델
- 캡슐화
- 명시적인 불변 조건
EF Core는 private 필드와 생성자를 매핑할 수 있다.
흔한 실수: IQueryable을 위쪽으로 누출
// ❌ IQueryable leaking upward
IQueryable Orders { get; }
위험한 이유
- 로직이 EF 쿼리 변환에 결합됨
- 추상화 깨짐
- 비즈니스 규칙이 쿼리 안으로 들어감
올바른 접근법
- LINQ는 리포지토리 내부에 두기
- 도메인 객체 또는 DTO 반환
EF Core가 적합하지 않은 시나리오
- 복잡한 보고서 쿼리
- 고성능 읽기 모델
- 대량 작업
- 무거운 분석
시니어 팀은 보통 다음을 조합한다:
- EF Core → 쓰기와 애그리게이트
- Dapper / raw SQL → 읽기
이 하이브리드 접근은 전혀 문제되지 않는다.
EF Core가 잘 다루는 영역
- 마이그레이션
- 변경 추적
- 트랜잭션
하지만 Unit of Work 개념은 애플리케이션 레이어에 속한다:
public interface IUnitOfWork
{
Task CommitAsync();
}
EF Core는 구현을 제공하지만 추상화는 정의하지 않는다.
테스트 가이드라인
- Do: 실제 프로바이더를 사용한 통합 테스트 작성; 매핑과 제약 조건을 검증.
- Avoid:
DbContext를 목(mock)하거나 로직 테스트에 InMemory 프로바이더를 과도하게 사용하는 것.
EF Core를 테스트하기 어렵다면 경계가 잘못 잡힌 것이다.
경고 신호 (경계 위반)
DbContext가 컨트롤러나 도메인 서비스에 주입됨- 도메인 엔티티에 EF 어트리뷰트가 붙어 있음
- LINQ 쿼리 안에 비즈니스 규칙이 포함됨
- Lazy loading에 과도하게 의존함
각각의 냄새는 아키텍처 경계가 깨졌음을 나타낸다.
요약
- 올바른 사용: EF Core는 추상화 뒤에 숨겨지고, 도메인을 지원하며, 교체 가능해야 한다.
- 잘못된 사용: EF Core가 시스템이 되고, 설계를 좌우하며, 진화를 방해한다.
Clean Architecture에서 EF Core는 도메인을 섬겨야 하며, 절대 도메인을 지배해서는 안 된다.
Written by Cristian Sifuentes — helping teams tame EF Core so architecture stays clean, testable, and resilient.