본문 바로가기

Study/Summary

스프링/ 빈(Bean) / 프레임워크vs라이브러리 / 의존성 주입

반응형

스프링부트

스프링은 JAVA 애플리케이션 개발을 위한 오픈 소스의 프레임워크이다. 스프링은 7대기능 ex) Spring JDBC, Spring MVC, Spring AOP, Spring ORM.. 등 모듈이 포함되어 있다. 이러한 모듈은 개발 시간을 대폭 단축 시켰다.

스프링 부트란, 스프링 애플리케이션을 설정하는 데 필요한 상용구 구성을 제거하는 스프링 프레임워크의 확장이다. 위에 언급한 것처럼 기능이 많으니, 스프링 프레임워크의 사용을 위한 설정의 많은 부분을 자동화하여 편리하게 스프링을 사용할 수 있도록 돕는다. Starter 디펜던시만 추가해주면 바로 api를 정의하고, 내장된 탐캣이나 제티로 서버를 실행할 수 있다.

 

spring-boot-starter-*

Starter란 특정 목적을 달성하기 위한 의존성 그룹이라고 생각하면 된다. 만약 우리가 JPA가 필요하다면 prom.xml(메이븐)이나 build.gradle(그레이들)에 'spring-boot-starter-data-jpa'만 추가해주면 spring boot가 그에 필요한 라이브러리들을 알아서 받아온다.

 

라이브러리 vs 프레임워크

라이브러리를 사용하는 애플리케이션 코드는 직접 제어한다. 필요한 기능이 있을 때 능동적으로 라이브러리를 사용하지만, 프레임워크는 애플리케이션 코드가 프레임워크에 의해 사용된다. 즉 “제어 흐름”의 권한이 어디 있는지의 차이이다.

프레임워크는 정해진 룰을 지켜야 하므로, 정의는 개발자가 하지만 알고리즘에 따라 함수를 실행하는 건 프레임워크이다. 부트스트랩, 앵귤러, 뷰 등이 있다.

라이브러리는 미리 만들어진 함수의 집합으로 보면 된다. 라이브러리를 사용하더라도 프레임워크가 정한 방식에 따라야 하지만 어떻게 사용할지 자유롭다. 리액트, 제이쿼리 등이 있다.

 

빈(Bean)

스프링 컨테이너( 스프링에서 자바 객체들을 관리하는 공간)에 의해서 관리되고, 스프링 컨테이너에 의해 자바 객체가 만들어지게 되면 이 객체를 스프링은 스프링 빈 이라고 부른다.

빈을 등록해주는 이유는 스프링이 각 객체간 의존관계를 관리하도록 하는데에 목적이 있다.

@Controller, @Service, @Repository 는 모두 @Component를 상속받고 있으며, 해당 어노테이션으로 등록된 클래스들은 스프링 컨테이너에 의해 자동으로 생성되어 스프링 빈으로 등록 된다.

@Controller
public class MemberController {

	private final MemberService memberService;

	@Autowired
	public MemberController(MemberService memberService){
		this.memberService = memberService;
	}
}

@Service
public class MemberService {

	private final MemberRepository memberRepository;
	...
}

위의 코드와 같이 생성자에 @Autowired 를 적어두면, 이 인스턴스에는 MemberService 와 의존관계를 가진다는 것을 의미한다. 이 @Autowired가 정상적으로 동작하려면 두 인스턴스가 빈으로써 컨테이너에 들어가있어야 하기 때문에 @Controller, @Service 를 써준것이다.

 

의존성주입 DI, Dependency Injection

스프링 프레임워크는 3가지 핵심 프로그래밍 모델을 지원하고 있는데, 그 중 하나가 의존성 주입이다. 외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴으로, 인터페이스를 사이에 둬서 클래스에서는 의존 관계가 고정되지 않도록 하고(유동적임), 런타임 시에 관계를 동적으로 주입하여 유연성을 확보하고 결합도를 낮출 수 있게 해준다.

public class Store {

	private Pencil pencil;

	public Store(){
		this.pencil = new Pencil();
	}
}

위의 코드는 두 클래스가 강하게 결합되어있는 문제가 있는 코드이다. 유연성이 떨어져서 Store에서 pencil이 아닌 Food로 바꾼다고 한다면 생성자에 변경이 필요하게 되는 것이다.

class Coffee {...}
//상속
class Cappucino extends Coffee {...}
class Americano extends Coffee {...}

class Programmer {

	private Coffee coffee;

	public Programmer(){
		this.coffee = new Cappuccino();
		this.coffee = new Americano();

	}
}

그리고 위와 같은 경우에서는 Coffee를 상속하는 클래스가 많아지면 그 중 Cappuccino가 필요한 클래스가 있다면 직접 수정해줘야한다.


public interface Product {

}

public class Pencil implements Product {

}
public class Store {

	private Product product;

	public Store(Product product){
		this.product = product;
	}
}
//컨테이너
Pulbic class BeanFactory {

	public void store(){
		//Bean 생성
		product pencil = new pencil();

		//의존성 주입
		Store store = new Store(pencil);
	}
}

이 과정을 줄여준게 위의 빈 설명헤서 빈으로 등록하고 생성자로 의존성을 주입해준 어노테이션들이다. 이로써 한 클래스를 수정하였을 때 다른 클래스를 수정해야 하는 상황을 막을 수 있다.

다음 세 가지 조건을 충족하는 작업을 의존관계 주입이라고 말한다.

  • 의존관계가 드러나지 않아야 하므로, 인터페이스에만 의존하고 있어야 한다.
  • 의존관계는 컨테이너 같은 제 3의 존재가 결정한다.
  • 의존관계는 사용할 객체에 대한 레퍼런스를 외부에서 제공(주입)해줌으로써 만들어진다.
객체를 직접 생성하는 것이 아닌 외부로 부터 필요한 객체를 받아서 사용하는 것이 의존성 주입이고, 이를 통해 객체간의 결합도를 줄이고 코드의 재활용성을 높여준다.
반응형