의존성 및 문제점에 대해서 간단히 다루고 이를 해결하기 위한 '의존성 주입'에 대해 다룹니다.
· 의존성?
의존성에 대해서는 많이 알려져있기때문에 간단하게 설명하면, 'A'가 변경될경우 'A'와 관련된 다른것들이 바뀌어야 한다는 것을 의미합니다.
· 예시
요구사항은 다음과 같습니다.
"식품 서비스 FoodService를 FastFoodService로 바꿔서 서비스해주세요."
- FoodService는 한식을 다루고, FastFoodService는 패스트푸드를 다룹니다.
public class Food
{
public string Name { get; set; }
public int Price { get; set; }
}
public class FoodService
{
public List<Food> GetFoods()
{
List<Food> foods = new List<Food>()
{
new Food() { Name = "Bibimbap", Price = 8000 },
new Food() { Name = "Kimbap", Price = 3000 },
new Food() { Name = "Bossam", Price = 30000 }
};
return foods;
}
}
public class FastFoodService
{
public List<Food> GetFoods()
{
List<Food> foods = new List<Food>()
{
new Food() { Name = "Burger", Price = 8000 },
new Food() { Name = "Fries", Price = 3000 },
};
return foods;
}
}
- 다른곳에서 FoodService를 사용하고있다면, FoodService를 모두 FastFoodService로 바꿔야합니다.
@page "/"
@using BlazorApp.Data;
<div>
@foreach (var food in _foodService.GetFoods())
{
<div>@food.Name</div>
<div>@food.Price</div>
}
</div>
@code {
//FoodService _foodService = new FoodService();
//이 코드로 대체
FastFoodService _foodService = new FastFoodService();
}
- 주석처리된 FoodService를 사용하는 클래스는 FastFoodService로 대체되어야합니다.
- 이 예시에서는 단순히 클래스만 변경하기에 크게 와닿지 않지만, 그 크기를 예측할 순 없습니다.
- 이런 사항을 해결하기 위해서 인터페이스를 사용할 수 있습니다.
· Interface
- Blazor은 C#문법을 사용하기때문에 Interface라는 이름으로 사용합니다.
public class Food
{
public string Name { get; set; }
public int Price { get; set; }
}
public interface IFoodService
{
IEnumerable<Food> GetFoods();
}
public class FoodService : IFoodService
{
public IEnumerable<Food> GetFoods()
{
List<Food> foods = new List<Food>()
{
new Food() { Name = "Bibimbap", Price = 8000 },
new Food() { Name = "Kimbap", Price = 3000 },
new Food() { Name = "Bossam", Price = 30000 }
};
return foods;
}
}
public class FastFoodService : IFoodService
{
public IEnumerable<Food> GetFoods()
{
List<Food> foods = new List<Food>()
{
new Food() { Name = "Burger", Price = 8000 },
new Food() { Name = "Fries", Price = 3000 },
};
return foods;
}
}
- IFoodService라는 인터페이스에 GetFoods()라는 함수가 있습니다.
- IFoodService에서 GetFoods를 할 때, 현재 서비스중인 서비스가 어떤것인지 명시해주면 추후에 다른 서비스로 바뀌어야할지라도 명시해준것만 바꿔주면 됩니다.
· 의존성 주입
- 인터페이스 타입으로 구현했다면, 웹에서 이 서비스를 사용할때 어떤 클래스(서비스타입)을 사용할지 알려줘야합니다. 이때 사용되는것이 의존성 주입입니다.
//Program.cs
...
// 서비스를 시작한다.
// IFoodService라는 인터페이스의 서비스는 FastFoodService로 할것이다.
builder.Services.AddSingleton<IFoodService, FastFoodService>();
...
- AddSingleton<>에서 IFoodService라는 인터페이스에 다음 매개변수로 FastFoodService가 들어갑니다.
- 이 말은 IFoodService에서 사용할것은 FastFoodService라는 뜻 입니다.
@page "/"
@using BlazorApp.Data;
@inject IFoodService foodService;
<div>
@foreach (var food in foodService.GetFoods())
{
<div>@food.Name</div>
<div>@food.Price</div>
}
</div>
@code {
}
- 서비스를 사용한다면, 해당 서비스를 다른 페이지에서 불러와야합니다.
- @inject IFoodService foodService;로 IFoodService를 foodService라는 이름으로 불러옵니다.
- foodService는 IFoodService클래스로서 사용방법은 다른 클래스들처럼 동일합니다.
· 서비스 변경
- 요구사항대로 서비스를 변경합니다.
- Program.cs에서 단순히 타입명만 바꿔주면 의존성 없이 유동적으로 변경할 수 있습니다.
· FoodService
// 서비스를 시작한다.
// IFoodService라는 인터페이스의 서비스는 FoodService 할것이다.
builder.Services.AddSingleton<IFoodService, FoodService>();
· FastFoodService
// 서비스를 시작한다.
// IFoodService라는 인터페이스의 서비스는 FastFoodService로 할것이다.
builder.Services.AddSingleton<IFoodService, FastFoodService>();
· 의존성 전이
- 만약 다른 인터페이스를 변수로 가지는 클래스가 있다면, 어떠한 인터페이스를 사용중이라고 알려줘야합니다.
- Blazor에서는 생성자에 의존성 인터페이스가 매개변수로 있다면, 이것을 자동으로 설정해줍니다.
//Program.cs
...
// 서비스를 시작한다.
// IFoodService라는 인터페이스의 서비스는 FoodService 할것이다.
builder.Services.AddSingleton<IFoodService, FastFoodService>();
// PaymentService를 서비스한다.
builder.Services.AddSingleton<PaymentService>();
...
- FastFoodService를 사용할때 PaymentService도 함께 사용한다고 설정한 상태입니다.
- 생성자에 인터페이스 변수를 초기화하도록 하였지만, 이 코드에서는 특별히 생성자에 대한 명시적 표현이 없습니다.
public class PaymentService
{
IFoodService _service;
// Dependency Injection에 의해 생성자에 필요한 매개변수가 자동으로 들어감!
public PaymentService(IFoodService service)
{
_service = service;
}
// TODO HERE
}
- PaymentService에 FoodService 인터페이스가 있고 생성자가 있습니다.
- 이 생성자를 어디에서도 호출하지 않았지만 IFoodService에는 FastFoodService타입의 인터페이스로 설정되게 됩니다.
'server > web server' 카테고리의 다른 글
[Web] 다이얼로그박스 및 유효성 검사 (0) | 2023.02.24 |
---|---|
[Web] 서비스 타입 (0) | 2023.02.24 |
[Web] 템플릿 컴포넌트 (0) | 2023.02.24 |
[Web] Cascading 파라미터 (0) | 2023.02.24 |
[Web] 컴포넌트 재사용 (0) | 2023.02.24 |