1) 스프링 프레임워크란? - 자바 플랫폼을 위한 오픈소스 애플리케이션 프레임워크 - 엔터프라이즈급 애플리케이션을 개발하기 위한 모든 기능을 종합적으로 제공하는 경량화된 솔루션 - 스프링 프레임워크는 경량 컨테이너로 자바 객체를 담고 직접 관리 - 객체의 생성 및 소멸, 라이프 사이클을 관리 - 객체가 필요하면 언제든지 스프링 컨테이너로부터 가져와 사용할 수 있다. - 스프링 프레임워크는 IOC 기반
[엔터프라이즈급 애플리케이션 개발?] - 기업을 대상으로 하는 개발 - 여러 사용자로부터 대규모 데이터 처리와 트랜잭션이 동시에 행해지는 큰 규모의 환경을 엔터프라이즈 환경
2) IoC[제어의 역전]란? 객체지향의 원리(OCP, DIP)를 적용하지 않은 프래그램의 경우 일반적으로 아래의 과정이 반복적으로 이루어진다. 1. 객체 생성 2. 의존성 객체 생성 -> 클래스 내부에서 생성 3. 의존성 객체 메소드 호출 이는 각 객체들이 프로그램의 흐름을 결정하고, 각 객체를 구성하는 작업에 직접적으로 참여한 것이다. 즉,객체의 생성 및 호출 작업이 사용자에 의해 제어가 되는 구조이다. 이해를 돕기 위해 아래의 예제를 살펴보자. 주문 서비스 클라이언트(OrderServiceImpl)에서는 상품을 주문 시, 고정액으로 할인을 적용해주거나 금액에 따른 비율로 할인을 적용해줄 수 있는 2가지의 정책이 있다. 클라이언트에서 기존에 사용하였던 고정액 할인 정책 되신 비율 할인 정책을 사용한다고 하면 코드를 변경해야 한다. 이럴 경우, OCP와 DIP 원칙을 모두 위반하게 된다. - OCP : 기능을 확장해서 변경하게 되면 클라이언트 코드에 영향을 준다. 즉 확장에는 열려 있고 변경에는 닫혀 있어야하는 OCP 원칙을 위반하게 된다. - DIP : 클라이언트가 인터페이스 뿐만 아니라 구체 클래스에도 의존을 하고 있다. DIP를 위반 클래스 다이어그램을 보면 클라이언트(OrderServiceImpl)가 할인정책 인터페이스(DiscountPolicy)에만 의존하기를 기대하였지만, 인터페이스 뿐만 아니라 구현 클래스에도 의존하고 있는 모습을 확인할 수 있다. 하지만 IoC(Inversion of Control)는 객체나 메소드의 생성 및 호출작업을 개발자가 결정하는 것이 아니라, 외부에서 결정된다. 즉, 제어권한을 위임받은 스프링에서 객체의 생성 및 라이프사이클이 관리되고, 사용자는 필요한 객체를 컨테이너에서 꺼내서 사용하기만 하면 된다.
스프링에서는 다음과 같은 순서로 객체가 생성되고 사용된다. 1. 객체 생성 2. 의존성 객체 주입 -> 사용자가 객체를 스스로 만드는 것이 아니라 제어권을 스프링에서 위임하여 스프링이 만들어 놓은 객체를 주입 3. 의존성 객체 메소드 호출
스프링은 - 모든 의존성 객체를 스프링이 실행될 때 다 만들어주고 필요한 곳에 주입시켜주며, 스프링 빈은 싱글톤으로 관리가 된다. - 객체의 의존성을 역전시켜 객체 간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 하여 가독성 및 코드 중복, 유지 보수를 편리하게 할 수 있도록 도와준다.
■ 수동 빈 등록 예제
- ApplicationContext를 스프링 컨테이너 - 스프링 컨테이너는 @Configuration이 붙은 클래스(AppConfig.class)를 설정 정보로 사용 - @Bean 어노테이션이 붙은 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록 - 스프링 컨테이너에 등록된 객체를 스프링 빈이고 한다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import soyeon.study.inflearn.member.MemberRepository;
import soyeon.study.inflearn.member.MemberService;
import soyeon.study.inflearn.member.MemberServiceImpl;
import soyeon.study.inflearn.member.MemoryMemberRepository;
import soyeon.study.inflearn.order.*;
@Configuration
public class AppConfig {
//클라이언트에서 필요한 구현 객체를 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 DiscountPolicy discountPolicy(){
//return new FixedDiscountPolicy();
return new RateDiscountPolicy();
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import soyeon.study.inflearn.AppConfig;
import soyeon.study.inflearn.AutoAppConfig;
import soyeon.study.inflearn.member.Grade;
import soyeon.study.inflearn.member.Member;
import soyeon.study.inflearn.member.MemberService;
import soyeon.study.inflearn.member.MemberServiceImpl;
import soyeon.study.inflearn.order.Order;
import soyeon.study.inflearn.order.OrderService;
import soyeon.study.inflearn.order.OrderServiceImpl;
//주문 서비스 App
public class OrderApp {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
MemberService memberService = ac.getBean("memberServiceImpl", MemberService.class);
OrderService orderService = ac.getBean("orderServiceImpl", OrderService.class);
Member member = new Member(1L, "memberA", Grade.VIP);
memberService.join(member);
Order order = orderService.createOrder(member.getMemberId(), "itemA", 20000);
System.out.println("할인 가격 = " + order.calculate());
System.out.println("주문 내역 = " + order.toString());
}
}
■ POJO
- Plain Old Java Object, 단순한 자바 오브젝트 - POJO는 객체 지향적인 원리에 충실하면서 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트 - POJO의 장점으로는 객체지향적인 설계를 자유롭게 적용, 깔끔한 코드, 간편한 테스트가 있다. - 스프링 프레임워크는 POJO 방식의 프레임워크이다.