๐ .NET Core ์ฝ์ ์ฑ์์ ์์กด์ฑ ์ฃผ์ ์ฌ์ฉํ๊ธฐ

์๋ ํ์ธ์, ์ฌ๋ฅ๋ท ๋ ์ ์ฌ๋ฌ๋ถ! ์ค๋์ .NET Core ์ฝ์ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์์กด์ฑ ์ฃผ์ (Dependency Injection, DI)์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค. ์ด ๊ธ์ ํตํด ์ฌ๋ฌ๋ถ์ ์ฝ์ ์ฑ์์๋ ์์กด์ฑ ์ฃผ์ ์ ๊ฐ๋ ฅํ ์ด์ ์ ํ์ฉํ ์ ์๊ฒ ๋ ๊ฒ์ ๋๋ค. ๐
์์กด์ฑ ์ฃผ์ ์ ํ๋ ์ํํธ์จ์ด ๊ฐ๋ฐ์์ ์ค์ํ ๋์์ธ ํจํด ์ค ํ๋๋ก, ์ฝ๋์ ์ ์ฐ์ฑ, ํ ์คํธ ์ฉ์ด์ฑ, ๊ทธ๋ฆฌ๊ณ ์ ์ง๋ณด์์ฑ์ ํฌ๊ฒ ํฅ์์ํต๋๋ค. ํนํ C# ๊ฐ๋ฐ์๋ค์๊ฒ๋ ํ์์ ์ธ ๊ธฐ์ ์ด๋ผ๊ณ ํ ์ ์์ฃ .
์ด ๊ธ์์๋ ์์กด์ฑ ์ฃผ์ ์ ๊ธฐ๋ณธ ๊ฐ๋ ๋ถํฐ ์์ํ์ฌ, .NET Core์ ๋ด์ฅ DI ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ, ๊ทธ๋ฆฌ๊ณ ์ค์ ์ฝ์ ์ฑ์ ์ ์ฉํ๋ ๊ณผ์ ๊น์ง ๋จ๊ณ๋ณ๋ก ์ดํด๋ณผ ์์ ์ ๋๋ค. ๋ํ, ์์กด์ฑ ์ฃผ์ ์ ์ฌ์ฉํ ๋์ ๋ชจ๋ฒ ์ฌ๋ก์ ์ฃผ์ํด์ผ ํ ์ ๋ค๋ ํจ๊ป ๋ค๋ฃจ๊ฒ ์ต๋๋ค.
์, ๊ทธ๋ผ ์ง๊ธ๋ถํฐ .NET Core ์ฝ์ ์ฑ์ ์ธ๊ณ์ ์์กด์ฑ ์ฃผ์ ์ด๋ผ๋ ๋ง๋ฒ์ ๋ถ์ด๋ฃ์ด ๋ณผ๊น์? ๐ซ
๐ ๋ชฉ์ฐจ
- ์์กด์ฑ ์ฃผ์ ์ ๊ธฐ๋ณธ ๊ฐ๋
- .NET Core์ ์์กด์ฑ ์ฃผ์ ์ปจํ ์ด๋ ์๊ฐ
- ์ฝ์ ์ฑ์์ ์์กด์ฑ ์ฃผ์ ์ค์ ํ๊ธฐ
- ์๋น์ค ๋ฑ๋ก๊ณผ ์๋ช ๊ด๋ฆฌ
- ์์กด์ฑ ์ฃผ์ ์ ํ์ฉํ ์ฝ์ ์ฑ ๊ตฌ์กฐํ
- ์ค์ ์์ : ๋ ์จ ์ ๋ณด ์ฝ์ ์ฑ ๋ง๋ค๊ธฐ
- ํ ์คํธ์ ์์กด์ฑ ์ฃผ์
- ๊ณ ๊ธ ์ฃผ์ : ์ปค์คํ DI ์ปจํ ์ด๋ ๋ง๋ค๊ธฐ
- ์ฑ๋ฅ ์ต์ ํ ํ
- ์์กด์ฑ ์ฃผ์ ์ ๋ชจ๋ฒ ์ฌ๋ก์ ์ํฐ ํจํด
- ๋ง๋ฌด๋ฆฌ ๋ฐ ์ถ๊ฐ ํ์ต ์๋ฃ
1. ์์กด์ฑ ์ฃผ์ ์ ๊ธฐ๋ณธ ๊ฐ๋ ๐ก
์์กด์ฑ ์ฃผ์ ์ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์์ ์ค์ํ ๋์์ธ ํจํด ์ค ํ๋์ ๋๋ค. ์ด ๊ฐ๋ ์ ์ดํดํ๊ธฐ ์ํด, ๋จผ์ '์์กด์ฑ'์ด ๋ฌด์์ธ์ง ์์๋ณด๊ฒ ์ต๋๋ค.
์์กด์ฑ์ด๋?
ํ๋ก๊ทธ๋๋ฐ์์ ์์กด์ฑ์ ํ ํด๋์ค๊ฐ ๋ค๋ฅธ ํด๋์ค์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ๋ ๋ฐ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ๋ณด๊ฒ ์ต๋๋ค:
public class EmailService
{
public void SendEmail(string to, string subject, string body)
{
// ์ด๋ฉ์ผ ์ ์ก ๋ก์ง
}
}
public class UserService
{
private EmailService _emailService = new EmailService();
public void RegisterUser(string email)
{
// ์ฌ์ฉ์ ๋ฑ๋ก ๋ก์ง
_emailService.SendEmail(email, "Welcome!", "Welcome to our service!");
}
}
์ ์ฝ๋์์ UserService
ํด๋์ค๋ EmailService
ํด๋์ค์ ์์กดํ๊ณ ์์ต๋๋ค. ์ด๋ UserService
๊ฐ EmailService
์ ์ธ์คํด์ค๋ฅผ ์ง์ ์์ฑํ๊ณ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
๋๋ค.
์์กด์ฑ ์ฃผ์ ์ ์ ์
์์กด์ฑ ์ฃผ์ ์ ์ด๋ฌํ ์์กด ๊ด๊ณ๋ฅผ ์ธ๋ถ์์ ์ฃผ์ ํ๋ ๋ฐฉ์์ ๋๋ค. ์ฆ, ํด๋์ค๊ฐ ์์กดํ๋ ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ๋ ๋์ , ์ธ๋ถ์์ ์์ฑ๋ ๊ฐ์ฒด๋ฅผ ๋ฐ์ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
์์ ์์ ๋ฅผ ์์กด์ฑ ์ฃผ์ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
public class UserService
{
private readonly IEmailService _emailService;
public UserService(IEmailService emailService)
{
_emailService = emailService;
}
public void RegisterUser(string email)
{
// ์ฌ์ฉ์ ๋ฑ๋ก ๋ก์ง
_emailService.SendEmail(email, "Welcome!", "Welcome to our service!");
}
}
์ด์ UserService
๋ IEmailService
์ธํฐํ์ด์ค์ ์์กดํ๋ฉฐ, ์์ฑ์๋ฅผ ํตํด ์ด ์์กด์ฑ์ ์ฃผ์
๋ฐ์ต๋๋ค.
์์กด์ฑ ์ฃผ์ ์ ์ด์
- ๋์จํ ๊ฒฐํฉ: ํด๋์ค ๊ฐ์ ์์กด์ฑ์ด ์ค์ด๋ค์ด ์ฝ๋์ ์ ์ฐ์ฑ์ด ์ฆ๊ฐํฉ๋๋ค.
- ํ ์คํธ ์ฉ์ด์ฑ: ๋ชฉ(mock) ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๋จ์ ํ ์คํธ๋ฅผ ์ฝ๊ฒ ์ํํ ์ ์์ต๋๋ค.
- ์ ์ง๋ณด์์ฑ: ์์กดํ๋ ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ๊ต์ฒดํ ์ ์์ด ์ฝ๋ ์์ ์ด ์ฉ์ดํฉ๋๋ค.
- ์ฌ์ฌ์ฉ์ฑ: ๋์ผํ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ๋ค์ํ ํด๋์ค๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์์กด์ฑ ์ฃผ์ ์ ์ ํ
์์กด์ฑ ์ฃผ์ ์ ์ฃผ๋ก ์ธ ๊ฐ์ง ๋ฐฉ์์ผ๋ก ์ด๋ฃจ์ด์ง๋๋ค:
- ์์ฑ์ ์ฃผ์ : ๊ฐ์ฅ ํํ ์ฌ์ฉ๋๋ ๋ฐฉ์์ผ๋ก, ํด๋์ค์ ์์ฑ์๋ฅผ ํตํด ์์กด์ฑ์ ์ฃผ์ ๋ฐ์ต๋๋ค.
- ์์ฑ ์ฃผ์ : ๊ณต๊ฐ ์์ฑ์ ํตํด ์์กด์ฑ์ ์ค์ ํฉ๋๋ค.
- ๋ฉ์๋ ์ฃผ์ : ๋ฉ์๋ ํธ์ถ์ ํตํด ์์กด์ฑ์ ์ ๋ฌ๋ฐ์ต๋๋ค.
์ด ์ค์์ ์์ฑ์ ์ฃผ์ ์ด ๊ฐ์ฅ ๊ถ์ฅ๋๋ ๋ฐฉ์์ ๋๋ค. ์๋ํ๋ฉด ๊ฐ์ฒด ์์ฑ ์์ ์ ๋ชจ๋ ์์กด์ฑ์ด ์ ๊ณต๋๋ฏ๋ก, ๊ฐ์ฒด๊ฐ ํญ์ ์ ํจํ ์ํ๋ฅผ ์ ์งํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์์กด์ฑ ์ฃผ์ ์ ๊ฐ๋ ์ ์ดํดํ๋ค๋ฉด, ์ด์ .NET Core์์ ์ด๋ฅผ ์ด๋ป๊ฒ ๊ตฌํํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค. .NET Core๋ ๋ด์ฅ๋ DI ์ปจํ ์ด๋๋ฅผ ์ ๊ณตํ์ฌ ์์กด์ฑ ์ฃผ์ ์ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋๋ก ์ง์ํฉ๋๋ค.
๋ค์ ์น์ ์์๋ .NET Core์ DI ์ปจํ ์ด๋์ ๋ํด ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฅผ ํตํด ์ฌ๋ฌ๋ถ์ ์ฝ์ ์ฑ์์ ์์กด์ฑ ์ฃผ์ ์ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ๊ธฐ๋ฐ์ ๊ฐ์ถ๊ฒ ๋ ๊ฒ์ ๋๋ค. ๐
2. .NET Core์ ์์กด์ฑ ์ฃผ์ ์ปจํ ์ด๋ ์๊ฐ ๐งฐ
.NET Core๋ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ๋ด์ฅ ์์กด์ฑ ์ฃผ์
์ปจํ
์ด๋๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ์ปจํ
์ด๋๋ Microsoft.Extensions.DependencyInjection
๋ค์์คํ์ด์ค์ ํฌํจ๋์ด ์์ผ๋ฉฐ, ASP.NET Core ์ ํ๋ฆฌ์ผ์ด์
๋ฟ๋ง ์๋๋ผ ์ฝ์ ์ฑ์์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
DI ์ปจํ ์ด๋์ ์ฃผ์ ๊ตฌ์ฑ ์์
- IServiceCollection: ์๋น์ค ๋ฑ๋ก์ ์ํ ์ธํฐํ์ด์ค
- ServiceProvider: ๋ฑ๋ก๋ ์๋น์ค์ ์ธ์คํด์ค๋ฅผ ์ ๊ณตํ๋ ํฉํ ๋ฆฌ
- ServiceDescriptor: ์๋น์ค ๋ฑ๋ก ์ ๋ณด๋ฅผ ๋ด๋ ํด๋์ค
์๋น์ค ๋ฑ๋ก ๋ฐฉ๋ฒ
์๋น์ค๋ฅผ ๋ฑ๋กํ๋ ์ฃผ์ ๋ฉ์๋๋ค์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
AddTransient<TService, TImplementation>()
: ์์ฒญํ ๋๋ง๋ค ์ ์ธ์คํด์ค ์์ฑAddScoped<TService, TImplementation>()
: ๋ฒ์(์ฃผ๋ก ์น ์์ฒญ) ๋น ํ๋์ ์ธ์คํด์ค ์์ฑAddSingleton<TService, TImplementation>()
: ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด์์ ํ๋์ ์ธ์คํด์ค๋ง ์ฌ์ฉ
์ด๋ฌํ ๋ฉ์๋๋ค์ IServiceCollection
์ธํฐํ์ด์ค์ ํ์ฅ ๋ฉ์๋๋ก ์ ๊ณต๋ฉ๋๋ค.
๊ธฐ๋ณธ ์ฌ์ฉ ์์
๋ค์์ .NET Core์ DI ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ๋ ๊ธฐ๋ณธ์ ์ธ ์์ ์ ๋๋ค:
using Microsoft.Extensions.DependencyInjection;
public class Program
{
public static void Main(string[] args)
{
// ์๋น์ค ์ปฌ๋ ์
์์ฑ
var services = new ServiceCollection();
// ์๋น์ค ๋ฑ๋ก
services.AddTransient<IMyService, MyService>();
// ์๋น์ค ํ๋ก๋ฐ์ด๋ ์์ฑ
var serviceProvider = services.BuildServiceProvider();
// ์๋น์ค ์ฌ์ฉ
var myService = serviceProvider.GetService<IMyService>();
myService.DoSomething();
}
}
public interface IMyService
{
void DoSomething();
}
public class MyService : IMyService
{
public void DoSomething()
{
Console.WriteLine("Doing something...");
}
}
DI ์ปจํ ์ด๋์ ์๋ ์๋ฆฌ
.NET Core์ DI ์ปจํ ์ด๋๋ ๋ค์๊ณผ ๊ฐ์ ๊ณผ์ ์ผ๋ก ์๋ํฉ๋๋ค:
- ์๋น์ค ๋ฑ๋ก:
IServiceCollection
์ ์๋น์ค์ ๊ทธ ๊ตฌํ์ ๋ฑ๋กํฉ๋๋ค. - ์๋น์ค ํ๋ก๋ฐ์ด๋ ์์ฑ:
BuildServiceProvider()
๋ฉ์๋๋ฅผ ํธ์ถํ์ฌIServiceProvider
์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค. - ์๋น์ค ํด๊ฒฐ:
GetService<T>()
๋๋GetRequiredService<T>()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํ์ํ ์๋น์ค์ ์ธ์คํด์ค๋ฅผ ์ป์ต๋๋ค.
DI ์ปจํ ์ด๋์ ์ฅ์
- ์๋ ์์กด์ฑ ํด๊ฒฐ: ๋ณต์กํ ์์กด์ฑ ๊ทธ๋ํ๋ ์๋์ผ๋ก ํด๊ฒฐํฉ๋๋ค.
- ์๋ช ๊ด๋ฆฌ: ์๋น์ค์ ์๋ช ์ ์ฝ๊ฒ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
- ํ ์คํธ ์ฉ์ด์ฑ: ๋ชฉ(mock) ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ์ฃผ์ ํ ์ ์์ด ๋จ์ ํ ์คํธ๊ฐ ์ฉ์ดํฉ๋๋ค.
- ๊ตฌ์ฑ์ ์ค์ํ: ์ ํ๋ฆฌ์ผ์ด์ ์ ์์กด์ฑ ๊ตฌ์ฑ์ ํ ๊ณณ์์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
์ฃผ์์ฌํญ
DI ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ ๋ ์ฃผ์ํด์ผ ํ ์ ๋ค์ด ์์ต๋๋ค:
- ์ํ ์์กด์ฑ์ ํผํด์ผ ํฉ๋๋ค.
- ์๋น์ค์ ์๋ช ์ ์ ์ ํ ์ ํํด์ผ ํฉ๋๋ค.
- ์ปจํ ์ด๋์ ๋๋ฌด ๋ง์ ์ฑ ์์ ๋ถ์ฌํ์ง ์๋๋ก ์ฃผ์ํด์ผ ํฉ๋๋ค.
์ด์ .NET Core์ DI ์ปจํ ์ด๋์ ๋ํด ๊ธฐ๋ณธ์ ์ธ ์ดํด๋ฅผ ๊ฐ๊ฒ ๋์์ต๋๋ค. ๋ค์ ์น์ ์์๋ ์ด ์ง์์ ๋ฐํ์ผ๋ก ์ค์ ์ฝ์ ์ฑ์์ ์์กด์ฑ ์ฃผ์ ์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๐ ๏ธ
์ฌ๋ฅ๋ท์์ ์ ๊ณตํ๋ ์ด ๊ธ์ ํตํด, ์ฌ๋ฌ๋ถ์ .NET Core์ ๊ฐ๋ ฅํ DI ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ๋ ์ ์ฐํ๊ณ ์ ์ง๋ณด์๊ฐ ์ฌ์ด ์ฝ์ ์ฑ์ ๋ง๋ค ์ ์์ ๊ฒ์ ๋๋ค. ๊ณ์ํด์ ๋ค์ ๋ด์ฉ์ ์ดํด๋ณด์์ฃ !
3. ์ฝ์ ์ฑ์์ ์์กด์ฑ ์ฃผ์ ์ค์ ํ๊ธฐ ๐ง
์ด์ .NET Core ์ฝ์ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์์กด์ฑ ์ฃผ์ ์ ์ค์ ๋ก ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด ๊ณผ์ ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์์ ์ค์ ๊ณผ๋ ์ฝ๊ฐ ๋ค๋ฅด์ง๋ง, ๊ธฐ๋ณธ ์๋ฆฌ๋ ๋์ผํฉ๋๋ค.
1. ํ๋ก์ ํธ ์ค์
๋จผ์ , ์๋ก์ด .NET Core ์ฝ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฑํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํ์ํ NuGet ํจํค์ง๋ฅผ ์ถ๊ฐํฉ๋๋ค:
dotnet new console -n MyConsoleApp
cd MyConsoleApp
dotnet add package Microsoft.Extensions.DependencyInjection
dotnet add package Microsoft.Extensions.Hosting
Microsoft.Extensions.Hosting
ํจํค์ง๋ ์์กด์ฑ ์ฃผ์
์ค์ ์ ๋ ์ฝ๊ฒ ๋ง๋ค์ด์ฃผ๋ IHost
์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํฉ๋๋ค.
2. ํ๋ก๊ทธ๋จ ๊ตฌ์กฐ ์ค์
์ด์ Program.cs
ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ์์ ํฉ๋๋ค:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
class Program
{
static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
// ์ฌ๊ธฐ์ ์๋น์ค๋ฅผ ๋ฑ๋กํฉ๋๋ค
services.AddTransient<IMyService, MyService>();
services.AddHostedService<MyHostedService>();
});
}
public interface IMyService
{
void DoWork();
}
public class MyService : IMyService
{
public void DoWork()
{
Console.WriteLine("Doing some work!");
}
}
public class MyHostedService : IHostedService
{
private readonly IMyService _myService;
public MyHostedService(IMyService myService)
{
_myService = myService;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_myService.DoWork();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
3. ์ฝ๋ ์ค๋ช
CreateHostBuilder
๋ฉ์๋๋IHostBuilder
๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ฑ, ๋ก๊น , DI ์ปจํ ์ด๋ ์ค์ ๋ฑ์ ๋ด๋นํฉ๋๋ค.ConfigureServices
๋ฉ์๋ ๋ด์์ ์๋น์ค๋ฅผ DI ์ปจํ ์ด๋์ ๋ฑ๋กํฉ๋๋ค.AddHostedService
๋ฅผ ์ฌ์ฉํ์ฌMyHostedService
๋ฅผ ๋ฐฑ๊ทธ๋ผ์ด๋ ์๋น์ค๋ก ๋ฑ๋กํฉ๋๋ค. ์ด ์๋น์ค๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋ ๋ ์คํ๋ฉ๋๋ค.MyHostedService
๋ ์์ฑ์๋ฅผ ํตํดIMyService
๋ฅผ ์ฃผ์ ๋ฐ์ต๋๋ค.
4. ์์กด์ฑ ์ฃผ์ ์๋ ์๋ฆฌ
์ด ๋ค์ด์ด๊ทธ๋จ์ ์ฝ์ ์ฑ์์ ์์กด์ฑ ์ฃผ์ ์ด ์ด๋ป๊ฒ ์ค์ ๋๊ณ ์คํ๋๋์ง๋ฅผ ๋ณด์ฌ์ค๋๋ค.
5. ์คํ ๋ฐ ํ ์คํธ
์ด์ ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ๋ฉด, MyHostedService
๊ฐ ์์๋๊ณ IMyService
์ DoWork
๋ฉ์๋๊ฐ ํธ์ถ๋ฉ๋๋ค.
dotnet run
์ถ๋ ฅ:
Doing some work!
6. ์ฅ์ ๋ฐ ์ฃผ์์ฌํญ
์ฅ์ :
- ์ฝ๋์ ๋ชจ๋์ฑ๊ณผ ํ ์คํธ ์ฉ์ด์ฑ์ด ํฅ์๋ฉ๋๋ค.
- ์๋น์ค์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ฝ๊ฒ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
- ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์กฐ๊ฐ ๋ ๋ช ํํด์ง๋๋ค.
์ฃผ์์ฌํญ:
- ๊ฐ๋จํ ์ฝ์ ์ฑ์ ๊ฒฝ์ฐ, ์ด๋ฌํ ์ค์ ์ด ๊ณผ๋ํ ์ ์์ต๋๋ค. ํ๋ก์ ํธ์ ๋ณต์ก์ฑ์ ๊ณ ๋ คํ์ฌ ์ ์ฉํ์ธ์.
- ์์กด์ฑ ์ฃผ์ ์ ๊ณผ๋ํ๊ฒ ์ฌ์ฉํ๋ฉด ์ฝ๋์ ๋ณต์ก์ฑ์ด ์ฆ๊ฐํ ์ ์์ต๋๋ค.
- ์ฑ๋ฅ์ ๋ฏผ๊ฐํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ, DI ์ปจํ ์ด๋์ ์ค๋ฒํค๋๋ฅผ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
์ด์ ์ฌ๋ฌ๋ถ์ .NET Core ์ฝ์ ์ฑ์์ ์์กด์ฑ ์ฃผ์ ์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ ์ต๋๋ค. ์ด ๊ธฐ์ ์ ํ์ฉํ๋ฉด, ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ์์ ์ ๊ณตํ๋ ๋ค์ํ ์๋น์ค๋ค์ ๋ ํจ์จ์ ์ผ๋ก ํตํฉํ๊ณ ๊ด๋ฆฌํ ์ ์์ต๋๋ค. ๋ค์ ์น์ ์์๋ ์๋น์ค ๋ฑ๋ก๊ณผ ์๋ช ๊ด๋ฆฌ์ ๋ํด ๋ ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค. ๐
4. ์๋น์ค ๋ฑ๋ก๊ณผ ์๋ช ๊ด๋ฆฌ โณ
์์กด์ฑ ์ฃผ์ ์ปจํ ์ด๋๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํด์๋ ์๋น์ค ๋ฑ๋ก ๋ฐฉ๋ฒ๊ณผ ๊ฐ ์๋น์ค์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. .NET Core์ DI ์ปจํ ์ด๋๋ ์ธ ๊ฐ์ง ์ฃผ์ ์๋น์ค ์๋ช ์ ์ ๊ณตํฉ๋๋ค.
์๋น์ค ์๋ช ์ ํ
- Transient (์ผ์์ )
- Scoped (๋ฒ์)
- Singleton (๋จ์ผ)
1. Transient (์ผ์์ ) ์๋น์ค
Transient ์๋น์ค๋ ์์ฒญ๋ ๋๋ง๋ค ์๋ก์ด ์ธ์คํด์ค๊ฐ ์์ฑ๋ฉ๋๋ค.
services.AddTransient<IMyTransientService, MyTransientService>();
์ฌ์ฉ ์ฌ๋ก: ๊ฐ๋ฒผ์ด ์ํ ๋น์ ์ฅ ์๋น์ค
2. Scoped (๋ฒ์) ์๋น์ค
Scoped ์๋น์ค๋ ์ฃผ์ด์ง ๋ฒ์ ๋ด์์ ํ๋์ ์ธ์คํด์ค๋ง ์์ฑ๋ฉ๋๋ค. ์น ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ์ผ๋ฐ์ ์ผ๋ก ๊ฐ HTTP ์์ฒญ์ด ํ๋์ ๋ฒ์๊ฐ ๋ฉ๋๋ค.
services.AddScoped<IMyScopedService, MyScopedService>();
์ฌ์ฉ ์ฌ๋ก: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ปจํ ์คํธ, ์์ฒญ๋ณ ์บ์ฑ
3. Singleton (๋จ์ผ) ์๋น์ค
Singleton ์๋น์ค๋ ์ ํ๋ฆฌ์ผ์ด์ ์๋ช ๋์ ๋จ ํ๋์ ์ธ์คํด์ค๋ง ์์ฑ๋ฉ๋๋ค.
services.AddSingleton<IMySingletonService, MySingletonService>();
์ฌ์ฉ ์ฌ๋ก: ์ ์ญ ์ํ, ์บ์ฑ, ๋ก๊น ์๋น์ค
์๋น์ค ์๋ช ์ ํ ๊ฐ์ด๋
์๋น์ค ๋ฑ๋ก ๋ฐฉ๋ฒ
์๋น์ค๋ฅผ ๋ฑ๋กํ๋ ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค:
1. ์ธํฐํ์ด์ค์ ๊ตฌํ ํด๋์ค ๋ฑ๋ก
services.AddTransient<IMyService, MyService>();
2. ๊ตฌ์ฒด ํด๋์ค ์ง์ ๋ฑ๋ก
services.AddTransient<MyService>();
3. ํฉํ ๋ฆฌ ํจ์๋ฅผ ์ฌ์ฉํ ๋ฑ๋ก
services.AddTransient<IMyService>(sp => new MyService());
4. ์ด๋ฏธ ์กด์ฌํ๋ ์ธ์คํด์ค ๋ฑ๋ก
var myService = new MyService();
services.AddSingleton<IMyService>(myService);
์ฃผ์์ฌํญ ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก
- ์๋ช ๋ถ์ผ์น ์ฃผ์: Singleton ์๋น์ค์์ Scoped ๋๋ Transient ์๋น์ค๋ฅผ ์ฃผ์ ๋ฐ์ง ์๋๋ก ์ฃผ์ํ์ธ์.
- ์ํ ์์กด์ฑ ํผํ๊ธฐ: A๊ฐ B๋ฅผ ์์กดํ๊ณ B๊ฐ ๋ค์ A๋ฅผ ์์กดํ๋ ์ํ ์์กด์ฑ์ ๋ง๋ค์ง ์๋๋ก ์ฃผ์ํ์ธ์.
- ์ธํฐํ์ด์ค ์ฌ์ฉ: ๊ฐ๋ฅํ ํ ๊ตฌ์ฒด ํด๋์ค ๋์ ์ธํฐํ์ด์ค๋ฅผ ํตํด ์์กด์ฑ์ ์ฃผ์ ๋ฐ์ผ์ธ์.
- ์ ์ ํ ์๋ช ์ ํ: ์๋น์ค์ ํน์ฑ๊ณผ ์ฌ์ฉ ํจํด์ ๊ณ ๋ คํ์ฌ ์ ์ ํ ์๋ช ์ ์ ํํ์ธ์.
- ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉ: ๋ชจ๋ ํด๋์ค๋ฅผ ์๋น์ค๋ก ๋ฑ๋กํ ํ์๋ ์์ต๋๋ค. ์ค์ ๋ก ์์กด์ฑ ์ฃผ์ ์ด ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ์ธ์.
์ค์ ์์ : ๋ ์จ ์ ๋ณด ์๋น์ค
๊ฐ๋จํ ๋ ์จ ์ ๋ณด ์๋น์ค๋ฅผ ๊ตฌํํ์ฌ ๊ฐ ์๋ช ์ ํ์ ์ค์ ๋ก ์ ์ฉํด ๋ณด๊ฒ ์ต๋๋ค.
public interface IWeatherService
{
string GetCurrentWeather();
}
public class WeatherService : IWeatherService
{
private readonly string _weather;
public WeatherService()
{
// ์ค์ ๋ก๋ API ํธ์ถ ๋ฑ์ ํตํด ๋ ์จ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ๊ฒ์
๋๋ค.
_weather = new[] { "Sunny", "Cloudy", "Rainy" }[new Random().Next(3)];
}
public string GetCurrentWeather() => _weather;
}
public class WeatherReporter
{
private readonly IWeatherService _weatherService;
public WeatherReporter(IWeatherService weatherService)
{
_weatherService = weatherService;
}
public void ReportWeather()
{
Console.WriteLine($"Current weather: {_weatherService.GetCurrentWeather()}");
}
}
// ์๋น์ค ๋ฑ๋ก
services.AddTransient<IWeatherService, WeatherService>();
services.AddTransient<WeatherReporter>();
// ์ฌ์ฉ
var reporter1 = serviceProvider.GetService<WeatherReporter>();
var reporter2 = serviceProvider.GetService<WeatherReporter>();
reporter1.ReportWeather();
reporter2.ReportWeather();
์ด ์์ ์์ WeatherService
๋ฅผ Transient๋ก ๋ฑ๋กํ๊ธฐ ๋๋ฌธ์, reporter1
๊ณผ reporter2
๋ ๊ฐ๊ฐ ๋ค๋ฅธ ๋ ์จ ์ ๋ณด๋ฅผ ๋ณด๊ณ ํ ์ ์์ต๋๋ค.
์๋น์ค ๋ฑ๋ก๊ณผ ์๋ช ๊ด๋ฆฌ์ ๋ํ ์ดํด๋ ํจ๊ณผ์ ์ธ ์์กด์ฑ ์ฃผ์ ์์คํ ์ ๊ตฌ์ถํ๋ ๋ฐ ํต์ฌ์ ์ ๋๋ค. ๋ค์ ์น์ ์์๋ ์ด๋ฌํ ๊ฐ๋ ๋ค์ ํ์ฉํ์ฌ ์์กด์ฑ ์ฃผ์ ์ ํตํด ์ฝ์ ์ฑ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๐
5. ์์กด์ฑ ์ฃผ์ ์ ํ์ฉํ ์ฝ์ ์ฑ ๊ตฌ์กฐํ ๐๏ธ
์์กด์ฑ ์ฃผ์ ์ ํ์ฉํ๋ฉด ์ฝ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์กฐ๋ฅผ ๋์ฑ ๋ชจ๋ํํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ์ด ์น์ ์์๋ ์์กด์ฑ ์ฃผ์ ์ ์ฌ์ฉํ์ฌ ์ฝ์ ์ฑ์ ๊ตฌ์กฐํํ๋ ๋ฐฉ๋ฒ๊ณผ ๊ทธ ์ด์ ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
๊ธฐ๋ณธ ๊ตฌ์กฐ ์ค๊ณ
์์กด์ฑ ์ฃผ์ ์ ํ์ฉํ ์ฝ์ ์ฑ์ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ์ง์ ์ (Program.cs)
- ์์กด์ฑ ์ค์ (Startup.cs)
- ์๋น์ค ์ธํฐํ์ด์ค
- ์๋น์ค ๊ตฌํ
- ์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง (AppLogic.cs)
์์ : ๊ฐ๋จํ ํ ์ผ ๊ด๋ฆฌ ์ฝ์ ์ฑ
๊ฐ๋จํ ํ ์ผ ๊ด๋ฆฌ ์ฝ์ ์ฑ์ ๋ง๋ค์ด ์์กด์ฑ ์ฃผ์ ์ ํ์ฉํ ๊ตฌ์กฐํ๋ฅผ ์ค์ตํด ๋ณด๊ฒ ์ต๋๋ค.
1. Program.cs
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
class Program
{
static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.Services.GetRequiredService<AppLogic>().RunAsync();
}
static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
Startup.ConfigureServices(services);
});
}
2. Startup.cs
using Microsoft.Extensions.DependencyInjection;
public static class Startup
{
public static void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITaskRepository, InMemoryTaskRepository>();
services.AddTransient<ITaskService, TaskService>();
services.AddTransient<AppLogic>();
}
}
3. ์๋น์ค ์ธํฐํ์ด์ค
public interface ITaskRepository
{
List<string> GetTasks();
void AddTask(string task);
}
public interface ITaskService
{
List<string> GetAllTasks();
void AddNewTask(string task);
}
4. ์๋น์ค ๊ตฌํ
public class InMemoryTaskRepository : ITaskRepository
{
private readonly List<string> _tasks = new List<string>();
public List<string> GetTasks() => _tasks;
public void AddTask(string task) => _tasks.Add(task);
}
public class TaskService : ITaskService
{
private readonly ITaskRepository _taskRepository;
public TaskService(ITaskRepository taskRepository)
{
_taskRepository = taskRepository;
}
public List<string> GetAllTasks() => _taskRepository.GetTasks();
public void AddNewTask(string task) => _taskRepository.AddTask(task);
}
5. AppLogic.cs
public class AppLogic
{
private readonly ITaskService _taskService;
public AppLogic(ITaskService taskService)
{
_taskService = taskService;
}
public async Task RunAsync()
{
while (true)
{
Console.WriteLine("\n1. View Tasks");
Console.WriteLine("2. Add Task");
Console.WriteLine("3. Exit");
Console.Write("Choose an option: ");
var choice = Console.ReadLine();
switch (choice)
{
case "1":
ViewTasks();
break;
case "2":
await AddTaskAsync();
break;
case "3":
return;
default:
Console.WriteLine("Invalid option. Please try again.");
break;
}
}
}
private void ViewTasks()
{
var tasks = _taskService.GetAllTasks();
if (tasks.Count == 0)
{
Console.WriteLine("No tasks found.");
}
else
{
for (int i = 0; i < tasks.Count; i++)
{
Console.WriteLine($"{i + 1}. {tasks[i]}");
}
}
}
private async Task AddTaskAsync()
{
Console.Write("Enter new task: ");
var task = Console.ReadLine();
if (!string.IsNullOrWhiteSpace(task))
{
_taskService.AddNewTask(task);
Console.WriteLine("Task added successfully.");
}
else
{
Console.WriteLine("Task cannot be empty.");
}
}
}
๊ตฌ์กฐํ์ ์ด์
- ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ: ๊ฐ ์ปดํฌ๋ํธ๊ฐ ํน์ ์ฑ ์์ ๊ฐ์ง๊ณ ์์ด ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ด ํฅ์๋ฉ๋๋ค.
- ํ ์คํธ ์ฉ์ด์ฑ: ์ธํฐํ์ด์ค๋ฅผ ํตํ ์์กด์ฑ ์ฃผ์ ์ผ๋ก ๋จ์ ํ ์คํธ๊ฐ ์ฌ์์ง๋๋ค.
- ์ ์ฐ์ฑ: ๊ตฌํ์ ์ฝ๊ฒ ๊ต์ฒดํ ์ ์์ด ์๊ตฌ์ฌํญ ๋ณ๊ฒฝ์ ๋์ํ๊ธฐ ์ฝ์ต๋๋ค.
- ์ฌ์ฌ์ฉ์ฑ: ์ ์ ์๋ ์ธํฐํ์ด์ค๋ฅผ ํตํด ์ปดํฌ๋ํธ๋ฅผ ๋ค๋ฅธ ํ๋ก์ ํธ์์๋ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ํ์ฅ์ฑ: ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ฑฐ๋ ๊ธฐ์กด ๊ธฐ๋ฅ์ ์์ ํ๊ธฐ ์ฌ์ด ๊ตฌ์กฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
๊ตฌ์กฐํ ์ ๊ณ ๋ ค์ฌํญ
- ๊ณผ๋ํ ์ถ์ํ ์ฃผ์: ๋๋ฌด ๋ง์ ์ถ์ํ๋ ์คํ๋ ค ๋ณต์ก์ฑ์ ์ฆ๊ฐ์ํฌ ์ ์์ต๋๋ค.
- ์ ์ ํ ๊ทธ๋๋ผ๋๋ฆฌํฐ: ์๋น์ค์ ์ฑ ์ ๋ฒ์๋ฅผ ์ ์ ํ ์ค์ ํ์ฌ ๋๋ฌด ์๊ฑฐ๋ ๋๋ฌด ํฌ์ง ์๋๋ก ํฉ๋๋ค.
- ๋ช ํํ ์ธํฐํ์ด์ค ์ค๊ณ: ์ธํฐํ์ด์ค๋ ๊ทธ ๋ชฉ์ ๊ณผ ์ฑ ์์ ๋ช ํํ ๋ฐ์ํด์ผ ํฉ๋๋ค.
- ์ํ ์์กด์ฑ ๋ฐฉ์ง: ์ปดํฌ๋ํธ ๊ฐ์ ์ํ ์์กด์ฑ์ ๋ง๋ค์ง ์๋๋ก ์ฃผ์ํฉ๋๋ค.
์ด๋ ๊ฒ ๊ตฌ์กฐํ๋ ์ฝ์ ์ฑ์ ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ์์ ์ ๊ณตํ๋ ๋ค์ํ ์๋น์ค๋ค์ ์ฝ๊ฒ ํตํฉํ๊ณ ๊ด๋ฆฌํ ์ ์๋ ๊ธฐ๋ฐ์ ์ ๊ณตํฉ๋๋ค. ๋ค์ ์น์ ์์๋ ์ด๋ฌํ ๊ตฌ์กฐ๋ฅผ ๋ฐํ์ผ๋ก ์ค์ ์์ ๋ฅผ ํตํด ๋ ๋ณต์กํ ์๋๋ฆฌ์ค๋ฅผ ๋ค๋ฃจ์ด ๋ณด๊ฒ ์ต๋๋ค. ๐
6. ์ค์ ์์ : ๋ ์จ ์ ๋ณด ์ฝ์ ์ฑ ๋ง๋ค๊ธฐ ๐ค๏ธ
์ด์ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ์์กด์ฑ ์ฃผ์ ๊ฐ๋ ๊ณผ ๊ตฌ์กฐํ ๋ฐฉ๋ฒ์ ํ์ฉํ์ฌ ์ค์ ๋ก ๋์ํ๋ ๋ ์จ ์ ๋ณด ์ฝ์ ์ฑ์ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. ์ด ์ฑ์ ์ฌ์ฉ์๊ฐ ๋์ ์ด๋ฆ์ ์ ๋ ฅํ๋ฉด ํด๋น ๋์์ ํ์ฌ ๋ ์จ ์ ๋ณด๋ฅผ ํ์ํฉ๋๋ค.
ํ๋ก์ ํธ ๊ตฌ์กฐ
WeatherApp/
โโโ Program.cs
โโโ Startup.cs
โโโ AppLogic.cs
โโโ Services/
โ โโโ IWeatherService.cs
โ โโโ OpenWeatherMapService.cs
โโโ Models/
โโโ WeatherInfo.cs
๊ตฌํ ๋จ๊ณ
1. ๋ชจ๋ธ ์ ์ (WeatherInfo.cs)
public class WeatherInfo
{
public string City { get; set; }
public double Temperature { get; set; }
public string Description { get; set; }
}
2. ์๋น์ค ์ธํฐํ์ด์ค ์ ์ (IWeatherService.cs)
public interface IWeatherService
{
Task<WeatherInfo> GetWeatherAsync(string city);
}
3. ์๋น์ค ๊ตฌํ (OpenWeatherMapService.cs)
using System.Net.Http;
using System.Text.Json;
public class OpenWeatherMapService : IWeatherService
{
private readonly HttpClient _httpClient;
private const string ApiKey = "YOUR_API_KEY";
public OpenWeatherMapService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<WeatherInfo> GetWeatherAsync(string city)
{
var response = await _httpClient.GetAsync($"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={ApiKey}&units=metric");
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
var jsonDocument = JsonDocument.Parse(content);
var root = jsonDocument.RootElement;
return new WeatherInfo
{
City = root.GetProperty("name").GetString(),
Temperature = root.GetProperty("main").GetProperty("temp").GetDouble(),
Description = root.GetProperty("weather")[0].GetProperty("description").GetString()
};
}
}
4. ์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง (AppLogic.cs)
public class AppLogic
{
private readonly IWeatherService _weatherService;
public AppLogic(IWeatherService weatherService)
{
_weatherService = weatherService;
}
public async Task RunAsync()
{
while (true)
{
Console.Write("Enter city name (or 'exit' to quit): ");
var city = Console.ReadLine();
if (city?.ToLower() == "exit")
break;
try
{
var weather = await _weatherService.GetWeatherAsync(city);
Console.WriteLine($"Weather in {weather.City}:");
Console.WriteLine($"Temperature: {weather.Temperature}ยฐC");
Console.WriteLine($"Description: {weather.Description}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
Console.WriteLine();
}
}
}
5. ์์กด์ฑ ์ค์ (Startup.cs)
using Microsoft.Extensions.DependencyInjection;
public static class Startup
{
public static void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<IWeatherService, OpenWeatherMapService>();
services.AddTransient<AppLogic>();
}
}
6. ํ๋ก๊ทธ๋จ ์ง์ ์ (Program.cs)
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
class Program
{
static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.Services.GetRequiredService<AppLogic>().RunAsync();
}
static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
Startup.ConfigureServices(services);
});
}
์คํ ๊ฒฐ๊ณผ
Enter city name (or 'exit' to quit): Seoul
Weather in Seoul:
Temperature: 15.5ยฐC
Description: clear sky
Enter city name (or 'exit' to quit): New York
Weather in New York:
Temperature: 22.3ยฐC
Description: partly cloudy
Enter city name (or 'exit' to quit): exit
์ฝ๋ ์ค๋ช
- ์์กด์ฑ ์ฃผ์
:
IWeatherService
๋ฅผAppLogic
์ ์ฃผ์ ํ์ฌ ๋์จํ ๊ฒฐํฉ์ ๊ตฌํํ์ต๋๋ค. - ์๋น์ค ์๋ช
:
HttpClient
๋AddHttpClient
๋ฅผ ํตํด ๊ด๋ฆฌ๋๋ฉฐ,AppLogic
์ Transient๋ก ๋ฑ๋ก๋์์ต๋๋ค. - ๊ด์ฌ์ฌ ๋ถ๋ฆฌ: ๋ ์จ ์ ๋ณด ์กฐํ ๋ก์ง์
OpenWeatherMapService
์ ์บก์ํ๋์ด ์์ต๋๋ค. - ์์ธ ์ฒ๋ฆฌ: ๋คํธ์ํฌ ์ค๋ฅ ๋ฑ์ ์์ธ ์ํฉ์ ์ ์ ํ ์ฒ๋ฆฌํ๊ณ ์์ต๋๋ค.
๊ฐ์ ๊ฐ๋ฅํ ๋ถ๋ถ
- API ํค๋ฅผ ์ค์ ํ์ผ๋ก ๋ถ๋ฆฌ
- ๋ก๊น ๊ธฐ๋ฅ ์ถ๊ฐ
- ์บ์ฑ ๊ตฌํ์ผ๋ก ๋ฐ๋ณต ์์ฒญ ์ต์ ํ
- ์ฌ์ฉ์ ์ ๋ ฅ ์ ํจ์ฑ ๊ฒ์ฌ ๊ฐํ
์ด ์์ ๋ฅผ ํตํด ์ฐ๋ฆฌ๋ ์์กด์ฑ ์ฃผ์ ์ ํ์ฉํ์ฌ ๋ชจ๋ํ๋๊ณ ํ์ฅ ๊ฐ๋ฅํ ์ฝ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌํํ์ต๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ๋ ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ์์ ์ ๊ณตํ๋ ๋ค์ํ API๋ ์๋น์ค๋ฅผ ์ฝ๊ฒ ํตํฉํ ์ ์๋ ๊ธฐ๋ฐ์ ์ ๊ณตํฉ๋๋ค. ๋ค์ ์น์ ์์๋ ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ํ ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๐งช
7. ํ ์คํธ์ ์์กด์ฑ ์ฃผ์ ๐งช
์์กด์ฑ ์ฃผ์ ์ ์ฃผ์ ์ด์ ์ค ํ๋๋ ๋จ์ ํ ์คํธ๋ฅผ ์ฝ๊ฒ ์์ฑํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ด๋ฒ ์น์ ์์๋ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ๋ ์จ ์ ๋ณด ์ฝ์ ์ฑ์ ์ผ๋ถ ์ปดํฌ๋ํธ์ ๋ํ ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
ํ ์คํธ ํ๋ก์ ํธ ์ค์
๋จผ์ , ์๋ก์ด xUnit ํ ์คํธ ํ๋ก์ ํธ๋ฅผ ์์ฑํฉ๋๋ค:
dotnet new xunit -n WeatherApp.Tests
๊ทธ๋ฆฌ๊ณ ํ์ํ NuGet ํจํค์ง๋ฅผ ์ถ๊ฐํฉ๋๋ค:
dotnet add package Moq
dotnet add package Microsoft.Extensions.DependencyInjection
AppLogic ํ ์คํธ
AppLogic
ํด๋์ค์ ๋์์ ํ
์คํธํ๊ธฐ ์ํด IWeatherService
์ ๋ชจ์ ๊ฐ์ฒด(mock)๋ฅผ ์ฌ์ฉํฉ๋๋ค.
using Moq;
using Xunit;
using System.Threading.Tasks;
public class AppLogicTests
{
[Fact]
public async Task RunAsync_ShouldReturnCorrectWeatherInfo()
{
// Arrange
var mockWeatherService = new Mock<IWeatherService>();
mockWeatherService.Setup(service => service.GetWeatherAsync("Seoul"))
.ReturnsAsync(new WeatherInfo
{
City = "Seoul",
Temperature = 25.5,
Description = "Sunny"
});
var appLogic = new AppLogic(mockWeatherService.Object);
// Act & Assert
using (var consoleOutput = new ConsoleOutput())
{
await appLogic.RunAsync();
Assert.Contains("Weather in Seoul:", consoleOutput.GetOutput());
Assert.Contains("Temperature: 25.5ยฐC", consoleOutput.GetOutput());
Assert.Contains("Description: Sunny", consoleOutput.GetOutput());
}
}
}
// ์ฝ์ ์ถ๋ ฅ์ ์บก์ฒํ๊ธฐ ์ํ ํฌํผ ํด๋์ค
public class ConsoleOutput : IDisposable
{
private readonly StringWriter stringWriter;
private readonly TextWriter originalOutput;
public ConsoleOutput()
{
stringWriter = new StringWriter();
originalOutput = Console.Out;
Console.SetOut(stringWriter);
}
public string GetOutput()
{
return stringWriter.ToString();
}
public void Dispose()
{
Console.SetOut(originalOutput);
stringWriter.Dispose();
}
}
OpenWeatherMapService ํ ์คํธ
OpenWeatherMapService
๋ฅผ ํ
์คํธํ๊ธฐ ์ํด HttpClient
์ ๋์์ ๋ชจ์ํํฉ๋๋ค.
using Moq; using Moq;
using Xunit;
using System.Net.Http;
using System.Threading.Tasks;
using System.Threading;
using Moq.Protected;
public class OpenWeatherMapServiceTests
{
[Fact]
public async Task GetWeatherAsync_ShouldReturnCorrectWeatherInfo()
{
// Arrange
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
.ReturnsAsync(new HttpResponseMessage
{
Content = new StringContent(@"{
""name"": ""Seoul"",
""main"": { ""temp"": 25.5 },
""weather"": [{ ""description"": ""clear sky"" }]
}")
});
var client = new HttpClient(mockHttpMessageHandler.Object);
var weatherService = new OpenWeatherMapService(client);
// Act
var result = await weatherService.GetWeatherAsync("Seoul");
// Assert
Assert.Equal("Seoul", result.City);
Assert.Equal(25.5, result.Temperature);
Assert.Equal("clear sky", result.Description);
}
}
์์กด์ฑ ์ฃผ์ ์ปจํ ์ด๋ ํ ์คํธ
์์กด์ฑ ์ฃผ์ ์ค์ ์ด ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ฑ๋์๋์ง ํ์ธํ๋ ํ ์คํธ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
using Microsoft.Extensions.DependencyInjection;
using Xunit;
public class StartupTests
{
[Fact]
public void ConfigureServices_ShouldRegisterAllDependencies()
{
// Arrange
var services = new ServiceCollection();
// Act
Startup.ConfigureServices(services);
// Assert
var serviceProvider = services.BuildServiceProvider();
Assert.NotNull(serviceProvider.GetService<IWeatherService>());
Assert.NotNull(serviceProvider.GetService<AppLogic>());
}
}
ํ ์คํธ ์คํ
ํ ์คํธ๋ฅผ ์คํํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ ์ฌ์ฉํฉ๋๋ค:
dotnet test
ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง ํฅ์
๋ ๋์ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ์ํด ๋ค์๊ณผ ๊ฐ์ ์ถ๊ฐ ํ ์คํธ ์ผ์ด์ค๋ฅผ ๊ณ ๋ คํ ์ ์์ต๋๋ค:
- ์๋ชป๋ ๋์ ์ด๋ฆ์ผ๋ก ๋ ์จ ์ ๋ณด๋ฅผ ์์ฒญํ ๋์ ์์ธ ์ฒ๋ฆฌ
- ๋คํธ์ํฌ ์ค๋ฅ ์๋๋ฆฌ์ค
- API ์๋ต ํ์์ด ์์๊ณผ ๋ค๋ฅผ ๋์ ์ฒ๋ฆฌ
- ์ฌ๋ฌ ๋์์ ๋ํ ์ฐ์์ ์ธ ๋ ์จ ์ ๋ณด ์์ฒญ
๋ชจ๋ฒ ์ฌ๋ก
- ๋จ์ ํ ์คํธ ๊ฒฉ๋ฆฌ: ๊ฐ ํ ์คํธ๋ ๋ ๋ฆฝ์ ์ด์ด์ผ ํ๋ฉฐ, ๋ค๋ฅธ ํ ์คํธ์ ๊ฒฐ๊ณผ์ ์ํฅ์ ๋ฐ์ง ์์์ผ ํฉ๋๋ค.
- ์์กด์ฑ ๋ชจ์ํ: ์ธ๋ถ ์๋น์ค๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐ์ ์ธ๋ถ ์์กด์ฑ์ ํญ์ ๋ชจ์ ๊ฐ์ฒด๋ก ๋์ฒดํฉ๋๋ค.
- ํ ์คํธ ๊ฐ๋ ์ฑ: ๊ฐ ํ ์คํธ์ ๋ชฉ์ ์ด ๋ช ํํ ๋๋ฌ๋๋๋ก ์์ฑํฉ๋๋ค. Arrange-Act-Assert ํจํด์ ๋ฐ๋ฅด๋ ๊ฒ์ด ์ข์ต๋๋ค.
- ๊ฒฝ๊ณ ์กฐ๊ฑด ํ ์คํธ: ์ ์์ ์ธ ์ผ์ด์ค๋ฟ๋ง ์๋๋ผ ์์ธ์ ์ธ ์ํฉ๋ ํ ์คํธํฉ๋๋ค.
- ํ ์คํธ ๋ฐ์ดํฐ ๊ด๋ฆฌ: ํ ์คํธ ๋ฐ์ดํฐ๋ ํ๋์ฝ๋ฉ๋ณด๋ค๋ ๋ณ๋์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ ํ ์คํธ ๋ฐ์ดํฐ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ๊ด๋ฆฌํฉ๋๋ค.
๊ฒฐ๋ก
์์กด์ฑ ์ฃผ์ ์ ํ์ฉํ ์ค๊ณ๋ ๋จ์ ํ ์คํธ ์์ฑ์ ํฌ๊ฒ ์ฉ์ดํ๊ฒ ํฉ๋๋ค. ์ด๋ ์ฝ๋์ ํ์ง์ ํฅ์์ํค๊ณ , ๋ฆฌํฉํ ๋ง์ด๋ ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ ์ ๋ฐ์ํ ์ ์๋ ํ๊ท ์ค๋ฅ๋ฅผ ๋น ๋ฅด๊ฒ ๋ฐ๊ฒฌํ ์ ์๊ฒ ํด์ค๋๋ค. ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ์์ ์ ๊ณตํ๋ ๋ค์ํ ์๋น์ค๋ค์ ํตํฉํ ๋, ์ด๋ฌํ ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ ๋ฐฉ์์ ์์ ์ ์ด๊ณ ์ ์ง๋ณด์๊ฐ ์ฉ์ดํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋๋ ๋ฐ ํฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
๋ค์ ์น์ ์์๋ ์์กด์ฑ ์ฃผ์ ๊ณผ ๊ด๋ จ๋ ๊ณ ๊ธ ์ฃผ์ ์ธ ์ปค์คํ DI ์ปจํ ์ด๋ ๋ง๋ค๊ธฐ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฅผ ํตํด ์์กด์ฑ ์ฃผ์ ์ ๋ด๋ถ ๋์ ์๋ฆฌ๋ฅผ ๋ ๊น์ด ์ดํดํ ์ ์์ ๊ฒ์ ๋๋ค. ๐
8. ๊ณ ๊ธ ์ฃผ์ : ์ปค์คํ DI ์ปจํ ์ด๋ ๋ง๋ค๊ธฐ ๐ ๏ธ
์ด๋ฒ ์น์ ์์๋ ๊ฐ๋จํ ์ปค์คํ DI(์์กด์ฑ ์ฃผ์ ) ์ปจํ ์ด๋๋ฅผ ์ง์ ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค. ์ด ๊ณผ์ ์ ํตํด DI ์ปจํ ์ด๋์ ๋ด๋ถ ๋์ ์๋ฆฌ๋ฅผ ๋ ๊น์ด ์ดํดํ ์ ์์ ๊ฒ์ ๋๋ค.
๊ธฐ๋ณธ ๊ตฌ์กฐ
์ฐ๋ฆฌ์ ์ปค์คํ DI ์ปจํ ์ด๋๋ ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํ ๊ฒ์ ๋๋ค:
- ์๋น์ค ๋ฑ๋ก
- ์๋น์ค ํด๊ฒฐ (์์กด์ฑ ์ฃผ์ )
- ์๋ช ๊ด๋ฆฌ (Transient, Singleton)
๊ตฌํ
using System;
using System.Collections.Generic;
public class CustomContainer
{
private Dictionary<Type, ServiceDescriptor> _services = new Dictionary<Type, ServiceDescriptor>();
public void Register<TService, TImplementation>(ServiceLifetime lifetime = ServiceLifetime.Transient)
where TImplementation : TService
{
_services[typeof(TService)] = new ServiceDescriptor(typeof(TImplementation), lifetime);
}
public TService Resolve<TService>()
{
return (TService)ResolveService(typeof(TService));
}
private object ResolveService(Type serviceType)
{
if (!_services.ContainsKey(serviceType))
{
throw new Exception($"Service of type {serviceType.Name} is not registered");
}
var descriptor = _services[serviceType];
if (descriptor.Instance != null)
{
return descriptor.Instance;
}
var actualType = descriptor.ImplementationType;
var constructor = actualType.GetConstructors()[0];
var parameters = constructor.GetParameters();
var parameterInstances = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
parameterInstances[i] = ResolveService(parameters[i].ParameterType);
}
var implementation = Activator.CreateInstance(actualType, parameterInstances);
if (descriptor.Lifetime == ServiceLifetime.Singleton)
{
descriptor.Instance = implementation;
}
return implementation;
}
}
public class ServiceDescriptor
{
public Type ServiceType { get; }
public Type ImplementationType { get; }
public object Instance { get; set; }
public ServiceLifetime Lifetime { get; }
public ServiceDescriptor(Type implementationType, ServiceLifetime lifetime)
{
ImplementationType = implementationType;
Lifetime = lifetime;
}
}
public enum ServiceLifetime
{
Transient,
Singleton
}
์ฌ์ฉ ์์
// ์๋น์ค ์ ์
public interface IMessageService
{
string GetMessage();
}
public class EmailService : IMessageService
{
public string GetMessage() => "This is an email message.";
}
public class SmsService : IMessageService
{
public string GetMessage() => "This is an SMS message.";
}
public class NotificationService
{
private readonly IMessageService _messageService;
public NotificationService(IMessageService messageService)
{
_messageService = messageService;
}
public void SendNotification()
{
Console.WriteLine($"Sending notification: {_messageService.GetMessage()}");
}
}
// ์ปจํ
์ด๋ ์ฌ์ฉ
var container = new CustomContainer();
container.Register<IMessageService, EmailService>(ServiceLifetime.Singleton);
container.Register<NotificationService, NotificationService>();
var notificationService = container.Resolve<NotificationService>();
notificationService.SendNotification();
// ์๋น์ค ๋ณ๊ฒฝ
container.Register<IMessageService, SmsService>(ServiceLifetime.Singleton);
notificationService = container.Resolve<NotificationService>();
notificationService.SendNotification();
์ฝ๋ ์ค๋ช
- Register ๋ฉ์๋: ์๋น์ค์ ๊ทธ ๊ตฌํ์ ์ปจํ ์ด๋์ ๋ฑ๋กํฉ๋๋ค. ์๋น์ค์ ์๋ช ๋ ์ง์ ํ ์ ์์ต๋๋ค.
- Resolve ๋ฉ์๋: ์์ฒญ๋ ์๋น์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ๋ฐํํฉ๋๋ค. ์ด ๊ณผ์ ์์ ์ฌ๊ท์ ์ผ๋ก ์์กด์ฑ์ ํด๊ฒฐํฉ๋๋ค.
- ServiceDescriptor: ์๋น์ค์ ๊ตฌํ ํ์ , ์๋ช , ๊ทธ๋ฆฌ๊ณ ์ฑ๊ธํค ์ธ์คํด์ค๋ฅผ ์ ์ฅํฉ๋๋ค.
- ServiceLifetime: ์๋น์ค์ ์๋ช ์ ์ ์ํ๋ ์ด๊ฑฐํ์ ๋๋ค. ์ฌ๊ธฐ์๋ Transient์ Singleton๋ง ๊ตฌํํ์ต๋๋ค.
ํ๊ณ์
์ด ๊ฐ๋จํ ๊ตฌํ์๋ ๋ช ๊ฐ์ง ํ๊ณ๊ฐ ์์ต๋๋ค:
- ์ํ ์์กด์ฑ ๊ฐ์ง ๊ธฐ๋ฅ์ด ์์ต๋๋ค.
- Scoped ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ง์ํ์ง ์์ต๋๋ค.
- ์์ฑ์ ์ฃผ์ ๋ง ์ง์ํ๋ฉฐ, ์์ฑ ์ฃผ์ ์ด๋ ๋ฉ์๋ ์ฃผ์ ์ ์ง์ํ์ง ์์ต๋๋ค.
- ์ ๋ค๋ฆญ ํ์ ์ ๋ํ ํน๋ณํ ์ฒ๋ฆฌ๊ฐ ์์ต๋๋ค.
- ์ฑ๋ฅ ์ต์ ํ๊ฐ ๋์ด ์์ง ์์ต๋๋ค.
๊ฐ์ ๋ฐฉํฅ
์ค์ ํ๋ก๋์ ํ๊ฒฝ์์ ์ฌ์ฉํ DI ์ปจํ ์ด๋๋ฅผ ๋ง๋ค๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ๋ค์ ์ถ๊ฐ๋ก ๊ตฌํํด์ผ ํฉ๋๋ค:
- ์ํ ์์กด์ฑ ๊ฐ์ง ๋ฐ ์์ธ ์ฒ๋ฆฌ
- Scoped ์๋ช ์ฃผ๊ธฐ ์ง์
- ๋ค์ํ ์ฃผ์ ๋ฐฉ์ ์ง์ (์์ฑ ์ฃผ์ , ๋ฉ์๋ ์ฃผ์ )
- ์ ๋ค๋ฆญ ํ์ ์ง์
- ์ฑ๋ฅ ์ต์ ํ (์: ๋ฆฌํ๋ ์ ๊ฒฐ๊ณผ ์บ์ฑ)
- ์ค๋ ๋ ์์ ์ฑ ๋ณด์ฅ
- ๋ค์ํ ๋ฑ๋ก ๋ฐฉ์ ์ง์ (์: ํฉํ ๋ฆฌ ํจ์๋ฅผ ํตํ ๋ฑ๋ก)
๊ฒฐ๋ก
์ด ๊ฐ๋จํ ์ปค์คํ DI ์ปจํ ์ด๋ ๊ตฌํ์ ํตํด ์์กด์ฑ ์ฃผ์ ์ ํต์ฌ ์๋ฆฌ๋ฅผ ์ดํดํ ์ ์์์ต๋๋ค. ์ค์ .NET Core์ DI ์ปจํ ์ด๋๋ ์ด๋ณด๋ค ํจ์ฌ ๋ณต์กํ๊ณ ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง๋ง, ๊ธฐ๋ณธ์ ์ธ ์๋ ์๋ฆฌ๋ ์ ์ฌํฉ๋๋ค.
์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ์์ ์ ๊ณตํ๋ ๋ค์ํ ์๋น์ค๋ค์ ํตํฉํ ๋, ์ด๋ฌํ DI ์ปจํ ์ด๋์ ๋ด๋ถ ๋์ ์๋ฆฌ๋ฅผ ์ดํดํ๋ ๊ฒ์ ๋งค์ฐ ์ ์ฉํ ๊ฒ์ ๋๋ค. ์ด๋ฅผ ํตํด ์์กด์ฑ ์ฃผ์ ์ ๋ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํ๊ณ , ํ์ํ ๊ฒฝ์ฐ ์ปค์คํ ์๋ฃจ์ ์ ๊ฐ๋ฐํ ์ ์๋ ๊ธฐ๋ฐ์ ๊ฐ์ถ๊ฒ ๋ฉ๋๋ค.
๋ค์ ์น์ ์์๋ ์์กด์ฑ ์ฃผ์ ์ ์ฌ์ฉํ ๋์ ์ฑ๋ฅ ์ต์ ํ ํ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฅผ ํตํด ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ํจ์จ์ ์ผ๋ก DI๋ฅผ ํ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ๊ฒ ๋ ๊ฒ์ ๋๋ค. ๐
9. ์ฑ๋ฅ ์ต์ ํ ํ ๐
์์กด์ฑ ์ฃผ์ ์ ์ฝ๋์ ์ ์ฐ์ฑ๊ณผ ํ ์คํธ ์ฉ์ด์ฑ์ ํฌ๊ฒ ํฅ์์ํค์ง๋ง, ์๋ชป ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ ์ ํ๋ฅผ ์ด๋ํ ์ ์์ต๋๋ค. ์ด ์น์ ์์๋ .NET Core์ DI ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ ๋ ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
1. ์ ์ ํ ์๋ช ์ฃผ๊ธฐ ์ ํ
์๋น์ค์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ ์ ํ ์ ํํ๋ ๊ฒ์ ์ฑ๋ฅ์ ํฐ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
- Transient: ๋งค๋ฒ ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ฏ๋ก, ์ํ๋ฅผ ์ ์งํ์ง ์๋ ๊ฐ๋ฒผ์ด ์๋น์ค์ ์ ํฉํฉ๋๋ค.
- Scoped: ์์ฒญ ๋ฒ์ ๋ด์์ ์ฌ์ฌ์ฉ๋๋ฏ๋ก, ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฒญ๋ณ ์๋น์ค์ ์ ํฉํฉ๋๋ค.
- Singleton: ์ ํ๋ฆฌ์ผ์ด์ ์๋ช ๋์ ํ๋์ ์ธ์คํด์ค๋ง ์ฌ์ฉํ๋ฏ๋ก, ์ํ๋ฅผ ๊ณต์ ํ๋ ์๋น์ค์ ์ ํฉํฉ๋๋ค.
// ์์
services.AddTransient<ILightweightService, LightweightService>();
services.AddScoped<IRequestScopedService, RequestScopedService>();
services.AddSingleton<ISharedStateService, SharedStateService>();
2. ์์ฑ ๋น์ฉ์ด ๋์ ๊ฐ์ฒด๋ Singleton์ผ๋ก ๋ฑ๋ก
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ, HTTP ํด๋ผ์ด์ธํธ ๋ฑ ์์ฑ ๋น์ฉ์ด ๋์ ๊ฐ์ฒด๋ Singleton์ผ๋ก ๋ฑ๋กํ์ฌ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
services.AddSingleton<HttpClient>();
services.AddSingleton<IExpensiveService, ExpensiveService>();
3. ํฉํ ๋ฆฌ ํจํด ํ์ฉ
๋ณต์กํ ๊ฐ์ฒด ์์ฑ ๋ก์ง์ด ํ์ํ ๊ฒฝ์ฐ, ํฉํ ๋ฆฌ ํจํด์ ์ฌ์ฉํ์ฌ ์ฑ๋ฅ์ ๊ฐ์ ํ ์ ์์ต๋๋ค.
services.AddSingleton<IServiceFactory>(sp =>
{
return new ServiceFactory(sp);
});
services.AddTransient<IMyService>(sp =>
{
var factory = sp.GetRequiredService<IServiceFactory>();
return factory.CreateMyService();
});
4. ๋ ์ด์ง ๋ก๋ฉ ๊ตฌํ
์ผ๋ถ ์๋น์ค๋ ์ค์ ๋ก ์ฌ์ฉ๋ ๋๋ง ์ด๊ธฐํํ๋ ๊ฒ์ด ์ ๋ฆฌํ ์ ์์ต๋๋ค. ์ด๋ฅผ ์ํด Lazy<T>๋ฅผ ํ์ฉํ ์ ์์ต๋๋ค.
services.AddTransient<Lazy<IExpensiveService>>(sp =>
{
return new Lazy<IExpensiveService>(() => sp.GetRequiredService<IExpensiveService>());
});
5. ๊ฐ์ฒด ํ๋ง ์ฌ์ฉ
์์ฃผ ์์ฑ๋๊ณ ํ๊ดด๋๋ ๊ฐ์ฒด์ ๊ฒฝ์ฐ, ๊ฐ์ฒด ํ๋ง์ ์ฌ์ฉํ์ฌ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
services.AddSingleton<ObjectPool<MyExpensiveObject>>(sp =>
{
return new DefaultObjectPool<MyExpensiveObject>(new DefaultPooledObjectPolicy<MyExpensiveObject>());
});
6. ์ปจํ ์ด๋ ๋น๋ ์ต์ ํ
์ ํ๋ฆฌ์ผ์ด์ ์์ ์ DI ์ปจํ ์ด๋๋ฅผ ๋น๋ํ๋ ๊ณผ์ ์ ์ต์ ํํ ์ ์์ต๋๋ค.
var services = new ServiceCollection();
// ์๋น์ค ๋ฑ๋ก...
var serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions
{
ValidateScopes = false,
ValidateOnBuild = false
});
๋จ, ์ด ์ต์ ๋ค์ ๊ฐ๋ฐ ํ๊ฒฝ์์๋ ํ์ฑํํ์ฌ ์ ์ฌ์ ์ธ ๋ฌธ์ ๋ฅผ ์กฐ๊ธฐ์ ๋ฐ๊ฒฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
7. ๋ถํ์ํ ์์กด์ฑ ์ ๊ฑฐ
๊ฐ ํด๋์ค๊ฐ ์ ๋ง๋ก ํ์ํ ์์กด์ฑ๋ง ์ฃผ์ ๋ฐ๋๋ก ์ค๊ณํ์ธ์. ๋ถํ์ํ ์์กด์ฑ์ ์ฑ๋ฅ ์ ํ์ ์์ธ์ด ๋ ์ ์์ต๋๋ค.
8. ํ๋กํ์ผ๋ง ๋ฐ ๋ฒค์น๋งํน
์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํด์๋ ์ค์ ์ธก์ ์ด ํ์ํฉ๋๋ค. .NET์ ํ๋กํ์ผ๋ง ๋๊ตฌ์ BenchmarkDotNet ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ์ธ์.
[Benchmark]
public void ResolveService()
{
var service = _serviceProvider.GetService<IMyService>();
service.DoSomething();
}
9. ์ปดํ์ผ ์์ DI ๊ณ ๋ ค
๊ทน๋จ์ ์ธ ์ฑ๋ฅ์ด ํ์ํ ๊ฒฝ์ฐ, ๋ฐํ์ DI ๋์ ์ปดํ์ผ ์์ DI๋ฅผ ๊ณ ๋ คํด๋ณผ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, Source Generators๋ฅผ ์ฌ์ฉํ DI ๊ตฌํ์ด ์์ต๋๋ค.
์ฑ๋ฅ ์ต์ ํ ์์
๋ค์์ ์์์ ์ธ๊ธํ ๋ช ๊ฐ์ง ์ต์ ํ ๊ธฐ๋ฒ์ ์ ์ฉํ ์์ ์ ๋๋ค:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// ์ฑ๊ธํค์ผ๋ก ๋ฑ๋กํ์ฌ ์ฌ์ฌ์ฉ
services.AddSingleton<HttpClient>();
// ํฉํ ๋ฆฌ ํจํด ํ์ฉ
services.AddSingleton<IServiceFactory, ServiceFactory>();
services.AddTransient<IMyService>(sp => sp.GetRequiredService<IServiceFactory>().CreateMyService());
// ๋ ์ด์ง ๋ก๋ฉ ๊ตฌํ
services.AddTransient<Lazy<IExpensiveService>>(sp =>
new Lazy<IExpensiveService>(() => sp.GetRequiredService<IExpensiveService>()));
// ๊ฐ์ฒด ํ๋ง ์ฌ์ฉ
services.AddSingleton<ObjectPool<MyExpensiveObject>>(sp =>
new DefaultObjectPool<MyExpensiveObject>(new DefaultPooledObjectPolicy<MyExpensiveObject>()));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ์ ํ๋ฆฌ์ผ์ด์
๊ตฌ์ฑ...
}
}
public class ServiceFactory : IServiceFactory
{
private readonly IServiceProvider _serviceProvider;
public ServiceFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IMyService CreateMyService()
{
// ๋ณต์กํ ์์ฑ ๋ก์ง...
return new MyService(_serviceProvider.GetRequiredService<IDependency>());
}
}
public class MyController : ControllerBase
{
private readonly Lazy<IExpensiveService> _lazyExpensiveService;
private readonly ObjectPool<MyExpensiveObject> _objectPool;
public MyController(Lazy<IExpensiveService> lazyExpensiveService, ObjectPool<MyExpensiveObject> objectPool)
{
_lazyExpensiveService = lazyExpensiveService;
_objectPool = objectPool;
}
public IActionResult DoSomething()
{
// ํ์ํ ๋๋ง ์ด๊ธฐํ
var expensiveService = _lazyExpensiveService.Value;
// ๊ฐ์ฒด ํ์์ ๊ฐ์ฒด ๊ฐ์ ธ์ค๊ธฐ
var expensiveObject = _objectPool.Get();
try
{
// ์์
์ํ...
return Ok();
}
finally
{
// ๊ฐ์ฒด๋ฅผ ํ๋ก ๋ฐํ
_objectPool.Return(expensiveObject);
}
}
}
๊ฒฐ๋ก
์์กด์ฑ ์ฃผ์ ์ ๊ฐ๋ ฅํ ๋๊ตฌ์ด์ง๋ง, ์ฑ๋ฅ์ ๋ฏธ์น๋ ์ํฅ์ ํญ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ์์ ์ต์ ํ ๊ธฐ๋ฒ๋ค์ ์ ์ ํ ํ์ฉํ๋ฉด, ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ์์ ์ ๊ณตํ๋ ๋ค์ํ ์๋น์ค๋ค์ ํจ์จ์ ์ผ๋ก ํตํฉํ๋ฉด์๋ ๋์ ์ฑ๋ฅ์ ์ ์งํ ์ ์์ต๋๋ค. ๋ค์ ์น์ ์์๋ ์์กด์ฑ ์ฃผ์ ์ ๋ชจ๋ฒ ์ฌ๋ก์ ์ํฐ ํจํด์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฅผ ํตํด ๋ ๊ฒฌ๊ณ ํ๊ณ ์ ์ง๋ณด์๊ฐ ์ฉ์ดํ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ๊ฒ ๋ ๊ฒ์ ๋๋ค. ๐ก
10. ์์กด์ฑ ์ฃผ์ ์ ๋ชจ๋ฒ ์ฌ๋ก์ ์ํฐ ํจํด ๐ญ
์์กด์ฑ ์ฃผ์ ์ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํด์๋ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๊ณ ์ํฐ ํจํด์ ํผํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ด ์น์ ์์๋ .NET Core ํ๊ฒฝ์์์ DI ๋ชจ๋ฒ ์ฌ๋ก์ ํผํด์ผ ํ ์ํฐ ํจํด์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
๋ชจ๋ฒ ์ฌ๋ก (Best Practices)
- ์์ฑ์ ์ฃผ์
์ฌ์ฉ
public class MyService { private readonly IDependency _dependency; public MyService(IDependency dependency) { _dependency = dependency ?? throw new ArgumentNullException(nameof(dependency)); } }
- ์ธํฐํ์ด์ค์ ์์กด
services.AddTransient<IMyService, MyService>();
- ์ ์ ํ ์๋ช
์ฃผ๊ธฐ ์ ํ
services.AddTransient<IShortLivedService, ShortLivedService>(); services.AddScoped<IRequestScopedService, RequestScopedService>(); services.AddSingleton<ILongLivedService, LongLivedService>();
- ์์กด์ฑ ์ต์ํ
public class GoodService { public GoodService(IDependency1 dep1, IDependency2 dep2) { // ํ์ํ ์์กด์ฑ๋ง ์ฃผ์ } }
- ์ค์ ์ฃผ์
services.Configure<MyOptions>(Configuration.GetSection("MyOptions")); services.AddTransient<IMyService, MyService>(); public class MyService { public MyService(IOptions<MyOptions> options) { // ์ค์ ์ฌ์ฉ } }
- ํฉํ ๋ฆฌ ํจํด ํ์ฉ
services.AddTransient<IMyService>(sp => { var dependency = sp.GetRequiredService<IDependency>(); return new MyService(dependency); });
- ์ปดํฌ์ง์
๋ฃจํธ์์๋ง ํด๊ฒฐ
public class Program { public static void Main(string[] args) { var host = CreateHostBuilder(args).Build(); var myService = host.Services.GetRequiredService<IMyService>(); // ์ฌ๊ธฐ์๋ง ์๋น์ค๋ฅผ ์ง์ ํด๊ฒฐ } }
์ํฐ ํจํด (Anti-Patterns)
- ์๋น์ค ๋ก์ผ์ดํฐ ํจํด
// ์ํฐ ํจํด public class BadService { private readonly IServiceProvider _serviceProvider; public BadService(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public void DoSomething() { var dependency = _serviceProvider.GetService<IDependency>(); // ์ด๋ ์์กด์ฑ์ ์จ๊ธฐ๊ณ ํ ์คํธ๋ฅผ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค. } }
- ์ํ ์์กด์ฑ
// ์ํฐ ํจํด public class ServiceA { public ServiceA(ServiceB b) { } } public class ServiceB { public ServiceB(ServiceA a) { } }
- ๊ณผ๋ํ ์ถ์ํ
// ์ํฐ ํจํด services.AddTransient<IServiceA, ServiceA>(); services.AddTransient<IServiceB, ServiceB>(); services.AddTransient<IServiceC, Service C>(); services.AddTransient<IServiceD, ServiceD>(); // ๋ชจ๋ ๊ฒ์ ์ถ์ํํ๋ ๊ฒ์ ๊ณผ๋ํ ์ ์์ต๋๋ค.
- ์ปจํ
์ด๋์ ๋ํ ๊ณผ๋ํ ์์กด
// ์ํฐ ํจํด public class OverlyDependentService { private readonly IServiceProvider _serviceProvider; public OverlyDependentService(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public void DoSomething() { var service1 = _serviceProvider.GetService<IService1>(); var service2 = _serviceProvider.GetService<IService2>(); var service3 = _serviceProvider.GetService<IService3>(); // ์ด๋ ์์กด์ฑ์ ์จ๊ธฐ๊ณ ํ ์คํธ๋ฅผ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค. } }
- ๋ถ์ ์ ํ ์๋ช
์ฃผ๊ธฐ ์ฌ์ฉ
// ์ํฐ ํจํด services.AddSingleton<IDataContext, DataContext>(); // ๋ฐ์ดํฐ ์ปจํ ์คํธ๋ฅผ ์ฑ๊ธํค์ผ๋ก ๋ฑ๋กํ๋ฉด ๋ฉํฐ ์ค๋ ๋ ํ๊ฒฝ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
- ์ ์ ํด๋์ค ๋ฐ ์ฑ๊ธํค ํจํด ๊ณผ๋ค ์ฌ์ฉ
// ์ํฐ ํจํด public static class StaticHelper { public static void DoSomething() { } } // ๋์ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๊ณ DI๋ฅผ ํตํด ์ฃผ์ ๋ฐ์ผ์ธ์. public interface IHelper { void DoSomething(); } services.AddTransient<IHelper, Helper>();
- ์๋น์ค ํด๊ฒฐ์ ์ํ `new` ํค์๋ ์ฌ์ฉ
// ์ํฐ ํจํด public class BadService { public void DoSomething() { var dependency = new Dependency(); // ์ด๋ DI์ ์ด์ ์ ๋ฌด์ํ๊ณ ๊ฐํ ๊ฒฐํฉ์ ๋ง๋ญ๋๋ค. } }
๋ชจ๋ฒ ์ฌ๋ก ์ ์ฉ ์์
๋ค์์ ์์์ ์ธ๊ธํ ๋ชจ๋ฒ ์ฌ๋ก๋ค์ ์ ์ฉํ ์์ ์ ๋๋ค:
public interface IUserService
{
Task<User> GetUserAsync(int id);
}
public interface IEmailService
{
Task SendEmailAsync(string to, string subject, string body);
}
public class UserService : IUserService
{
private readonly IDbContext _dbContext;
public UserService(IDbContext dbContext)
{
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
}
public async Task<User> GetUserAsync(int id)
{
return await _dbContext.Users.FindAsync(id);
}
}
public class EmailService : IEmailService
{
private readonly IOptions<EmailSettings> _emailSettings;
private readonly ILogger<EmailService> _logger;
public EmailService(IOptions<EmailSettings> emailSettings, ILogger<EmailService> logger)
{
_emailSettings = emailSettings ?? throw new ArgumentNullException(nameof(emailSettings));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task SendEmailAsync(string to, string subject, string body)
{
// ์ด๋ฉ์ผ ์ ์ก ๋ก์ง
_logger.LogInformation($"Sending email to {to}");
// ์ค์ ์ด๋ฉ์ผ ์ ์ก ์ฝ๋...
}
}
public class UserController : ControllerBase
{
private readonly IUserService _userService;
private readonly IEmailService _emailService;
public UserController(IUserService userService, IEmailService emailService)
{
_userService = userService ?? throw new ArgumentNullException(nameof(userService));
_emailService = emailService ?? throw new ArgumentNullException(nameof(emailService));
}
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(int id)
{
var user = await _userService.GetUserAsync(id);
if (user == null)
{
return NotFound();
}
await _emailService.SendEmailAsync(user.Email, "User Retrieved", "Your user information was accessed.");
return Ok(user);
}
}
// Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<IDbContext, AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<IUserService, UserService>();
services.AddSingleton<IEmailService, EmailService>();
services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
services.AddControllers();
}
}
๊ฒฐ๋ก
์์กด์ฑ ์ฃผ์ ์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๊ณ ์ํฐ ํจํด์ ํผํจ์ผ๋ก์จ, ๋ ์ ์ง๋ณด์๊ฐ ์ฉ์ดํ๊ณ ํ ์คํธํ๊ธฐ ์ฌ์ด ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์ด๋ ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ์์ ์ ๊ณตํ๋ ๋ค์ํ ์๋น์ค๋ค์ ํจ๊ณผ์ ์ผ๋ก ํตํฉํ๊ณ ๊ด๋ฆฌํ๋ ๋ฐ ํฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด์๋ ํ๋ก์ ํธ์ ํน์ฑ๊ณผ ์๊ตฌ์ฌํญ์ ๋ง๊ฒ ์ ์ฐํ๊ฒ ์ ์ฉํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ๋๋ก๋ ์ํฐ ํจํด์ผ๋ก ์ฌ๊ฒจ์ง๋ ๋ฐฉ์์ด ํน์ ์ํฉ์์๋ ์ต์ ์ ์ ํ์ผ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ํญ์ ์ํฉ์ ๊ณ ๋ คํ์ฌ ํ๋จํ๊ณ ์ ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋ค์ ์น์ ์์๋ ์ด ๊ธ์ ๋ง๋ฌด๋ฆฌ์ ํจ๊ป ์ถ๊ฐ ํ์ต ์๋ฃ๋ฅผ ์ ๊ณตํ์ฌ, ์ฌ๋ฌ๋ถ์ด ์์กด์ฑ ์ฃผ์ ์ ๋ํด ๋ ๊น์ด ์๊ฒ ํ์ตํ ์ ์๋๋ก ๋์๋๋ฆฌ๊ฒ ์ต๋๋ค. ๐
11. ๋ง๋ฌด๋ฆฌ ๋ฐ ์ถ๊ฐ ํ์ต ์๋ฃ ๐
์ง๊ธ๊น์ง .NET Core ์ฝ์ ์ฑ์์์ ์์กด์ฑ ์ฃผ์ ์ ๋ํด ๊น์ด ์๊ฒ ์ดํด๋ณด์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊ธฐ๋ณธ ๊ฐ๋ ๋ถํฐ ์์ํ์ฌ ์ค์ ๊ตฌํ, ํ ์คํ , ์ฑ๋ฅ ์ต์ ํ, ๊ทธ๋ฆฌ๊ณ ๋ชจ๋ฒ ์ฌ๋ก์ ์ํฐ ํจํด๊น์ง ๋ค์ํ ์ฃผ์ ๋ฅผ ๋ค๋ฃจ์์ต๋๋ค.
ํต์ฌ ์์ฝ
- ์์กด์ฑ ์ฃผ์ ์ ์ฝ๋์ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๊ณ ์ ์ง๋ณด์์ฑ์ ๋์ด๋ ๊ฐ๋ ฅํ ๋์์ธ ํจํด์ ๋๋ค.
- .NET Core๋ ๋ด์ฅ๋ DI ์ปจํ ์ด๋๋ฅผ ์ ๊ณตํ์ฌ ์์กด์ฑ ์ฃผ์ ์ ์ฝ๊ฒ ๊ตฌํํ ์ ์๊ฒ ํด์ค๋๋ค.
- ์ฝ์ ์ฑ์์๋ ์์กด์ฑ ์ฃผ์ ์ ํ์ฉํ์ฌ ๋ชจ๋ํ๋๊ณ ํ ์คํธ ๊ฐ๋ฅํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
- ์ ์ ํ ์๋น์ค ์๋ช ๊ด๋ฆฌ์ ์ฑ๋ฅ ์ต์ ํ ๊ธฐ๋ฒ์ ํตํด ํจ์จ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
- ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๊ณ ์ํฐ ํจํด์ ํผํจ์ผ๋ก์จ ๋ ๋์ ์ฝ๋ ํ์ง์ ๋ฌ์ฑํ ์ ์์ต๋๋ค.
์ถ๊ฐ ํ์ต ์๋ฃ
์์กด์ฑ ์ฃผ์ ๊ณผ .NET Core์ ๋ํด ๋ ๊น์ด ํ์ตํ๊ณ ์ถ๋ค๋ฉด, ๋ค์ ์๋ฃ๋ค์ ์ฐธ๊ณ ํ์ธ์:
- ๊ณต์ ๋ฌธ์
- ์ฑ
- "Dependency Injection Principles, Practices, and Patterns" by Mark Seemann and Steven van Deursen
- "Pro ASP.NET Core 3" by Adam Freeman
- ์จ๋ผ์ธ ์ฝ์ค
- ๋ธ๋ก๊ทธ ๋ฐ ์ํฐํด
- ์คํ ์์ค ํ๋ก์ ํธ
- dotnet/runtime - .NET Core ๋ฐํ์์ ์์ค ์ฝ๋
- Autofac - ์ธ๊ธฐ ์๋ DI ์ปจํ ์ด๋
๋ง๋ฌด๋ฆฌ
์์กด์ฑ ์ฃผ์ ์ ํ๋ ์ํํธ์จ์ด ๊ฐ๋ฐ์์ ํ์์ ์ธ ๊ธฐ์ ์ ๋๋ค. ํนํ ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ์์ ๋ค์ํ ์๋น์ค๋ฅผ ํตํฉํ๊ณ ๊ด๋ฆฌํ ๋, ์์กด์ฑ ์ฃผ์ ์ ์์น์ ์ ํ์ฉํ๋ฉด ์ ์ฐํ๊ณ ํ์ฅ ๊ฐ๋ฅํ ์์คํ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
์ด ๊ธ์์ ๋ค๋ฃฌ ๋ด์ฉ๋ค์ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด๋ฉด์, ์ฌ๋ฌ๋ถ๋ง์ ๊ฒฝํ๊ณผ ๋ ธํ์ฐ๋ฅผ ์์๊ฐ์๊ธฐ ๋ฐ๋๋๋ค. ์์กด์ฑ ์ฃผ์ ์ ์ฒ์์๋ ๋ณต์กํด ๋ณด์ผ ์ ์์ง๋ง, ๊พธ์คํ ์ค์ต๊ณผ ํ์ต์ ํตํด ๋ง์คํฐํ ์ ์๋ ๊ฐ๋ ฅํ ๋๊ตฌ์ ๋๋ค.
์์ผ๋ก์ ๊ฐ๋ฐ ์ฌ์ ์์ ์์กด์ฑ ์ฃผ์ ์ ํตํด ๋ ๋์ ์ฝ๋๋ฅผ ์์ฑํ๊ณ , ๋ ํจ์จ์ ์ธ ์์คํ ์ ๊ตฌ์ถํ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ํญ์ ์๋ก์ด ๊ธฐ์ ๊ณผ ํจํด์ ๋ํด ์ด๋ฆฐ ๋ง์์ ๊ฐ์ง๊ณ , ์ง์์ ์ผ๋ก ํ์ตํ๋ ๊ฐ๋ฐ์๊ฐ ๋์ธ์. ์ฌ๋ฌ๋ถ์ ์ฑ์ฅ๊ณผ ์ฑ๊ณต์ ์์ํฉ๋๋ค! ๐
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