티스토리 뷰

Dev/Design Pattern

Coupling이란? Tight Coupling vs Loose Coupling 정리

꿈을 위해 잠을 잊은 그대에게 2020. 4. 4. 10:36

- Coupling의 정의

 

coupling이란 서로 상호작용하는 시스템들간의 의존성을 의미한다. 의존성은 실질적 의존성과 인위적 의존성으로 나뉠 수 있다. 실질적 의존성은 한 시스템이 소비하는 다른 시스템의 기능이나 서비스 집합을 의미한다 인위적 의존성은 한 시스템이 다른 시스템이 제공하는 기능이나 서비스를 소비하기 위해 필요한 여러 요소들의 집합을 의미한다. 전형적으로 인위적 의존성은 언어적인 의존성, 플랫폼 의존성, API 의존성등이 있다. 인위적 의존성은 언제나 존재하지만 그 비용은 충분히 감소될 수 있다. Loose Coupling은 이러한 인위적 의존성을 최소한으로 줄이는 구조를 의미한다.

 

긴밀한 결합(Tight Coupling)

 

 강하게 결합된 객체(Tightly Coupled Object)는 다른 오브젝트에 대한 상당히 많은 정보를 필요로 하고 보통 두 객체간의 인터페이스들에게 서로 높은 의존성을 가지고 있다. 타이트하게 연견된 애플리케이션에서 하나의 객체를 변경하는 것은 많은 다른책체들을 변경을 요구한다. 작은 애플리케이션에서는 변경점들을 확인하고 쉽고 놓칠수 있는 가능성도 적지만 많약에 큰 프로젝트이면 그렇지 않다. 그러나 느슨하게 연결된 오브젝트(Loosely Coupled Objects)들은 서로 의존성이 없다.

 

느슨한 결합(Loose Coupling)

 

 느슨한 결합은 하나의 콤포넌트의 변경이 다른 콤포넌트들의 변경을 요구하는 위험을 줄이는 것을 목적으로 하는 시스템에서  콤포넌트 간의 내부 의존성을 줄이는 것을 추구하는 디자인 목표다. 느슨한 결합은 시스템을 더욱 유지 할 수 있도록 만들고, 전체 프레임워크를 더욱 안정적으로 만들고 시스템의 유연성을 증가하게 하려는 의도를 가진 포괄적인 개념이다.

 

- Loose Coupling의 강력함

 

두 객체가 느슨하게 결합되어 있다는 것은, 그 둘이 상호작용을 하긴 하지만 서로에 대해서 서로 잘 모른다는 것을 의미합니다.

 

옵저버 패턴에서는 주제(subject)와 옵저버(observer)가 느슨하게 결합되어 있는 객체 디자인을 제공합니다.

왜 그럴까요?

 

주제가 옵저버에 대해서 아는 것은 옵저버가 특정 인터페이스(Observer Interface)를 구현한다는 것 뿐입니다. 

옵저버의 구상 클래스(Concreate Class)가 무엇인지, 옵저버가 무엇을 하는지 등에 대해서는 알 필요가 없습니다.

 

옵저버는 언제든지 새로 추가할 수 있습니다. 

주제는 Observer 인터페이스를 구현하는 객체의 목록에만 의존하기 때문에 언제든지 새로운 옵저버를 추가할 수 있죠. 사실 실행중에 한 옵저버를 다른 옵저버로 바꿔도 되고, 그렇게 해도 주제 객체는 계속해서 데이터를 보낼 수 있습니다. 마찬가지로, 옵저버를 아무 때나 제거해도 됩니다.

 

새로운 형식의 옵저버를 추가하려고 할 때도 주제를 전혀 변경할 필요가 없습니다. 

옵저버가 되어야 하는 새로운 구상 클래스가 생겼다고 가정해 봅시다. 이 때도 새로운 클래스 형식을 받아들일 수 있도록 주제를 바꿔야 할 필요는 없습니다. 새로운 클래스에서 Observer 인터페이스를 구현하고 옵저버로 등록하기만 하면 되지요. 주제 객체는 전혀 신경도 쓰지 않습니다. Observer 인터페이스만 구현한다면 어떤 객체에든지 연락을 하니까요.

 

주제와 옵저버는 서로 독립적으로 재사용할 수 있습니다. 

주제나 옵저버를 다른 용도로 활용할 일이 있다고 해도 손쉽게 재사용할 수 있습니다. 그 둘이 서로 단단하게 결합되어 있지 않기 때문이죠.

 

주제나 옵저버가 바뀌더라도 서로한테 영향을 미치지는 않습니다. 

둘이 서로 느슨하게 결합되어 있기 때문에 주제 혹은 옵저버 인터페이스를 구현한다는 조건만 만족된다면 어떻게 바꿔도 문제가 생기는 일은 없습니다.

 

- Loose Coupling 디자인 원칙

 

서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.

 

느슨하게 결합하는 디자인을 사용하면 변경 사항이 생겨도 무난히 처리할 수 있는 유연한 객체지향 시스템을 구축할 수 있습니다. 객체 사이의 상호 의존성을 최소화할 수 있기 때문이죠.

 

- Tight Coupling vs Loose Coupling의 예제

 

객체 지향 설계에서 커플링은 한 요소가 다른 요소에 대해 가지고있는 직접적인 지식의 정도를 나타냅니다. 다시 말해, 클래스 A의 변경이 클래스 B의 변경과 관련된 빈도를 나타냅니다. 두 가지 유형의 커플링이 있습니다.

 

