프로그래밍/C#

[C#] 의존성 주입 (Dependency Injection)

Victory_HA 2022. 6. 6. 22:46

의존성이란

  • 의존성이라는 것은 A가 B에 의존할 경우 B가 변경될 때 A도 변경될 수 있는 가능성이 있다는 뜻입니다.

    의존성 주입 (Dependency Injection)

  • 의존성 주입이란 외부에서 객체를 생성하여 넘겨주는 것을 의미합니다.

  • 예를들어 A 클래스가 B 클래스를 의존할 때,

  • B Object를 A가 직접 생성하지 않고 외부에서 생성하여 넘겨주면 의존성 주입했다고 합니다.

  • 왼쪽은 A에서 B를 생성하는 일반적인 의존 형태이고, 오른쪽은 외부에서 의존 객체를 생성하고 주입하는 형태입니다.

  • 의존성 주입은 소프트웨어 디자인 패턴 중 하나로, 클래스 간의 의존성을 외부에서 주입하는 방식을 의미합니다.
  • 이를 통해 코드의 재사용성과 유연성을 높이며, 유닛 테스트와 확장성에도 도움을 줍니다.

As-Is 코드 (의존성 주입을 사용하지 않은 경우)

using System;

public class Logger
{
    public void Log(string message)
    {
        Console.WriteLine($"[Log] {message}");
    }
}

public class UserService
{
    private readonly Logger _logger;

    public UserService()
    {
        _logger = new Logger();
    }

    public void DoSomething()
    {
        // 비즈니스 로직 수행
        _logger.Log("Something was done in the UserService.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        UserService userService = new UserService();
        userService.DoSomething();
    }
}
  • UserService 클래스가 Logger 클래스에 의존성을 갖고 있습니다.
  • 이로 인해 UserService 클래스는 Logger 클래스에 강하게 결합되어 있으며, 유닛 테스트나 변경 사항에 취약합니다.

To-Be 코드 (의존성 주입을 적용한 경우)

using System;

public interface ILogger
{
    void Log(string message);
}

public class Logger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine($"[Log] {message}");
    }
}

public class UserService
{
    private readonly ILogger _logger;

    public UserService(ILogger logger)
    {
        _logger = logger;
    }

    public void DoSomething()
    {
        // 비즈니스 로직 수행
        _logger.Log("Something was done in the UserService.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        ILogger logger = new Logger();
        UserService userService = new UserService(logger);

        userService.DoSomething();
    }
}
  • `UserService 클래스가 ILogger 인터페이스에 의존성을 주입받도록 변경되었습니다.
  • 이로써 UserService와 Logger 사이의 결합도가 낮아졌습니다.
  • 또한, Main 메서드에서는 ILogger 구현체를 생성하고 이를 UserService 생성자에 주입하는 방식을 사용합니다.
  • 이렇게 하면 UserService 클래스는 로그 출력에 필요한 구체적인 구현 내용을 몰라도 되며,
  • 다른 종류의 로깅 시스템을 사용하거나 변경하는 데 더 유연해집니다.

속성 주입(Property Injection)과 생성자 주입(Constructor Injection)은 의존성 주입의 다양한 형태 중 두 가지 주요한 형태입니다.
이 두 가지 형태는 각각 다른 방식으로 의존성을 주입하는 방법을 나타냅니다.

생성자 주입(Constructor Injection)

  • 보통 생성자 주입이 의존성 주입을 구현하는 가장 권장되는 방식이며,
  • 클래스의 상태가 객체 생성 이후 변경되지 않도록 보장하는 장점이 있습니다.
  • 생성자 주입은 의존성을 주입할 때 클래스의 생성자를 통해 이루어지는 방식입니다.
  • 클래스가 의존성을 생성자 매개변수로 받아들이고, 객체가 생성될 때 외부에서 의존성을 주입합니다.
  • 생성자 주입은 클래스가 생성될 때 필요한 모든 의존성을 보장받을 수 있도록 해줍니다.
public class UserService
{
    private readonly ILogger _logger;

    public UserService(ILogger logger)
    {
        _logger = logger;
    }

    public void DoSomething()
    {
        // 비즈니스 로직 수행
        _logger.Log("Something was done in the UserService.");
    }
}

속성 주입(Property Injection)

  • 속성 주입은 의존성을 주입할 때 클래스의 속성을 통해 이루어지는 방식입니다.
  • 클래스가 외부 종속성을 갖는 공개 속성을 정의하고, 이 속성을 통해 의존성을 주입받습니다.
  • 일반적으로 속성 주입은 필수적인 의존성이 아닌 선택적인 의존성을 주입할 때 사용될 수 있습니다.
public class UserService
{
    public ILogger Logger { get; set; }

    public void DoSomething()
    {
        // 비즈니스 로직 수행
        Logger?.Log("Something was done in the UserService.");
    }
}

'프로그래밍 > C#' 카테고리의 다른 글

[C#] 디자인패턴-싱글톤 패턴(Singleton Pattern)  (0) 2022.07.03
[C#] ? 와 ?? 연산자  (0) 2022.06.22
[C#] 람다연산자 =>  (0) 2022.06.06
[C#] 오버라이딩이란? (Override)  (0) 2022.06.06
[C#] 키워드 정리  (0) 2022.06.06