스프링 핵심 원리 이해

Yeseong31·2023년 10월 7일
0

관심사의 분리

SoC: Seperation of Concern

관심사의 분리가 필요한 이유는 SRPDIP를 위해서이다.

  • 하나의 모듈은 하나의 책임만 가져야 한다. ➡️ “SRP”
  • 관심사의 분리가 필요한 이유는 코드를 객체 지향에 맞게 설계하는 것과 같다.

AppConfig의 등장

@Configuration
public class SpringConfig {
	
	private final MemberRepository memberRepository;

	@Autowired
	public SpringConfig(MemberRepository memberRepository) {
		this.memberRepository = memberRepository;
	}

	@Bean
	public MemberService memberService() {
		return new MemberService(memberRepository);
	}
}
  • AppConfig는 구현 객체를 생성하고 연결하는 책임을 가지는 별도의 설정 클래스이다.
    • 애플리케이션의 실제 동작에 필요한 구현 객체를 생성한다.
    • 그리고 생성한 객체 인스턴스의 참조를 생성자를 통해 주입한다. ➡️ “의존 관계 주입”
  • 이를 통해 구현체는 의존 관계에 대한 고민을 외부에 맡기고, 본인의 로직을 실행하는 데에 집중할 수 있다.

구현 객체를 생성하고 연결하는 책임은 AppConfig에 있다. ➡️ “SRP”
AppConfig가 클라이언트 코드 대신 객체 인스턴스를 생성하고, 의존 관계를 주입한다. ➡️ “DIP”
AppConfig가 의존 관계를 주입하므로 클라이언트 코드는 변경되지 않는다. ➡️ “OCP”


제어의 역전

IoC: Inversion of Control

제어의 역전은 프로그램의 제어 흐름을 개발자가 아닌 외부에서 관리하는 것을 말한다.

  • AppConfig 등장 이후로 구현 객체는 자신의 로직을 실행하는 역할만 담당하게 되었다.
  • 이제 프로그램의 제어 흐름과 권한은 모두 AppConfig에게 넘겨졌다.
  • 이와 같이 개발자가 작성한 객체/메서드의 제어를 외부에 위임하도록 설계하는 것제어의 역전이라 한다.

프레임워크와 라이브러리의 관계를 생각해보자.
프레임워크의 통제권은 개발자가 아닌 프레임워크 자체에 있다. 개발자는 프레임워크가 제공하는 틀 안에서 코드를 작성해야 한다. 반면 라이브러리의 통제권은 재발자에게 있다. 개발자는 기능 구현에 필요한 라이브러리를 불러서 코드를 작성할 수 있다.


의존 관계 주입

DI: Dependency Injection

애플리케이션 실행 시점에 외부에서 실제 구현 객체를 생성하고, 클라이언트에 전달하여 클라이언트와 서버가 실제 의존 관계를 맺는 것의존 관계 주입이라고 한다.

  • 의존 관계 주입을 사용하면 코드 변경 없이 클라이언트가 호출하는 대상의 타입 인스턴스를 변경할 수 있다.
  • 또한 정적인 클래스 의존 관계의 변경 없이 동적인 객체 인스턴스 의존 관계를 쉽게 변경할 수 있다.

정적 의존 관계

public class OrderServiceImpl implements OrderService {

	private final MemberRepository memberRepository;
	private final DiscountPolicy discountPolicy;
}
  • 애플리케이션을 실행하지 않고 코드의 형태만 보아도 의존 관계를 쉽게 알 수 있다.
  • 다만 애플리케이션 실행 전에는 외부에서 어떤 객체가 주입될지 알지 못한다.

동적 의존 관계

  • 애플리케이션 실행 시점에 실제 생성된 객체 인스턴스의 참조가 연결된 의존 관계이다.

IoC/DI 컨테이너

  • AppConfig처럼 객체를 생성하고 관리하면서 의존 관계를 연결해 준다.
  • 최근에는 “의존 관계”에 초점을 맞추어 DI 컨테이너라고 많이 부른다.

스프링으로 전환

AppConfig 스프링 기반으로 변경

@Configuration
public class AppConfig {

	@Bean
	public MemberService memberService() {
		return new MemberServiceImpl(memberRepository());
	}

	@Bean
	public OrderService orderService() {
		return new OrderServiceImpl(
				memberRepository(), discountPolicy());
	}

	...
}
  • @Configuration, @Bean을 통해 스프링 컨테이너에 스프링 빈으로 등록한다.

MemberApp에 스프링 컨테이너 적용

public class MemberApp {
	
	public static void main(String[] args) {
	
		ApplicationContext applicationContext 
				= new AnnotationConfigApplicationContext(AppConfig.class);

		MemberService memberService 
				= applicationContext.getBean("memberService", MemberService.class);

		...
	}
}

스프링 컨테이너

ApplicationContext applicationContext 
		= new AnnotationConfigApplicationContext(AppConfig.class);
  • ApplicationContext를 스프링 컨테이너라고 한다.
  • 스프링 컨테이너는 XML, 애노테이션 등 다양한 설정 정보를 받아들이도록 설계되었다.

애노테이션 기반 자바 설정 클래스

  • 스프링 컨테이너는 @Configuration이 붙은 AppConfig를 설정 정보로 사용한다.
  • 스프링 컨테이너에 등록된 객체를 스프링 빈이라고 한다.
    • @Bean이 붙은 메서드를 모두 호출하여 반환된 객체를 스프링 컨테이너에 등록한다.
    • 스프링 빈은 @Bean이 붙은 메서드의 이름을 스프링 빈의 이름으로 사용한다.

참고

[인프런] 스프링 핵심 원리 - 기본편

profile
역시 개발자는 알아야 할 게 많다.

0개의 댓글

관련 채용 정보