ejyoo's 개발 노트

EF Core DbContext 의 로딩방식 본문

BackEnd/.Net Core

EF Core DbContext 의 로딩방식

ejyoovV 2023. 8. 23. 08:50

EF Core 에서 DBContext를 사용하여 데이터를 조회할 때,

아래의 경우가 있다.

1) 조인하여 한번에 조회

2) 따로 따로 조회

3) DbContext로 각각 접근하여 조회

 

위의 방법을 통해서 데이터를 조회하게 되는데,

EF Core의 어떤 기준에 의해 저런 방법을 사용하여 데이터를 조회하는지 궁금하여 정리를 해보았다.

 


 

EF Core (Entity Framework Core)에서 데이터를 로딩하는 방식에는 크게 세가지 방법이 있다.

 

1. 지연로딩 (Lazy Loading)

2. 즉시 로딩 (Eager Loading)

3. 명시적 로딩 (Explicit Loading)

 

 

 

1. 지연 로딩 (Lazy Loading)
지연로딩은 연관된 엔터티나 컬렉션에 처음 접근할 때 실제 데이터가 로드되는 방식이다.

이 방식을 사용하려면 아래의 작업을 수행해야 한다.

1) EF Core 모델링 시 네비게이션 속성에 'virtual' 키워드를 추가해야 한다.

2) `Microsoft.EntityFrameworkCore.Proxies` 패키지를 설치하고 DbContext에서 UseLazyLoadingProxies() 를 설정하여 프록시 사용을 활성화해야 한다.

   - DbContext 구성 예제

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseLazyLoadingProxies().UseSqlServer(myConnectionString);
}

   - 프록시 사용 활성화 외에 아래의 다른 방법을 사용할 수 있다.

     * 설정된 DbContext를 상속

        - 기본 DbContext에서 Lazy Loading이 활성화된 설정을 상속받아 사용하면 해당 설정이 자동적용됨.

     * 라이브러리에서 설정 : EF Core나 프로젝트 설정 업데이트 시 Lazy Loading이 기본적으로 활성화 될 수 있음. 이 경우 패키지의 업데이트 이력을 확인해야 함.

 

지연 로딩의 예제

아래의 코드를 확인해보자.

var resultData = context.A.ToList();
context.B.ToList();

A, B 엔터티가 각각 존재하고

B는 A를 참조하고 있다고 가정할 때,

A의 인스턴스 중 하나의 B 네비게이션 속성에 접근하려고 시도하면 지연 로딩이 작동하면서 A엔터티와 관련된 B엔터티를 데이터베이스에서 가져온다.

하지만 위의 예제에서 context.B.ToList()를 호출하였기 때문에

EF Core의 로컬 캐시에 B 엔터티가 이미 존재하므로 실제로 데이터베이스가 쿼리를 다시 실행하지 않는다.

 

요약하면 context.A.ToList() 와 context.B.ToList()를 호출한 후

resultData에 있는 A인스턴스의 B네비케이션 속성에 접근하면

그 네비게이션 속성은 지연로딩을 통해 채워지게 된다.

이미 B가 로컬 캐시에 로드되어 있기 때문에 실제로 데이터베이스 쿼리가 다시 실행되진 않는다.

https://learn.microsoft.com/en-us/ef/core/querying/related-data/lazy

 

Lazy Loading of Related Data - EF Core

Lazy loading of related data with Entity Framework Core

learn.microsoft.com


2. 즉시 로딩 (Eager Loading)
즉시로딩은 DB 조회 시 주 엔터티와 연관된 엔터티나 컬렉션을 하나의 쿼리로 함께 로드하는 방식이다.

Include 나 ThenInclude 메서드를 사용하여 필요한 네비게이션 속성을 명시적으로 로드가 가능하다.

Include 로 조회된 네비게이션 속성에 대한 조건 검색은 불가능하며,

네비게이션 속성에 대한 조건 검색이 필요한 경우에는 즉시로딩의 방식 말고 다른 방법을 고안해야 한다.

  - 다른 방법 ex) EFCore - 지연로딩과 로컬 캐싱 특성 이용

아래의 코드는 즉시 로딩에 대한 예제이다.

A 엔터티를 조회할 때 관련된 B엔터티를 함께 로드하게 된다.

모델링 시 As 안에 Bs 네비게이션 속성이 존재해야 한다.

var data = context.As.Include(a => a.Bs).ToList();



3. 명시적 로딩 (Explicit Loading)
명시적 로딩은 연관된 엔터티나 컬렉션을 명시적으로 로드하는 방식이다.

주 엔터티를 먼저 로드한 뒤 후에 필요할 때 연관된 엔터티나 컬렉션을 별도의 쿼리로 로드한다.

'Load' 메서드를 사용하여 연관된 데이터를 로드한다.

 

각 로딩 전략은 특정 상황에 따라 장단점이 있으므로, 상황과 요구 사항에 따라 적절한 방식을 선택하는 것이 중요하다.