Java

[SpringFramework] Coupling, 강한 결합과 느슨한 결합

ride-dev 2023. 11. 26. 00:00

강한 결합과 느슨한 결합

0. 결합(Coupling)이란? 

무언가를 변경하는 데 얼마나 많은 작업이 관련되어 있는지에 대한 것입니다.

 

결합은 일상생활에서 찾아볼 수 있습니다.

더보기

자동차를 예시로 들어보겠습니다.

자동차의 구성 요소들을 생각하면

엔진, 타이어, 핸들, 전면 유리,  키, 내비게이션, 블랙박스, 엔진 오일, 워셔액 등이 있습니다.

이 중에 엔진은 자동차에 (강하게) 결합되어 있습니다, 엔진을 교체하는 작업은 상당히 번거롭습니다.

타이어는 어떤가요? 타이어를 교체하는 것이 번거로울 수 있지만, 엔진에 비해 상대적으로 수월합니다.

워셔액은 또 어떻죠? 누구나 보충할 수 있습니다. 이는 느슨한 결합이라고 볼 수 있습니다.

 

데스크톱과 노트북을 예시로 들어보겠습니다.

집에 설치된 노트북과 데스크톱을 사용하는 데 크게 어려움은 없을 겁니다.

그러나 집이 아닌 야외, 카페나 학교 혹은 정말 야외에서 사용한다고 생각해 보십시오.

절대 불가능하다고 할 수는 없지만, 상당한 어려움이 있을 것입니다.

 

이처럼 결합(Coupling)은 일상생활에서도 쉽게 떠올리거나 찾아볼 수 있습니다.

1. 결합(Coupling)의 필요성?

결합은 훌륭한 소프트웨어를 구축하는 데 중요한 요소 중 하나입니다.

 

고객의 요구사항에 따라,

소프트웨어에 새로운 기능을 추가하거나,

기존에 사용하던 기술을 신버전으로 변경하는 것 등,

소프트웨어의 변화는 필연적입니다.

 

소프트웨어의 작동을 중단하는 것이 아니라면,

최소한의 코드만 변경하여 소프트웨어를 업데이트할 수 있어야 합니다.

변경사항에 대해 신속하고 유연한 대처를 하기 위해 느슨한 결합(Loose Coupling)이 필요합니다.

2. Java에서의 결합(Coupling)

더보기

다음은 Java에서 결합을 설명하기 위한 예제입니다.

(생략된 부분이 많습니다)

현재 애플리케이션에서 하나의 프로그램으로 하나의 게임만 실행시키는 것은 문제가 되지 않습니다.

ProgramRunner클래스의 생성자를 보면, Game을 매개변수로 받고 있기 때문에

컴파일 오류 없이 게임을 실행할 수 있습니다.

만약, 동일한 프로그램으로 기존 게임(Game)이 아닌, 다른 게임(New Game)을 실행하려면 어떻게 해야 할까요?

 

더보기

강한 결합(Tight Coupling)으로 만들어진 코드를 보겠습니다.

ProgramRunner 클래스가 특정 게임에 강하게 결합되어 있기 때문에,

BasicApp과 ProgramRunner, 두 곳의 클래스에서 코드를 변경(삭제 혹은 비활성화)합니다.

 

이제 인터페이스(Console)를 도입하여 느슨한 결합(Loose Coupling)을 만들어보겠습니다.

더보기

구조는 아래와 같습니다.

ProgramRunner가 Console을 상호작용하도록 하고,

모든 Game이 Console 인터페이스를 도입합니다.

변경된 코드

각 게임의 동일한 기능(up)을 interface(Console)로 묶습니다.

이제 다른 게임을 실행하려면, BasicApp만 수정합니다.

빨간 사각형으로 표시한 부분을 Game으로 변경하면 됩니다

다른 게임을 실행하는 상황에서

인터페이스를 도입하면

(이전 코드에 비해)

가독성이 향상되고(변경 시, 둘러봐야 하는 범위가 줄어듭니다)

코드 변경 사항이 줄어들며(구현체만 변경합니다)

유지보수가 쉬워집니다.

 

물론, 규모가 작으면 인터페이스를 도입하지 않아야 더 적은 코드를 작성하게 될 수도 있습니다.

그러나, 규모가 커질수록 인터페이스를 도입하는 것이, 더 적은 코드를 작성하게 만듭니다.

 

구멍가게에서 물건을 구매할 때는 각종 상품이 뒤죽박죽 있을 때, 상품을 찾는 데 큰 시간이 소요되지 않지만

4층 규모의 마트에서 물건을 구매할 때 각종 상품이 뒤죽박죽 있다고 생각하면 상당히 끔찍합니다.

당장은 뒤죽박죽 진열하는 것이 빠를지라도

각 구역을 나누어 진열하는 것이 나중을 생각하면 이득일 수밖에 없습니다.

더보기

여기서 Game은 ProgramRunner의 의존성입니다.

Console 또한 ProgramRunner의 의존성입니다.

ProgramRunner는 의존성을 연결합니다.

 

SpringFramework에서는 Game에 의존성을 주입할 수 있습니다.

기존 코드에서는

 var game = new NewGame();

Game클래스가 생성되고, 

 var programRunner = new ProgramRunner(game);

ProgramRunner 클래스에 주입되거나 결합됩니다.

규모가 커지면, 수천수만 개의 의존성이 생성되며 필요한 곳에 주입됩니다.

그 정도 규모의 코드에 대해 수동으로 객체를 생성, 관리 및 실행할 수 있을까요?

 

SpringFramework를 사용한다면 수동으로 객체를 생성, 결합하지 않아도 됩니다.

(Spring이 객체를 관리합니다)

 

다음 게시글에서는 Spring을 실행하고, Spring에서 Bean이라고 불리는 객체를 생성해 보도록 하겠습니다.

728x90