Base

강한 의존성과 약한 의존성

Dr.Mlem 2024. 9. 29. 20:22

Q1.
프로그래밍에서 의존성이 강하다와 약하다는 어떤 차이를 말하는거야? 예시를 들어가면서 설명해줄 수 있을까?


 

프로그래밍에서 의존성이 강하다(strong coupling)와 약하다(loose coupling)의 차이는 모듈 간의 상호 의존도에 관한 개념입니다. 즉, 하나의 모듈이 다른 모듈에 얼마나 깊이 의존하는지를 나타냅니다. 이 개념은 소프트웨어 설계에서 매우 중요한데, 의존성이 강할수록 시스템이 변경에 취약해지고 유지보수가 어려워질 수 있습니다. 반면에, 의존성이 약하면 시스템을 확장하거나 변경할 때 더 유연하게 대응할 수 있습니다.

1. 의존성이 강한 경우 (Strong Coupling)

의존성이 강할 때는 한 모듈이 다른 모듈의 내부 구현에 강하게 의존하고 있어서, 한 모듈이 변경되면 의존하는 다른 모듈도 함께 수정되어야 합니다. 이는 코드 재사용성, 유지보수성에 부정적인 영향을 미칠 수 있습니다.

예시:

Python

class Engine:
    def start(self):
        print("Engine started.")

class Car:
    def __init__(self):
        self.engine = Engine()
    
    def start(self):
        self.engine.start()
        print("Car started.")

위의 코드에서 Car 클래스는 Engine 클래스에 강하게 의존하고 있습니다. Car 클래스는 Engine 객체를 직접 생성하고 사용합니다. 만약 Engine 클래스가 수정되거나 변경된다면, Car 클래스도 수정해야 할 가능성이 큽니다. 이렇듯 두 클래스가 서로 강하게 연결되어 있으면 변경에 취약해집니다.

2. 의존성이 약한 경우 (Loose Coupling)

의존성이 약할 때는 한 모듈이 다른 모듈의 세부 사항에 의존하지 않고, 인터페이스나 추상화를 통해 상호작용합니다. 이를 통해 한 모듈이 변경되더라도 다른 모듈에 미치는 영향을 최소화할 수 있습니다.

예시:

Python

class Engine:
    def start(self):
        print("Engine started.")

class ElectricEngine:
    def start(self):
        print("Electric engine started.")

class Car:
    def __init__(self, engine):
        self.engine = engine
    
    def start(self):
        self.engine.start()
        print("Car started.")

이 경우, Car 클래스는 특정한 Engine 구현체에 의존하지 않고, 대신 주입된 엔진(Engine 객체든 ElectricEngine 객체든)을 사용합니다. 이는 의존성이 약한 구조로, Car는 Engine이나 ElectricEngine을 사용할 수 있으므로 더 유연합니다. 만약 엔진의 구현이 변경되더라도, Car 클래스는 영향을 덜 받게 됩니다.

주요 차이점 정리:

  • 강한 의존성: 한 클래스가 다른 클래스의 구현에 직접적으로 의존. 변화에 민감하며 수정 시 많은 영향을 미침.
  • 약한 의존성: 클래스들이 인터페이스나 추상화를 통해 상호작용. 유연하고 확장성, 유지보수성이 높음.

이 개념을 잘 활용하면, 변화에 유연하고 확장 가능한 시스템을 설계하는 데 큰 도움이 됩니다.



Q2.
Java 코드를 써서 설명해주겠어?

java

class Engine {
    public void start() {
        System.out.println("Engine started.");
    }
}

class Car {
    private Engine engine;

    public Car() {
        // Car가 직접 Engine을 생성
        this.engine = new Engine();
    }

    public void start() {
        engine.start();
        System.out.println("Car started.");
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}

 

설명:

위 코드에서 Car 클래스는 Engine 클래스에 강하게 의존하고 있습니다. Car가 Engine 객체를 직접 생성하기 때문에, 만약 Engine 클래스가 변경되면 Car도 영향을 받아야 합니다. 예를 들어, Engine 클래스가 start() 메서드를 ignite()로 바꾼다면 Car 클래스도 해당 메서드명을 수정해야 합니다.

이러한 강한 의존성은 확장성과 유연성을 제한하게 됩니다. 예를 들어, 만약 ElectricEngine이라는 새로운 엔진 타입을 추가하고 싶다면, Car 클래스도 수정을 필요로 합니다.

2. 의존성이 약한 경우 (Loose Coupling)

java

interface Engine {
    void start();
}

class GasolineEngine implements Engine {
    public void start() {
        System.out.println("Gasoline engine started.");
    }
}

class ElectricEngine implements Engine {
    public void start() {
        System.out.println("Electric engine started.");
    }
}

class Car {
    private Engine engine;

    // 의존성을 주입받음 (Dependency Injection)
    public Car(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.start();
        System.out.println("Car started.");
    }
}

public class Main {
    public static void main(String[] args) {
        // GasolineEngine을 사용하는 Car
        Engine gasolineEngine = new GasolineEngine();
        Car gasolineCar = new Car(gasolineEngine);
        gasolineCar.start();

        // ElectricEngine을 사용하는 Car
        Engine electricEngine = new ElectricEngine();
        Car electricCar = new Car(electricEngine);
        electricCar.start();
    }
}

 

설명:

이번 예시는 의존성이 약한 경우입니다. Car 클래스는 Engine이라는 인터페이스에 의존하고, GasolineEngine과 ElectricEngine은 이 인터페이스를 구현합니다. 이제 Car는 특정 엔진 구현체에 직접적으로 의존하지 않고, 인터페이스를 통해 다양한 엔진을 사용할 수 있습니다.

이 방식에서는 Engine의 구현체가 바뀌어도 Car 클래스는 변경될 필요가 없습니다. 예를 들어, 나중에 새로운 엔진 타입을 추가하고 싶다면, Car 클래스에는 전혀 손대지 않고 새로운 엔진 구현체만 추가하면 됩니다.

의존성 주입 (Dependency Injection)의 장점:

  • 확장성: 새로운 엔진 타입을 추가할 때 Car 클래스를 수정할 필요가 없습니다.
  • 유연성: Car는 여러 종류의 엔진을 주입받아 사용할 수 있으므로 상황에 맞게 동작을 변경할 수 있습니다.
  • 유지보수성: Engine의 구현체가 변경되더라도 Car 클래스에 미치는 영향이 적습니다.

요약:

  • 강한 의존성: 클래스가 다른 클래스의 구현체에 직접 의존해서 변경에 취약.
  • 약한 의존성: 인터페이스를 통해 상호작용하여 더 유연하고 확장 가능.

이런 의존성 설계는 복잡한 시스템을 유지보수하고 확장하는 데 매우 중요한 역할을 합니다.


'Base' 카테고리의 다른 글

Parsing, 파싱  (0) 2024.09.30
"제너릭"에 대한 공부 5  (0) 2024.09.29
buffer 1  (0) 2024.09.27
"제너릭"에 대한 공부 4  (1) 2024.09.26
"제너릭" 에 대한 공부 2  (0) 2024.09.26