Spring Framwork 특징

  • 경량 컨테이너로서 자바 객체를 직접 관리한다. 각각의 객체 생성, 소멸과 같은 라이프 사이클을 관리하며 스프링으로부터 필요한 객체를 얻어올 수 있다.
  • 스프링은 Plain Old Java Object 방식의 프레임워크이다. 일반적인 J2EE 프레임워크에 비해 구현을 위해 특정한 인터페이스를 구현하거나 상속을 받을 필요가 없어 기존에 존재하는 라이브러리 등을 지원하기에 용이하고 객체가 가볍다.
  • 스프링은 제어 반전(IoC : Inversion of Control)을 지원한다. 컨트롤의 제어권이 사용자가 아니라 프레임워크에 있어서 필요에 따라 스프링에서 사용자의 코드를 호출한다.
  • 스프링은 의존성 주입(DI : Dependency Injection)을 지원한다. 각각의 계층이나 서비스들 간에 의존성이 존재할 경우 프레임워크가 서로 연결시켜준다.
  • 스프링은 관점 지향 프로그래밍(AOP : Aspect-Oriented Programming)을 지원한다. 따라서 트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통적으로 사용하는 기능의 경우 해당 기능을 분리하여 관리할 수 있다.
  • 스프링은 영속성과 관련된 다양한 서비스를 지원한다. iBATIS나 하이버네이트 등 이미 완성도가 높은 데이터베이스 처리 라이브러리와 연결할 수 있는 인터페이스를 제공한다.
  • 스프링은 확장성이 높다. 스프링 프레임워크에 통합하기 위해 간단하게 기존 라이브러리를 감싸는 정도로 스프링에서 사용이 가능하기 때문에 수많은 라이브러리가 이미 스프링에서 지원되고 있고 스프링에서 사용되는 라이브러리를 별도로 분리하기도 용이하다.

이러한 어려워 보이는 많은 특징이 있다. 간단하게 Spring Framework의 핵심 기능 중 하나인 강한 결합을 느슨한 결합으로 만들어 주는 것부터 알아보려 한다.

예를 들어 아래에 간단한 Pacmangame을 만든다고 가정한다.


    var game = new PacmanGame();            // 객체 생성
    var gameRunner = new GameRunner(game);  // 객체 생성 + GameRunner클래스에 game주입

이러한 의존성이 수많은 클래스 생성 시 수많은 의존성이 필요한 곳에 주입이된다. 이를 수동으로 직접 생성, 관리, 실행하는 것을 Spring Framwork가 하도록 한다.

사용 방법

  1. Spring apllications이나 Spring context 실행
  2. Spring Framwork가 관리하도록 설정 (@Configuration 주석을 추가한 설정클래스를 만들고 정의 가능 그리고 @Bean주석이 있는 메서드를 생성해야한다.)

예를 들어 HelloWorldConfiguration라는 Configuration클래스를 만들고 context라는 인스턴스 생성하여 Spring Context실행 가능

    import org.springframework.context.annotation.AnnotationConfigApplicationContext;

    var context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);

    // name 이라는 Bean 메서드가 있다면 아래의 방벙으로 호출가능
    System.out.println(context.getBean("name"));

기존의 Spring Bean과 관계가 있는 Spring Bean 생성 및 Bean 재활용

  1. 메서드 호출
  2. 적절한 매개변수 사용
    @Bean
    public String name() {
        return "Ranga";
    }

    @Bean
    public int age() {
        return 15;
    }
    
    @Bean
    public Person person() {
        return new Person("Ravi", 20, new Address("Main Street", "Utrecht"));
    }

    @Bean
    public Person person2MethodCall() {
        return new Person(name(), age());
        
    }

    @Bean
    public Person person3Parameters(String name, int age, Address address2) {
        return new Person(name, age, address2);

    }

    @Bean(name = "address2")
    public Address address() {
        return new Address("Baker Street", "London");
    }

    @Bean(name = "address3")
    public Address address() {
        return new Address("Gwangalli Street", "Busan");
    }

    // 출력 방법 클래스 이름 또는 Bean 이름 사용
    System.out.println(context.getBean(Address.class)) // 지금은 일치하는 Bean이 2개 이상이라 에러 발생
    System.out.println(context.getBean("address2"))

💡 Bean이 2개이상으로 에러가 발생 한다면 해결방법은 크게 2가지

  1. 기본 주소 @primary로 설정해주기
  2. @Qualifier로 한정자로 자동 연결해주기

    @Bean
    public Person person5Qualifier(String name, int age, @Qualifier("address3qualifier")) {
        return new Person(name, age, address);
        
    }

    @Bean(name = "address2")
    @Primary
    public Address address() {
        return new Address("Baker Street", "London");
    }

    @Bean(name = "address3")
    @Qualifier("address3qualifier")
    public Address address() {
        return new Address("Gwangalli Street", "Busan");
    }

용어 정리

