[ASP.NET Core] Dependency Injection 예제
- 웹 프로그래밍/ASP.NET & ASP.NET Core
- 2022. 4. 15. 05:35
참고
소개
- ASP.NET Core는 처음부터 종속성 주입을 지원하도록 설계되었습니다.
- ASP.NET Core는 기본 제공 IoC 컨테이너를 사용하여 생성자 또는 메서드를 통해 종속성 클래스의 객체를 주입합니다.
IoC(Inversion Of Control)란?
- Inversion of Control(IoC) : Dependency Inversion Principle 을 적용하는 방법입니다.
- Inversion of Control은 상위 수준 components 가 하위 수준 components의 구체적인 구현이 아닌 추상화(abstraction) 에 의존하도록 하는 실제 메커니즘입니다.
- Inversion of Control은 할리우드 원리(Hollywood Principle) 라고도 합니다.
- 이 이름은 할리우드 영화 산업에서 따온 것으로, 배우 오디션이 끝난 후 감독은 보통 "우리에게 전화하지 마세요. 우리가 전화할 것입니다." 라고 말합니다.
IoC Container란? : DI(Dependency Injection) Container 라고도 하며, Components 의 자동 Dependency Injection을 제공하는 프로그래밍 Framework 입니다.
Built-in IoC Container
- ASP.NET Core 프레임워크에는 다른 타사 IoC 컨테이너만큼 많은 기능이 없는 즉시 사용 가능한 간단한 IoC 컨테이너가 포함되어 있습니다.
- 자동 등록, 스캐닝, 인터셉터 또는 데코레이터와 같은 더 많은 기능을 원하면 내장 IoC 컨테이너를 타사 컨테이너로 교체할 수 있습니다.
- 기본 제공 컨테이너는 기본적으로 생성자 주입을 지원하는 IServiceProvider 구현으로 표시됩니다.
- 내장 IoC 컨테이너에서 관리하는 유형(클래스) 를 서비스라고 합니다.
- ASP.NET Core 에는 기본적으로 두 가지 유형의 서비스가 있습니다.
- Framework Services : IApplicationBuilder, IHostingEnvirnoment, ILoggerFactory 등과 같은 ASP.NET Core 프레임 워크의 일부 서비스
- Application Services : 프로그래머가 응용 프로그램을 위해 만드는 서비스(사용자 지정 유형 또는 클래스) 를 의미합니다.
- IoC 컨테이너가 자동으로 애플리케이션 서비스를 주입하도록 하려면 먼저 IoC 컨테이너에 서비스를 등록해야 합니다.
Dependency Injection 예제
- ASP.NET Core Web API 프로젝트를 생성하고, Dependency Injection(DI) 로직을 작성해 보도록 하겠습니다.
1. ASP.NET Core Web API 프로젝트 생성
- 첫 번째로, ASP.NET Core Web API 프로젝트를 생성합니다.
2. Model 클래스 생성
- 예제로 Blog 라는 모델 클래스를 생성합니다.
- Models 폴더를 생성하고, 해당 폴더 안에 Blog.cs 클래스를 생성합니다.
namespace BlogDIDemo.Models
{
public class Blog
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
}
}
3. 데이터 관련 클래스 생성
- 다음으로 앞서 만든 Blog 객체를 관리 및 데이터 생성하는 클래스를 생성합니다.
- Data 폴더를 생성하고, 폴더 안에 BlogRepository.cs 클래스를 생성하여 다음과 같이 코드를 작성합니다.
using BlogDIDemo.Models;
namespace BlogDIDemo.Data
{
public class BlogRepository
{
public static List<Blog> blogs = new()
{
new Blog(){ Id = 1, Title = "DI Deep Dive", Content = "This is a five part series"},
new Blog(){ Id = 2, Title = "Minimal API", Content = "Learn in 30 mins"},
new Blog(){ Id = 3, Title = "Prescription API", Content = "Still under construction"}
};
public List<Blog> GetAllBlogs()
{
return blogs;
}
}
}
4. 컨트롤러 추가
- 다음으로 Controllers 폴더 안에 읽기/쓰기 전용의 API 컨트롤러 클래스를 생성합니다.
- 이름은 BlogController.cs 라고 하였습니다.
- 그리고 다음과 같이 BlogController.cs 에 코드를 작성합니다.
using BlogDIDemo.Data;
using BlogDIDemo.Models;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace BlogDIDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BlogController : ControllerBase
{
BlogRepository repository = new BlogRepository();
// GET: api/<BlogController>
[HttpGet]
public ActionResult<IEnumerable<Blog>> Get()
{
var blogs = repository.GetAllBlogs();
return Ok(blogs);
}
}
}
- 여기까지 작성 후, 프로젝트 실행하게 되면 정상적으로 실행은 됩니다.
- 하지만, 현재 BlogController 클래스 안에는 직접 BlogRepository 클래스를 의존하고 있습니다.
- 이와 같이 직접적인 의존은 추후에 코드 변경사항이 생기게 되면 참조되어 있는 모든 부분을 찾아서 수정해야 하는 단점이 있습니다.
- 때문에 이런 문제를 해결하려면, Interface 를 이용하여 추상화 작업을 하면 됩니다.
5. 인터페이스 생성
- Data 폴더 안에 IBlogRepository.cs 인터페이스를 생성합니다.
- 그리고 BlogRepository 클래스는 IBlogRepository 인터페이스를 상속 받도록 합니다.
IBlogRepository.cs
using BlogDIDemo.Models;
namespace BlogDIDemo.Data
{
public interface IBlogRepository
{
List<Blog> GetAllBlogs();
}
}
BlogRepository.cs
using BlogDIDemo.Models;
namespace BlogDIDemo.Data
{
public class BlogRepository : IBlogRepository
{
public static List<Blog> blogs = new()
{
new Blog() { Id = 1, Title = "DI Deep Dive", Content = "This is a five part series" },
new Blog() { Id = 2, Title = "Minimal API", Content = "Learn in 30 mins" },
new Blog() { Id = 3, Title = "Prescription API", Content = "Still under construction" }
};
public List<Blog> GetAllBlogs()
{
return blogs;
}
}
}
6. 생성자에 의존성 주입
- 이제 앞서 생성한 IBlogRepository 인터페이스의 객체를 BlogsController 클래스 생성자에 주입합니다.
- 이 작업은 앞서 BlogRepository 객체를 직접 참조하는 강한 결합을 해제하고 느슨한 결합으로 바꾸는 작업입니다.
- BlogController.cs 의 바뀐 소스 코드 내용은 다음과 같습니다.
using BlogDIDemo.Data;
using BlogDIDemo.Models;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace BlogDIDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BlogController : ControllerBase
{
private readonly IBlogRepository _repository;
public BlogController(IBlogRepository repository)
{
_repository = repository;
}
// GET: api/<BlogController>
[HttpGet]
public ActionResult<IEnumerable<Blog>> Get()
{
var blogs = _repository.GetAllBlogs();
return Ok(blogs);
}
}
}
- 위 코드에서 보는 것과 같이 IBlogRepository 객체만 받지, 직접적으로 클래스 안에서 BlogRepository 객체를 생성하는 부분은 없어졌습니다.
7. 종속성 추가하기
- 이제 Dependency Injection 을 나타내는 코드는 모두 작성 완료하였습니다.
- 마지막으로 종속성을 추가해야 합니다.
- 종속성을 추가하는 방법은 program.cs 에 다음과 같음 모드를 추가하면 됩니다.
program.cs
// My Dependency Injection Service Add
builder.Services.AddTransient<IBlogRepository, BlogRepository>();
- 실행 결과, 정상적으로 실행 되는 것을 확인할 수 있습니다.
8. 새로운 데이터 추가
- 만약 기존의 Blog 데이터에서 새로운 Blog Repository의 데이터가 추가되었다고 가정합니다.
- Data 폴더에 NewBlogsRepository.cs 클래스를 추가합니다.
- 그리고 다음과 같이 코드를 작성합니다.
using BlogDIDemo.Models;
namespace BlogDIDemo.Data
{
public class NewBlogRepository : IBlogRepository
{
public static List<Blog> blogs = new()
{
new Blog() { Id = 1000, Title = "DI Deep Dive", Content = "This is a five part series" },
new Blog() { Id = 2000, Title = "Minimal API", Content = "Learn in 30 mins" },
new Blog() { Id = 3000, Title = "Prescription API", Content = "Still under construction" }
};
public List<Blog> GetAllBlogs()
{
return blogs;
}
}
}
- 그리고 앞서 의존성 추가했던 소스코드에서 BlogRepository -> NewBlogRepository 로만 변경하여 프로그램을 실행 시켜 봅니다.
// My Dependency Injection Service Add
builder.Services.AddTransient<IBlogRepository, NewBlogRepository>();
- 실행 결과, NewBlogRepository 의 데이터들이 나오는 것을 확인할 수 있습니다.
- Dependency Injection 을 통하여 대상 Repository 만 변경할 뿐, Controller 는 변경없이 쉽게 Repository를 다룰 수 있는 것을 확인할 수 있습니다.
728x90
'웹 프로그래밍 > ASP.NET & ASP.NET Core' 카테고리의 다른 글
[ASP.NET Core] 서비스 생명주기 예제 (0) | 2022.04.16 |
---|---|
[ASP.NET Core] 서비스 생명주기 Singleton, Scoped, Transient (0) | 2022.04.15 |
[ASP.NET Core] ASP.NET Core Solution 구조 (0) | 2022.04.15 |
[ASP.NET Core] 의존성 역전 원칙 예제(DIP) (0) | 2022.04.14 |
[ASP.NET Core] 의존성 주입(Dependency Injection) 이란? (0) | 2022.04.14 |
이 글을 공유하기