본문 바로가기

백엔드/닷넷

지네릭 패턴 - 유닛 오브 워크

반응형

지네릭 패턴은 엔티티 타입을 변경할 수 있게 해 주어 메서드를 공유할 수 있지만 각 엔티티 별로 구현체를 생성하므로 중복적인 인젝션과 다른 객체로 인식되어 엔티티 간에 서로 의존관계가 있는 경우 하나의 엔티티에 정보 등록이 실패할 경우 이로 인해 에러가 발생할 수 있는 단점이 있습니다.

 

이러한 문제를 해결하기 위해 각 엔티티를 하나의 워크 유닛으로 묶어 구현하는 유닛오브 워크 패턴을 살펴보겠습니다.

목차

프로젝트 설정

에이피아이 프로젝트 생성

 

.NET 웹 에이피아이 생성하기

개발도구 설치하기 .NET을 이용하여 웹애플리케이션을 만들기 위해서는 .NET에서 제공하는 개발도구가 필요합니다. 개발도구 다운로드는 아래 링크에서 가능합니다. .NET | Free. Cross-platform. Open Sour

jin-co.tistory.com

지네릭 패턴 구성

 

서버 아키텍처 - 지네릭 레포지토리

레포지토리는 정적 타입을 가지는 데 이는 엔티티가 증가할 때마다 레포지토리를 추가로 생성해야 하는 불편함을 줍니다. 지네릭은 동적으로 타입을 지정하는 기능으로 지네릭 레포지토리를

jin-co.tistory.com

구현하기

워크유닛 인터페이스 생성

인터페이스를 생성하고

아래와 같이 'IDisposable' 인터페이스를 상속하고 (해당 인터페이스는 생성된 각 컴포넌트를 처분하는 역할을 합니다), 지네릭 레포지토리 인터페이스와 각 엔티티의 작업완료상태를 배열로 저장할 속성을 추가합니다.

워크유닛 인터페이스 구현

생성한 인터페이스를 구현할 클래스를 생성하고

컨스트럭터를 생성하고 콘텍스트를 인젝션 하고 생성된 레포지토리를 관리할 헤쉬테이블을 추가합니다.

private readonly StoreContext _context;
private Hashtable _repos;
public WorkUnit(StoreContext context)
{
  this._context = context;
}

구현된 메서드에 아래와 같이 코드를 작성합니다

public async Task<int> Completed()
{
  return await _context.SaveChangesAsync();
}

public void Dispose()
{
  _context.Dispose();
}

public IGenericRepo<T> Repo<T>() where T : BaseEntity
{
  if (_repos == null) _repos = new Hashtable();
  var type = typeof(T).Name;
  if (!_repos.ContainsKey(type))
  {
    var repoType = typeof(GenericRepo<>);
    var repoInstance = Activator.CreateInstance(repoType.MakeGenericType(typeof(T)), _context)
    _repos.Add(type, repoInstance);
  }
  return (IGenericRepo<T>)_repos[type];
}

서비스 설정

Program.cs 파일에 서비스를 추가합니다

builder.Services.AddScoped<IWorkUnit, WorkUnit>();

지네릭 인터페이스 메서드 추가

지네릭 인터페이스에 아래 메서드들을 추가합니다

void Add(T entity);
void Update(T entity);
void Delete(T entity);

구현 클래스로 이동하여 추가한 메서드를 구현하고 아래처럼 코드를 수정합니다. 메서드의 기능은 부분업데이트를 막기 위한 코드로 각 엔티티의 작업을 Add로 추가하고 모든 작업이 끝났을 때 Complete를 통해 저장합니다.

public void Add(T entity)
{
  _context.Set<T>().Add(entity);
}

public void Delete(T entity)
{
  _context.Set<T>().Remove(entity);
}

public void Update(T entity)
{
  _context.Set<T>().Attach(entity);
  _context.Entry(entity).State = EntityState.Modified;
}

컨트롤러 수정하기

컨트롤러 파일로 이동하여

수정 전

인젝션 된 지네릭 레포지토리들을 삭제하고 워크유닛 인터페이스를 주입합니다

수정 후

데이터베이스 저장하기

엔티티의 부분 업데이트를 막기 위해 추가한 메서드는 아래와 같이 활용합니다

이상으로 지네릭 패턴의 단점인 인젝션의 중복과 부분업데이트로 인한 데이터 불일치 오류를 해결하기 위해 유닛오브 워크 패턴을 사용하는 방법을 보았습니다.

 

728x90
반응형