Record

  • 불변(immutable) 데이터 객체를 쉽게 생성할 수 있도록 하는 새로운 유형의 클래스
  • JDK14에서 preview로 등장하여 JDK16에서 정식 스펙으로 포함
  • 일반적으로 Java 클래스를 만들 때는 수많은 getter, setter 메서드를 생성하는데 이러한 Java Bean의 불편함을 해소
  • equals, hashCode, toString, public 생성자를 생성해주면서, 변수들은 private final 키워드로 취급
  • record는 final 클래스라서 상속이 불가능
  • 모든 필드는 private final로 정의 됨
    // 일반적인 무결성을 생각한 코드
    public class Person{
        private final String name;
        private final int age;

        public Person(String name, int age){
            this.name = name;
            this.age = age;
        }

        public String getName(){
            return name;
        }

        public int getAge(){
            return age;
        }

    // Record
    record Person (String name, int age) {};

Spring Container

  • 스프링에서 의존관계 주입(Dependency Injection, DI)을 이용하여 애플리케이션을 구성하는 여러 빈(Bean)들의 생명주기(Lifecycle)와 애플리케이션의 서비스 실행 등을 관리하며 생성된 인스턴스들에게 기능을 제공하는 것을 부르는 말이다.
  • 스프링 컨테이너를 언급할때는 빈 팩토리(BeanFactory)와 애플리케이션 컨텍스트(ApplicationContext) 두 가지로 다룬다.

Bean

  • Bean 또는 Bean Object는 스프링이 IoC 방식으로 관리하는 오브젝트(managed object)라는 뜻
  • Bean은 스프링을 사용하는 애플리케이션에서 만들어지는 모든 오브젝트가 아니라 스프링이 직접 그 생성과 제어를 담당하는 오브젝트만을 Bean이라고 부른다.

Bean factory

  • 스프링의 IoC를 담당하는 핵심 컨테이너
  • 빈을 등록하고, 생성하고, 조회하고 돌려주고, 그 외에 부가적인 빈을 관리하는 기능을 담당
  • 보통은 이 빈 팩토리를 바로 사용하지 않고 이를 확장한 Application Context를 이용
    • 이유는 BeanFactory의 모든 기능을 포함하는 것은 물론이고 아래 추가 기능들을 제공하기 때문이다.
    • 따라서 이 추가기능들을 사용하는 것보다 메모리 소모량 축소가 더욱 중요한 상황이 아니라면 추가 기능을 위해 사용하는 것이 좋다.
  • BeanFactory라고 붙여쓰면 빈 팩토리가 구현하고 있는 가장 기본적인 인터페이스의 이름이 된다. 이 인터페이스에 getBean()과 같은 메소드가 정의되어 있다.

Application Context

  • 빈 팩토리를 확장한 IoC 컨테이너 기본적인 기능은 빈 팩토리와 동일 여기에 스프링이 제공하는 각종 부가 서비스를 추가로 제공한다.
    • 웹 애플리케이션, REST API, 마이크로서비스 등
  • 빈 팩토리라고 부를 때는 주로 빈의 생성과 제어의 관점에서 이야기하는 것이고, 애플리케이션 컨텍스트라고 할 때는 스프링이 제공하는 애플리케이션 지원 기능을 모두 포함해서 이야기하는 것이라고 보면 된다.
  • 스프링에서는 애플리케이션 컨텍스트라는 용어를 빈 팩토리보다 더 많이 사용한다. ApplicationContext라고 적으면 애플리케이션 컨텍스트가 구현해야 하는 기본 인터페이스를 가리키는 것이기도 하다. Application Context는 BeanFactory를 상속한다.

SpringContext

Cofiguration Metadata

  • Application Context 또는 Bean Factory IoC를 적용하기 위해 사용하는 메타 정보
  • IoC 컨테이너에 의해 관리되는 애플리케이션 오브젝트를 생성하고 구성할 때 사용
  • Application의 형상정보, 청사진(Application의 전체 그림이 그려져 있는) 이라고도 한다.

Container, IoC Container 등

  • Application Context나 Bean Factory를 Container 또는 IoC Container(주로 Application Context) 등 다양하게 불린다.
  • IoC 방식으로 Bean을 관리한다는 의미에서 Application Context나 Bean Factory를 그냥 Container 또는 IoC 컨테이너 라고 함
  • ApplicationContext 인터페이스를 구현한 오브젝트를 가리키기도 한다.
  • Spring에 빈을 등록하고는 Spring Container 또는 Application Context를 말한다.

Java Bean vs POJO vs Spring Bean

Java Bean

  • 오늘날은 많이 쓰이지 않는다.
  • 크게 3가지 제약
    • public 기본 생성자, no-arg 생성자 존재
    • getter, setter 사용해서 properties에 접근 가능
    • java Serializable implements

POJO(Plain Old Java Object)

  • 아무 제약이 없다.
  • Java 클래스를 생성하면 아무 제약없는 POJO 객체다.
  • 특정한 라이브러리나 컨테이너 기술에 종속족이지 않음을 의미하며 자유롭게 객체지향적 설계를 구현할 수 있다.
  • 가장 일반적인 형태로 코드를 작성하고 실행할 수 있으며, 높은 생산성과 유연한 테스트를 할 수 있다.

Spring Bean

  • IoC Container가 관리하는 모든 객체는 Spring Bean이다.
  • Spring 사용자는 IoC Container, Bean Factory 또는 ApplicationsContext 로 객체들을 관리한다.

댓글남기기