EF Core 를 사용하는 이유는 아무래도, 코드 모델과 스키마를 언제나 일치 시킬 수 있다는 효율성과 안정성인 것 같습니다.
효율성과 안정성이라는 의미는…
많은 분들이 그러하듯, 처음 설계할 때, 마이그레이션으로 인한 관리가 아니라, 아래와 같은 방법을 선호합니다.
// Program.cs
// ...
var context = new MyDbContext();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
// ...
위의 코드가 실행될 때 스키마에 문제가 있다면 EF 도구가 예외를 발생시키기에, 앱이 멈추는데, 디자인 도구가 표시해준 문제의 원인을 해결해나가면서 스키마를 빌드업해 나가기 때문에 코드 모델과 스키마 사이에 정합성을 담보할 수 있습니다.
우리가 컴파일러의 도움을 받으면서 코드를 작성하듯, EF 도구의 도움을 받으면서 스키마를 빌드업해 나가는 것이죠.
스키마의 뼈대가 어느 정도 완성되면, 초기 마이그레션을 커밋하고, 이때부터 마이그레이션을 통해 스키마를 관리하는 단계로 접어듭니다.(운영단계까지)
이 단계에서는 불가역적인 스키마 변경에 주의를 해야 하는데, EF 도구는 매 커밋마다 불가역적인 데이터 소실 위험이 감지되었을 때 경고해줍니다.
이러한 경고를 처리할 때, 많은 경우 마이그레이션을 수동으로 조작하는 등, DB 관리 능력이 요구됩니다.
그런데, 더 중요한 점은 데이터 베이스를 망칠 수 있는 실수를 리뷰해주는 존재가 있다는 점입니다. 우리는 마이그레이션이라는 샌드박스 위에서 안전하게 데이터를 유지할 수 있는 것이죠.
EF의 또 다른 장점은 DB의 설계를 코드로 하기 때문에, DDD 같은 디자인 패턴의 철학을 녹이는 것도 가능하다는 점입니다.
대표적으로 Aggregate Root 엔티티만 노출하고, 서브 엔티티는 숨기는 것이죠.
이는 코드가 서브 엔티티를 직접 수정하는 것을 방지하는 효과가 있습니다.
간단하게 설명하자면, User owns UserInfo 관계라면, IUserRepository만 제공하고, IUserInfoRepository는 제공하지 않는 것이죠.
이렇게 하면, 코드가 UserInfo 를 수정하는 경우, 반드시 IUserRepository를 통하는 것이 강제됩니다.
이는 Aggregate 를 하나의 Transaction 단위로 보라는 DDD의 규칙을
Aggregate 전체 상태가 한 번에 변경되던가 아니면 취소되던가.
unit of work 를 추상화한 DbContext 를 통해 구현하는 것입니다.
생쿼리에 익숙한 분들에게는 비효율적으로 보일 수 있는 부분이지만, 데이터 안정성을 위해서는 필요한 규칙이라고 생각합니다. (DDD 에서 괜히 Aggregate 개념을 강조한 것은 아니죠.)
물론, 생쿼리를 쓰면서도 동일한 규칙을 적용할 수도 있지만, 코드적 관리와 쿼리적 관리를 별도로, 그것도 수동으로 해야 합니다. 스키마가 복잡하게 성장할 수록 관리를 힘들게 하는 부분이라고 생각합니다.
EF 를 쓰면, 언어의 컴파일러와 EF 디자인 도구라는 도우미를 얻을 수 있고, 관리 포인트도 코드 하나라서 효율적입니다.
사실 아래의 글은 위 과정을 수행하면서 디자인 도구에게 뚜까 맞으면서 배운 것을 녹여 낸 것입니다.
EF 모델 패턴 연구 -
튜토리얼, 팁, 강좌 - 닷넷데브 (dotnetdev.kr)
물론 기본적으로 EF를 써야 한다는 입장에 기반한 것이고, 제가 그런 입장을 가진 가장 큰 이유는 앞서 설명한 부분들 - 타입 안정성과 효율성 - 입니다.
설계 단계에서 이러한 EF의 장점을 뽑을 대로 다 뽑았다면, 운영 단계에서 쿼리 성능을 올리는 것은 개인의 역량과 선호의 영역일 것 같습니다.
예를 들어, 어떤 분들은 EF가 Linq로부터 생성한 쿼리를 프로시저로 정의하고, 그 프로시저를 직접 호출해서 쿼리(Read) 성능을 올리기도 하더군요.
특히 CQRS 를 도입하는 경우, 그런 경향이 강한 것 같습니다. (이 방식에 대한 반대 여론도 만만치 않습니다.)
물론 이를 위해서는 EF 가 생성한 쿼리를 이해하고 개선할 수 있는 높은 숙련도가 요구됩니다.
불행하게도 저는 해당되지 않기에, 코드로만 처리할 수 있는 EF 에 더 매달리는 것인지도 모르겠습니다.