내가 이해하기 위해!! 참고자료: 스프링 퀵 스타트 제 1장
-
프레임워크의 사전적 의미
- 뼈대, 틀
-
소프트웨어 관점
- 아키텍처에 해당하는 골격코드
- 프레임워크를 사용하면 애플리케이션에 대한 분석, 설계, 구현 모두에서
재사용성 이 증가한다.
-
빠른 구현 시간
- 프레임워크를 사용하면 아키텍처에
해당하는 골격 코드를 프레임워크에서 제공 - 개발자는
비즈니스 로직만 구현한다. - 제한된 시간에 많은 기능을 구현할 수 있다.
- 프레임워크를 사용하면 아키텍처에
-
쉬운 관리
- 같은 프레임워크가 적용된 애플리케이션은
아키텍쳐가 같으므로 관리하기가 쉽다. - 유지보수에 들어가는
인력과 시간도 줄일 수 있다.
- 같은 프레임워크가 적용된 애플리케이션은
-
개발자들의 역량 획일화
- 경험이 적은 개발자도, 경험이 많은 개발자도 생성한 코드가 비슷해진다.
- 효율적으로 구성이 가능하다.
-
검증된 아키텍쳐의 재사용과 일관성 유지
- 프레임워크에서 제공하는 아키텍쳐를 이용하므로
별다른 검증 없이소프트웨어 개발이 가능하다. - 왜곡이나 변형이 없다.
- 프레임워크에서 제공하는 아키텍쳐를 이용하므로
- 자바 기반의 프레임워크로
오픈소스 형태로 제공한다.
- 로드 존슨이 2004년에 만든 오픈소스 프레임워크
- POJO(Plain Old Java Object)를 사용하면서도 EJB일도 가능하도록 지원한다.
- IoC와 AOP를 지원하는 경량의 컨테이너 프레임워크
-
경량(Lightweight)
- 여러 개의 모듈로 구성되어 있고, 하나 이상의 JAR파일로 구성되어있다.
- 가볍고 빠르다.
- POJO형태의 객체를 관리한다.
-
제어의 역행(Inversion of Control)
- 낮은 결합도를 유지한다.
- 객체를 변경할 때 자바코드를 수정하지 않고,
컨테이너가 대신 처리함으로 의존 관계가 떨어져 유지보수가 편리하다.
-
관점지향 프로그래밍(Aspect Oriented Programming, AOP)
- 비즈니스 메소드를 개발할 때, 핵심 비즈니스 로직과 각 비즈니스 메소드마다 반복해서 등장하는
공통 로직을 분리함으로써 응집도가 높게 개발 지원 - 공통기능 -> 외부의 독립된 클래스로 분리/ 선언적으로 처리
- 비즈니스 메소드를 개발할 때, 핵심 비즈니스 로직과 각 비즈니스 메소드마다 반복해서 등장하는
-
컨테이너
- 특정 객체의 생성과 관리 담당
- 객체 운용에 필요한 다양한 기능 제공
- 서버안에 포함되어 배포 및 구동
- 스프링도 일종의 컨테이너다.
public class HelloServlet extends HttpSerblet{
public HelloServlet(){
System.out.println("===> HelloServlet 객체 생성");
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException{
System.out.println("doGet() 메소드 호출");
}
}- Servlet클래스는 web.xml에 자동으로 등록된다.
<web-app>
<servlet>
<servlet-name>hello</servlet>
<servlet-class>hello.HelloServlet</servlet-class> <!-- hello.HelloServlet클래스를 찾아 객체를 생성 후 실행 -->
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello.do</url-pattern> <!--hello.do url요청 -->
</servlet-mapping>
</web-app>실행결과
===> HelloServlet 객체 생성
doGet() 메소드 호출
- WEB-INF/web.xml 파일을 로딩하여 구동
- 브라우저로부터 /hello.do 요청 수신
- hello.HelloServlet 클래스를 찾아 객체를 생성하고 doGet()메소드 호출
- doGet() 메소드 실행 결과를 클라이언트 브라우저로 전송
- 컨테이너는 자신이 관리할 클래스들이 등록된 XML 설정 파일은 로딩하여 구동
- 클라이언트의 요청이 들어오는 순간 XML 설정파일을 참조 //객체 생성, 객체 생명주기 관리
- 개발자가 어떤 객체를 생성할지 판단하고 객체 간의 의존관계도를 소스코드로 표현
- 제어의 역행은 소스코드가 아닌
컨테이너로 처리
SamsungTV.java
package polymorphism;
public class 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.our.println("SamsungTV ---소리 내린다.");
}
}LgTV.java
package polymorphism;
public class LgTV{
public void turnOn(){
System.out.println("LgTV ---전원 켠다.");
}
public void turnOff(){
System.out.println("LgTV ---전원 끈다.");
}
public void soundUp(){
System.out.println("LgTV ---소리 올린다.");
}
public void soundDown(){
System.our.println("LgTV ---소리 내린다.");
}
}두개의 클래스는 같은 기능을 수행하는 메소드가 있지만 메소드 이름이 다르다.
TVUser.java
package polymorphism;
public class TVUser{
public static void main(String[] args){
SamsungTV tv = new SamsungTV();
tv.powerOn();
tv.volumeUp();
tv.volumeDown();
tv.powerOff();
}
}
}유저가 자바 코드 대부분을 수정해야한다. 그러므로 TV 교체를 결정하기가 쉽지 않을 것이다.
결합도를 낮추기 위해서 다형성을 이용한다. TV 클래스들의 최상위 부모로 사용할 TV인터페이스를 추가하고 공통으로 가져야 할 메소드를 추상 메소드로 선언한다.
TV.java
package polymorphism;
public interface TV{
public void powerOn();
public void powerOff();
public void volumeUp();
public void volumeDown();
}TV 인터페이스들을 구현하도록 수정한다.
SamsungTV.java
package polymorphism;
public class SamsungTV implements TV{
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.our.println("SamsungTV ---소리 내린다.");
}
}LgTV.java
package polymorphism;
public class LgTV implements TV{
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.our.println("LgTV ---소리 내린다.");
}
}TVUser.java
package polymorphism;
public class TVUser{
public static void main(String[] args){
SamsungTV tv = new SamsungTV();
tv.powerOn();
tv.volumeUp();
tv.volumeDown();
tv.powerOff();
}
}
}이제 참조하는 객체만 변경하면 된다. 객체를 쉽게 변경 가능하다. 다형성을 이용하면 최소한의 수정으로 객체를 교체 가능하다. 따라서 유지보수는 좀 더 편해졌다고 볼 수 있다.
결합도를 낮추기 위한 또 다른 방법으로 디자인 패턴을 이용하는 것이다.
TV를 교체할 때 클라이언트 소스를 수정하지 않고 TV만 교체할 수 있으면 유지보수는 더 편리해질 것이다.
이를 위헤 factory 패턴을 적용해야한다.
- factory패턴? 클라이언트에서 사용할 객체 생성을 캡슐화하여 TVUser와 TV사이를 느슨한 결합 상태로 만들어준다.
BeanFactory.java
package polymorphism;
public class BeanFactory{
public Object getBean(String beanName){
if(beanName.equals("samsung")){
return new SamsungTV():
}else if(beanName.equals("lg")){
return new LgTV();
}
return null;
}
}TVUser.java
package polymorphism;
public class TVUser{
public static void main(String[] args){
BeanFactory factory = new BeanFactory();
TV tv = (TV)factory.getBean(args[0]);
tv.powerOn();
tv.volumeUp();
tv.volumeDown();
tv.powerOff();
}
}
}프로그램을 실행하고 Lg 나 Samsung을 넘겨주면 된다. Run As - Run Configurations - Arguments탭 선택 - 입력 순이다. 유저는 더욱 간단하게 TV객체를 변경할 수 있을 것이다.