티스토리 뷰

흔히들 bean 객체를 쓰면 모듈간에 결합도가 낮아져서 개발이 편리해진다는데... 그럼 결합도는 뭐고, bean을 사용하면 어떤 점이 구체적으로 좋다는 걸까? 

 

바로 확인해보자.


우선 결합도는 정보처리기사 공부할 때 나오는 필기 & 실기에 무조건 나오는 개념이며, 쉽게 말해 어떤 모듈이 다른 모듈에 얼마나 의존하고 있는 지 정도로 나타낸 것이다. (21년 1회 실기에도 나왔지만, 틀렸...)

 

즉, 결합도가 높을 수록, 수정할 때 서로 얽혀있는 것들이 많아 쉽사리 건들기 힘들다는 말이다.

 

바로 이해되는 예제를 하나 확인해보자.


다음과 같이 SamsungTV와 LgTV 객체가 존재하며, 두 객체는 동일한 이름의 메서드를 가지고 있다.

 

◎SamsungTV.java

package polymorphism;

public class SamsungTV{
	
	public SamsungTV() {
		System.out.println("SamsungTV --- 객체 생성");
	}

	public void powerOn() {
		System.out.println("SamsungTV --- 전원 켜기");
	}

	public void powerOff() {
		System.out.println("SamsungTV --- 전원 끄기");
	}

	public void volumeUp() {
		System.out.println("SamsungTV --- 볼륨 켜기");
	}

	public void volumeDown() {
		System.out.println("SamsungTV --- 볼륨 줄이기");
	}
	
}

 

◎LgTV.java

package polymorphism;

public class LgTV{

	public LgTV() {
		// TODO Auto-generated constructor stub
	}
	
	public void powerOn() {
		System.out.println("LgTV --- 전원 켜기");
	}
	
	public void powerOff() {
		System.out.println("LgTV --- 전원 끄기");
	}
	
	public void volumeUp() {
		System.out.println("LgTV --- 소리 키우기");
	}
	
	public void volumeDown() {
		System.out.println("LgTV --- 소리 줄이기");
	}

}

이때, Main에서 다음과 같이 둘 중 하나의 객체를 맴버 변수로 선언하여 메서드를 사용할 수 있다.  

 

◎Main

package polymorphism;

public class TVuser {

	public static void main(String[] args) {
		
		SamsungTV samsungTV = new  SamsungTV();
		
		samsungTV.powerOn();
		samsungTV.powerOff();
		samsungTV.volumeDown();
		samsungTV.volumeUp();
		
	}

}

그러나, Samsung이 아닌 LG TV로 수정해야 한다면? 맴버 변수인 samsungTV가 작성된 모든 부분을 LgTV로 변경해야 하는 번거로움이 존재한다.

 

어떤 프로젝트에서 이런 경우가 발생한다면, 진짜 1시간은 수정만 해야하는 경우가 분명히 생길 것이다. 

 

그렇기 때문에 이렇게 직접 맴버 변수를 선언하여 사용하는 것이 결합도가 높다는 것이다.


그럼 여기서 이 결합도를 한 단계 낮출 수 있는 방법이 있다. 

 

바로 인터페이스를 구현받아 사용하는 것 

 

◎TV.java (interface)

package polymorphism;

public interface TV {
	public void powerOn();
	public void powerOff();
	public void volumeUp();
	public void volumeDown();
}

위와 같이 추상 메서드를 구현해놓은 인터페이스를 생성하고, SamsungTV와 LgTV에서 각각 구현받은 메서드를 재정의 하여 사용하는 것이다.

 

◎SamsungTV.java

package polymorphism;

public class SamsungTV implements TV{
	
	public SamsungTV() {
		System.out.println("SamsungTV --- 객체 생성");
	}

	@Override
	public void powerOn() {
		System.out.println("SamsungTV --- 전원 켜기");
	}

	@Override
	public void powerOff() {
		System.out.println("SamsungTV --- 전원 끄기");
	}

	@Override
	public void volumeUp() {
		System.out.println("SamsungTV --- 볼륨 켜기");
	}

	@Override
	public void volumeDown() {
		System.out.println("SamsungTV --- 볼륨 줄이기");
	}
	
}

 

◎LgTV.java

package polymorphism;

public class LgTV implements TV{

	public LgTV() {
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public void powerOn() {
		System.out.println("LgTV --- 전원 켜기");
	}
	
	@Override
	public void powerOff() {
		System.out.println("LgTV --- 전원 끄기");
	}
	
	@Override
	public void volumeUp() {
		System.out.println("LgTV --- 소리 키우기");
	}
	
	@Override
	public void volumeDown() {
		System.out.println("LgTV --- 소리 줄이기");
	}

}

 

◎Main

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVuser {

	public static void main(String[] args) {
		
		TV tv = new SamsungTV();
		
		tv.powerOn();
		tv.powerOff();
		tv.volumeDown();
		tv.volumeUp();
		
	}

}

 

이렇게 구성하면, Main에서는 Samsung과 LG 각각의 객체가 아닌 TV라는 인터페이스를 맴버 변수로 선언하여 사용하면 되기 때문에, 수정이 필요할 때 생성자 부분만 수정하면 되는 것이다.


이 보다 한단계 더 결합도를 낮추는 방법이 존재하는데, 이게 바로 bean 객체를 활용하는 것이다. 

 

우선, 다음과 같이 beanFactory 객체를 만들어 각 TV 객체를 생산하여 반환하는 Factory를 구성한다.

 

◎beanFactory

package polymorphism;

public class BeanFactory {

	public BeanFactory() {
		// TODO Auto-generated constructor stub
	}
	
	public Object getBean(String beanName) {
		if(beanName.equals("samsung")){
			return new SamsungTV();
		}else if(beanName.equals("lg")){
			return new LgTV();
		}else {
			return null;
		}
	}

}

이후에는 간단하다, 그냥 Main에서 command를 보내 값을 받으면 끝.

 

◎Main

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVuser {

	public static void main(String[] args) {
		
		BeanFactory factory = new BeanFactory();
		
		TV tv = (TV)factory.getBean("samsung");
		
		tv.powerOn();
		tv.powerOff();
		tv.volumeDown();
		tv.volumeUp();
		
		// 3. Spring Container 종료
		factory.close();
	}

}

이 경우, getBean() 에 들어가는 command 만 변경하면 되기 때문에 더욱 유지보수가 용이하다.


이러한 bean 객체는 Spring에서 기본적으로 제공하기 때문에 STS에서 xml문서를 이용하여 자동으로 매핑되게끔 관리할 수 있다.

 

바로 알아보자.

우선 해당 패키지에서 new를 눌러 bean 환경 설정 문서를 생성할 수 있다. 

 

◎applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id = "tv" class = "polymorphism.SamsungTV">
	</bean>

</beans>

이후 다음과 같이 bean 객체를 등록해주면, 끝이다.

 

◎Main

package polymorphism;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TVuser {

	public static void main(String[] args) {
		
		// 1. Spring Container 구동
		AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");
		
		// 2. Spring Container 로부터  필요한 bean객체를 요청
		TV tv = (TV)factory.getBean("tv");
		
		tv.powerOn();
		tv.powerOff();
		tv.volumeDown();
		tv.volumeUp();
		
		// 3. Spring Container 종료
		factory.close();
	}

}

main에서는 위와 같이 xml 설정 문서를 가져와서 사용하면 간단하게 사용이 가능하다.

 

이러한 bean 객체에 대한 개념은 Spring 프로젝트에서 굉장히 많이 사용되니, 반드시 제대로 숙지하고 넘어가야 한다.

 

 

Comments