Spring이란 JAVA를 좀 더 편하게 사용할 수 있게 해주는 프레임워크로 대규모의 회사에서 많이 사용한다.
여기서 "JAVA를 좀 더 편하게" 라는 단어의 의미를 김영한님의 "스프링 핵심 원리 - 기본편" 을 들으며 이해할 수 있게 되었다.
내가 프로그래밍을 하다 보면 하나의 class 혹은 객체에 정~말 다양한 책임과 기능을 모두 넣어 사용했었다. (혼자 기획하고 개발하다보니..)
그 이후에 객체 지향 설계 원칙에 대해 알게 되었고 그 설계 원칙을 단 하나도 지키지 않고 프로그래밍을 했다는 것 또한 알게 되었다.
내가 느낀바로는 Spring은 객체 지향적인 설계를 할 수 있도록 도와주는 아주 좋은 툴이라는 생각이 들었다.
Spring에서 주요하게 사용 되는 단어로 IoC , DI 라는 단어가 나온다
IoC : 제어의 역전 (Inversion of Control)
기존의 프로그램은 구현 객체가 프로그램 제어 흐름에 직접적으로 개입(인스턴스 생성 등)하여 실행되었다.
// private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
//인스턴스 생성시 discountPolicy에 RateDiscountPolicy를 직접적으로 선언
위의 코드와 같이 코드를 작성하게 되면 RateDiscountPolicy를 사용하지 않고 FixDiscountPolicy를 사용하게 되면 해당 class로 가서 계속 코드를 바꿔줘야한다. 이것은 OCP(Open - Closed Principle : 확장에는 오픈, 변경에는 클로즈)에 위배된다. 또한 DIP(Dependency Inversion Principle : 인터페이스에만 의존 하기) 도 위배되고 있다.
그래서 내부의 코드를 바꾸지 않고 외부에서 생성자를 통해 기능을 주입하고자 한다. class는 외부에서 어떤 역할을 쥐어 주던 실행에만 신경을 쓰면 되기 때문에 OCP에 위배되지 않을 수 있다. 아래 AppConfig 클래스 코드를 보면 이해하기 쉬울 것이다.
...
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
public OrderService orderService() {
return new OrderServiceImpl(
memberRepository(),
discountPolicy());
}
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
public DiscountPolicy discountPolicy() {
return new FixDiscountPolicy();
}
}
그래서 AppConfig를 사용하여 기능 테스트를 해보면 더 명확해진다.
public class MemberServiceTest {
MemberService memberService;
@BeforeEach
public void beforeEach(){
AppConfig appConfig = new AppConfig();
memberService = appConfig.memberService();
}
@Test
void join(){
//given
Member member = new Member(1L, "memberA", Grade.VIP);
//when
memberService.join(member);
Member findMember = memberService.findMember(1L);
//then
Assertions.assertThat(member).isEqualTo(findMember);
}
}
이렇게 제어의 흐름을 직접 제어하는 것이 아니라 외부에서 제어 할 수 있도록 하는 것이 IoC(제어의 역전)이라고 한다.
DI : 의존관계 주입 (Dependency Injection)
애플리케이션 실행 시점(런타임)에 외부에서 인스턴스를 생성하고 클라이언트에 전달하여 클라이언트와 서버의 실제 의존 관계가 연결되는 것을 의존 관계 주입이라고 일컫는다.
Spring에서는 AppConifg 처럼 객체를 생성 & 관리 하며 의존관계를 연결해주는 것을 IoC컨테이너 또는 "DI 컨테이너"라고 한다. (Spring 컨테이너라고도 부름 )
스프링에서 자동으로 DI 컨테이너 등록
...
@Configuration
public class AppConfig {
@Bean
public MemberService memberService(){
return new MemberServiceImpl(memberRepository());
}
@Bean
public OrderService orderService(){
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public static DiscountPolicy discountPolicy() {
// return new FixDiscountPolicy();
return new RateDiscountPolicy();
}
}
스프링은 "@Configuration"이 붙은 AppConfig.class를 구성 정보로 사용한다.
해당 클래스 안에서 "@Bean" 이 붙은 메서드를 모두 호출하여 return된 객체를 스프링 컨테이너(=DI 컨테이너)에 등록한다.
(스프링 컨테이너에 등록된 객체를 스프링 빈이라고 한다)
자동으로 등록한 스프링 빈 사용하기
public class OrderApp {
public static void main(String[] args) {
// AppConfig appConfig = new AppConfig();
// MemberService memberService = appConfig.memberService();
// OrderService orderService = appConfig.orderService();
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
long memberId = 1L;
Member member = new Member(memberId, "memberA", Grade.VIP);
memberService.join(member);
Order order = orderService.createOrder(memberId, "itemA", 10000);
System.out.println("order = " + order);
}
}
ApplicationContext (인터페이스)를 스프링 컨테이너라고 하고, 애노테이션(@~~~) 기반의 자바 설정 클래스로 스프링 컨테이너를 구성하였다.
구현을 위해 new AnnotationConfigApplicationContext()에 AppConfig.class를 인자로 받아 스프링 컨테이너를 생성한다.
이는 AppConfig.class를 구성정보로하여 스프링컨테이너를 생성하였다고 일컫는다.
'개발 > Spring' 카테고리의 다른 글
[Spring Cache] Spring boot 환경에서 Redis Cache 사용하기 (0) | 2023.02.15 |
---|---|
[Spring] Spring MVC 정리 (0) | 2022.12.23 |
[Spring] 스프링 코어 정리 2 - 어노테이션 (0) | 2022.10.31 |
[Spring] 스프링 코어 정리 1 (0) | 2022.10.12 |
[Spring] 스프링 컨테이너의 빈 조회 방법 (0) | 2022.08.25 |