긴밀한 결합(Tight Coupling) : 일반적으로 긴밀한 결합은 두 클래스가 종종 서로 바뀌는 것을 의미합니다. 

 

다시 말해, A가 B가 구현 된 방식에 대해 알고있는 것 이상을 알고 있다면 A와 B는 밀접하게 연결되어 있습니다.


: 피부를 바꾸려면 몸이 서로 결합되어 있기 때문에 몸의 디자인도 바꿔야합니다. 

밀접한 결합의 가장 좋은 예는 RMI (Remote Method Invocation)입니다.

class Subject {
	Topic t = new Topic();

	public void startReading() {
		t.understand();
	}
}

class Topic {
	public void understand() {
		System.out.println("Tight coupling concept");
	}
}

 

설명 : 위 프로그램에서 Topic 클래스는 Subject 클래스에 종속됩니다. 

 

위의 프로그램에서 Subject 클래스는 Topic 클래스와 밀접하게 연결되어 있으며, Topic 클래스를 변경할 때 Subject 클래스를 변경해야하는 경우를 의미합니다. 

 

예를 들어, Topic 클래스의 understand() 메소드가 gotit() 메소드로 변경되면 startReading() 메소드를 변경해야하며 understand() 메소드를 호출하는 대신 gotit() 메소드를 호출하여야 합니다.

 

class Volume {
	public static void main(String args[]) {
		Box b = new Box(5, 5, 5);
		System.out.println(b.volume);
	}
}

class Box {
	public int volume;

	Box(int length, int width, int height) {
		this.volume = length * width * height;
	}
}

결과: 125

 

설명 : 위 예에서 두 클래스 사이에는 강력한 상호 종속성이 있습니다. Box 클래스에 변경 사항이 있으면 Volume 클래스의 결과에 반영됩니다.

 

느슨한 결합(Loose Coupling) : 간단히 말하면 느슨한 결합은 대부분 독립적이라는 의미입니다. 

 

클래스 A에 클래스 B에 대한 유일한 내용이 클래스 B의 인터페이스를 통해 구현 된 것이라면 클래스 A와 클래스 B는 느슨하게 결합되어 있다고합니다. 

 

스프링 프레임 워크는 객체 간의 긴밀한 결합 문제를 극복하기 위해 POJO / POJI 모델의 도움으로 의존성 주입 메커니즘을 사용하며 의존성 주입을 통해 느슨한 결합을 달성 할 수 있습니다.


: 셔츠를 갈아 입으면 몸을 바꾸지 않아도됩니다. 그렇게 할 수 있을 때 커플링이 느슨합니다. 그렇게 할 수 없다면, 긴밀한 결합이 있습니다. 느슨한 결합의 예는 인터페이스, JMS입니다.

 

public interface Topic {
	void understand();
}

class Topic1 implements Topic {
	public void understand() {
		System.out.println("Got it");
	}
}

class Topic2 implements Topic {
	public void understand() {
		System.out.println("understand");
	}
}

public class Subject {
	public static void main(String[] args) {
		Topic t = new Topic1();
		t.understand();
	}
}

 

설명 : 위 예에서 Topic1 및 Topic2 객체가 느슨하게 결합되었습니다. 

이는 주제가 인터페이스이고 런타임에 구현 된 클래스를 삽입 할 수 있으며 최종 사용자에게 서비스를 제공 할 수 있음을 의미합니다.

 

// Java program to illustrate
// loose coupling concept
class Volume {
	public static void main(String args[]) {
		Box b = new Box(5, 5, 5);
		System.out.println(b.getVolume());
	}
}

final class Box {
	private int volume;

	Box(int length, int width, int height) {
		this.volume = length * width * height;
	}

	public int getVolume() {
		return volume;

	}
}

결과: 125

 

설명 : 위 프로그램에서 두 클래스 사이에 종속성이 없습니다. Box 클래스에서 아무것도 변경하지 않으면 Volume 클래스에서 아무것도 변경할 필요가 없습니다.

 

Tight Coupling vs Loose Coupling 결론

 

일반적으로 Tight Coupling은 대부분의 경우 코드의 유연성과 재사용성을 감소 시키므로 변경을 훨씬 어렵게 만들고 시험 가능성(Testability) 등을 방해합니다. Loose Coupling은 더 나은 선택입니다. 응용 프로그램을 변경하거나 확장해야 할 때 느슨하게 결합 된 아키텍처로 디자인하는 경우 요구 사항이 변경 될 때마다 응용 프로그램의 일부에만 영향을 미칩니다.


Tight CouplingLoose Coupling의 그림을 살펴 보겠습니다.

Tight CouplingLoose Coupling의 차이점

  • Tight Coupling은 시험 가능성이 좋지 않습니다. 그러나 Loose Coupling은 시험 가능성을 향상시킵니다.
  • Tight Coupling은 인터페이스 개념을 제공하지 않습니다. 그러나 Loose Coupling은 구현이 아닌 인터페이스에 대한 프로그램의 GOF 원칙을 따르는 데 도움이됩니다.
  • Tight Coupling에서는 두 클래스간에 코드를 쉽게 교체 할 수 없습니다. 그러나 Loose Coupling으로 다른 코드 / 모듈 / 객체 / 구성 요소를 교체하는 것이 훨씬 쉽습니다.
  • Tight Coupling에는 변경 기능이 없습니다. 그러나 Loose Coupling은 크게 변경 가능합니다.

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크