SPRING/Spring Basic

[Spring] 스프링을 사용하는 이유

IT록흐 2024. 2. 1. 01:39
반응형

 

 

 

스프링(Spring)을 사용하는 이유

 

스프링을 사용하는 이유는 객체(Bean) 생성의존관계 주입(DI)을 대신 해주기 때문이다. ( IOC, 제어의 역전 )

 

그렇다면,

개발에서 객체생성과 의존관계 주입을 대신 해주는 프레임워크가 필요한 이유는 무엇일까? Spring은 객체지향개발을 도와주는 프레임워크이다. 객체지향개발에서 핵심은 객체 간 결합도를 줄이는 것이다. 

 

 

 

 

public class Computer {

	MouseA mouseA = new MouseA(); // MouseA에 의존, 결합도 증가
    
    public void click(){
    	mouseA.click();  // MouseA에 의존
    }
}

 

 

 

컴퓨터 객체가 마우스 객체를 참조하면 클릭 기능을 사용할 수 있다. 그러나 위 코드와 같이, 컴퓨터가 특정 마우스에 직접 접근하면 두 객체 사이의 결합도는 증가한다. 컴퓨터 클래스 안의 코드는 마우스A 전용코드가 된다. 만약 마우스A에서 마우스B로 변경된다면, 컴퓨터 클래스의 코드도 모두 수정해야 한다. 이는 객체지향의 5대 원칙 중 하나인 DIP(의존역전원칙)를 위배한 것이다. 

 

 

 

 

 

 

public class Computer {

	Mouse mouse = new MouseA(); // MouseA 구현체에 의존, 결합도 증가
    
    public void click(){
    	mouse.click(); 
    }
}

 

 

그러므로 컴퓨터는 추상화된 마우스 인터페이스에 접근해야 한다.

 

인터페이스를 추가하여 설계를 다시 하였지만 아직 결합도가 남아있다. 메소드는 특정 마우스에게 의존하지 않게 되었지만 Mouse 구현체를 생성하는 코드에서는 결합이 발생한다. 위 코드처럼, 객체가 의존하는 객체를 직접 생성(new)하고 주입하면 결합도는 증가한다.

 

1) 객체를 직접 생성하면 안된다. 

2) 객체를 직접 주입하면 안된다. 

 

두 가지를 지키면 객체는 특정 객체와 결합하지 않아, 객체지향설계 원칙 중 하나인 OCP(개방-폐쇄 원칙)를 지키며 기능을 확장할 수 있다. 

 

그렇다면 팩토리 패턴(Factory Pattern)을 이용하여, 객체를 생성하고 주입하는 권한을 팩토리 객체에게 넘겨보자. 

 

 

 

 

 

public class Computer {

    Mouse mouse;
    
    public Computer(MouseFactory mouseFactory){
    	mouse = mouseFactory.getMouse("A");
    }
     
    public void click(){
    	mouse.click(); 
    }
}

public class MouseFactory{

	public Mouse getMouse(String mouse){
    
            if(mouse.equals("A")) return new MouseA();
            else if(mouse.equals("B")) return new MouseB();
            else return new MouseC();
        
    	}

}

 

 

 

Computer가 MouseFactory에게 어떤 객체를 사용할 것인지 명시만 해주면 MouseFactory가 Mouse 구현체를 대신 생성(new)하고 return 하여 주입(Injection) 한다. Computer는 특정한 Mouse 구현체와 직접 연관되는 것이 없으니 OCP가 구현된다. 

 

그럼 이제 Spring 프레임워크가 무엇을 하는지 감이 올 것이다. 

 

Spring 프레임워크는 스프링 컨테이너에 객체(Bean)를 미리 생성해놓는다. 이것을 Bean이라 부른다. 생성된 Bean은 다른 객체에 주입할 수 있다. 이것이 의존관계 주입(Dependency Injection)이다. 

 

 

 

public class Computer {

    @Autowired // 의존관계 주입
    @Qualifier("mouseA") // 명시
    Mouse mouse;
  
    public void click(){
        mouse.click();
    }
}


@Configuration
public class SpringConfig{

    @Bean
    Mouse mouseA(){
        return new MouseA(); // MouseA Bean 생성
    }

    @Bean
    Mouse mouseB(){
        return new MouseB(); // MouseB Bean 생성
    }

    @Bean
    Mouse mouseC(){
        return new MouseC(); // MouseC Bean 생성
    }
}

 

 

Computer가 직접 Mouse 객체를 생성하고 주입하면 결합도가 증가하니 Spring이 대신 생성하고 주입한다. 

 

@Configuration으로 선언된 설정클래스에 명시된 Bean 정보는 BeanDefinition 객체 변환되고 Spring은 BeanDefinition을 참조하여 Bean을 생성하고 스프링컨테이너에 등록한다. Bean 생성이 완료되었으니 Computer 객체를 생성하면, Spring은 @Autowired가 선언된 변수에 맞는 타입을 가진 Bean을 스프링 컨테이너에서 찾아 주입한다. @Qualifier로 명시된 Bean 이름이 있으면 찾아서 주입한다.

 

이렇듯, Spring이 대신 객체를 생성하고 주입하기에, Spring으로 개발하면 효율적인 객체지향 개발이 가능해진다.

 

 

ApplicationContext

 

 

 

 

 

 

스프링 컨테이너는 ApplicationContext를 의미한다. ApplicationContext 인터페이스는 BeanFactory 인터페이스를 상속하는데, BeanFactory가 스프링 컨테이너의 핵심이다. BeanFactory는 이름부터가 팩토리이므로, 객체지향 개발의 핵심이라고 할 수 있다. Spring은 객체를 생성하고 주입하는 제어권을 Spring 자신에게 가져옴으로써( IOC, 제어의 역전 ), 객체 지향 개발을 손쉽게 도와주는 프레임워크라고 할 수 있다.

 

 

 

 

 

반응형