토비의 스프링 Chapter 1.4 ~ 1.6 정리

종명·2021년 4월 21일
0

1.4 제어의 역전(IoC)

  • 제어의 역전이란 간단히 프로그램의 제어 흐름 구조가 뒤바뀌는 것이라고 설명할 수 있다.
class UserDaoTest {
  public static void main(String[] args) throws ClassNotFoundException, SQLException {
      ConnectionMaker connectionMaker = new DConnectionMaker();
      UserDao dao = new UserDao(connectionMaker);
      ....
  }
}
  • 위의 UserDaoTest 클래스는 두가지 역할을 하고 있다.
  • ConnectionMaker 객체 생성 및 UserDao 객체에 주입
  • UserDao test

따라서 이 두가지 기능 분리해야 할 필요가 있다.

팩토리

  • 팩토리란 객체의 생성방법을 결정하고 그렇게 만들어진 객체를 돌려주는 역할을 하는 오브젝트를 말한다.
public class DaoFactory{
    public UserDao userDao() {
      ConnectionMaker connectionMaker = new DConnectionMaker();
      UserDao dao = new UserDao(connectionMaker);
      return dao;
    }
}
class UserDaoTest {
  public static void main(String[] args) throws ClassNotFoundException, SQLException {
      UserDao dao = new DaoFactory.userDao();
      ....
  }
}

1.5 스프링의 IoC

  • 스프링에서는 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트를 빈(bean)이라고 부른다. 동시에 스프링 빈은 스프링 컨테이너가 생성과 관계설정, 사용 등을 제어해주는 제어의 역전이 적용된 오브젝트를 가리키는 말이다.
  • 스프링에서는 빈의 생성과 관계설정 같은 제어를 담당하는 IoC 오브젝트를 빈 팩토리(bean factory)라고 부른다. 보통 빈 팩토리보다는 이를 좀 더 확장한 애플리케이션 컨텍스트(applcation context)를 주로 사용한다.
@Configuration 
public class DaoFactory {
  @Bean
  public UserDao userDao() {
      return new UserDao(conntetionMaker());
  }
  @Bean
  public ConnetionMaker connectionMaker() {
      return new ConnectionMaker();
  }
}
  • @Configuration : 애플리케이션 컨텍스트 또는 빈 팩토리가 사용할 설정정보라는 표시
  • @Bean : 오브젝트 생성을 담당하는 IoC용 메소드 라는 표시
class UserDaoTest {

    public static void main(String[] args) 
            throws ClassNotFoundException, SQLException {
        ApplicationContext context = 
                new AnnotationConfigApplicationContext(DaoFactory.class);
    
        UserDao userDao = context.getBean("userDao", UserDao.class);
    }
}
  • DaoFactory처럼 @Configuration이 붙은 자바 코드를 설정정보로 사용하려면 AnnotationConfigApplicationContext 를 이용하면 된다.
  • getBean() : ApplicationContext 가 관리하는 오브젝트를 요청하는 메소드이다.

애플리케이션 컨텍스트의 동작방식

  • 애플리케이션 컨텍스트는 DaoFactory 클래스를 설정정보로 등록해두고 @Bean이 붙은 메소드의 이름을 가져와 빈 목록을 만든다.
  • 클라이언트가 getBean()을 호출하면 자신의 빈 목록에서 요청한 이름을 찾고, 있다면 빈 생성 메소드를 호출해서 오브젝트 생성시킨 후 클라이언트에게 돌려준다.

애플리케이션 컨텍스트를 사용했을 때 얻을 수 있는 장점

  • 클라이언트는 구체적인 팩토리 메서드를 알 필요가 없다.
  • 애플리케이션 컨텍스트는 종합 IoC 서비스를 제공해준다.
  • 애플리케이션 컨텍스트는 빈을 검색하는 다양한 방법을 제공한다.

스프링 IoC 용어 정리

빈 (bean)

빈 또는 빈 오브젝트는 스프링이 IoC방식으로 관리하는 오브젝트라는 뜻이다. 스프링에서 사용하는 모든 오브젝트가 빈이 아니라 그중에서도 스프링이 직접 그 생성과 제어를 담당하는 오브젝트만을 빈이라고 부른다.

빈 팩토리 (bean factory)

스프링의 IoC를 담당하는 핵심 컨테이너를 가르킨다. 빈 등록, 생성, 조회, 반환하고 그외에 부가적인 빈을 관리하는 기능을 담당한다. 보통은 빈 팩토리를 바로 사용하지 않고 이를 확장한 애플리케이션 컨텍스트를 이용한다.

애플리케이션 컨텍스트 (application context)

빈 팩토리를 확장한 IoC 컨테이너이다. 빈을 관리하는 기본적인 기능은 빈 팩토리와 동일하고 여기에 스프링이 제공하는 각종 부가 서비스를 추가로 제공한다.

설정정보 / 설정 메타정보 (configuration metadata)

스프링의 설정정보란 애플리케이션 컨텍스트 또는 빈 팩토리가 IoC를 적용하기 위해 사용하는 메타정보를 말한다.
컨테이너에 어떤 기능을 세팅하거나 조겅하는 경우에도 사용하지만 주로 IoC 컨테이너에 의해 관리되는 애플리케이션 오브젝트를 생성하고 구성할 때 사용된다.

컨테이너 또는 IoC 컨테이너

IoC 방식으로 빈을 관리한다는 의미에서 애플리케이션 컨텍스트나 빈 팩토리를 컨테이너 또는 IoC 컨테이너라고도 한다. 후자는 주로 빈 팩토리 관점에서 이야기하는 것이고, 그냥 컨테이너 또는 스프링 컨테이너라고 할 때는 애플리케이션 컨텍스트를 가리키는 것이라고 보면 된다.

스프링 프레임워크

IoC컨테이너, 애플리케이션 컨텍스트를 포함해서 스프링이 제공하는 모든 기능을 통틀어 말할 때 주로 사용한다.

1.6 싱클톤 레지스트리와 오브젝트 스코프

오브젝트의 동일성과 동등성

자바에서는 두 개의 오브젝트가 같은가라는 말을 주의해서 써야한다.
두개의 오브젝트가 완전히 같은 동일한 오브젝트라고 말하는 것과 동일한 정보를 담고 있는 오브젝트라고 말하는 것은 분명한 차이가 있다.
전자를 동일성 비교(==), 후자를 동등성 비교(equals())하고 한다.


동일성 (Identity) : 두 객체가 완전히 같을 경우
동등성 (Equality) : 두 객체가 같은 정보를 같고 있을 경우

DaoFactory factory = new DaoFactory();

// 두 userDao가 다르다.
UserDao userDao1 = factory.userDao();
UserDao userDao2 = factory.userDao();
ApplicationContext context = new AnnotationConfigApplicationContext(DaoFactory.class);

// 두 userDao가 같다.
UserDao userDao3 = context.getBean("userDao", UserDao.class);
UserDao userDao4 = context.getBean("userDao", UserDao.class);
  • ApplcationContext를 사용하는 경우 같은 객체가 반환된다.
  • 그 이유는 스프링은 기본적으로 별다른 설정을 하지 않으면 내부에서 생성하는 빈 오브젝트를 모두 싱글톤으로 만들기 때문이다.
    여기서 싱글톤이라는 것은 디자인패턴에 나오는 싱글턴과 개념이 비슷하지만 구현방법이 확연히다르다.

싱글톤으로 빈을 만드는 이유

스프링이 주로 적용되는 대상이 자바 엔터프라이즈 기술을 사용하는 서버환경이기 때문이다. 클라이언트 요청이 올때마다 새로운 오브젝트를 만든다고 가정해보자.
요청 한번에 10개의 오브젝트를 만들어야하고, 초당 1000개의 요청이 들어온다면 초당 10000개의 오브젝트를 만들어야한다.
아무리 자바의 오브젝트 생성과 GC의 성능이 좋아졌다고 한들 이렇게 부하가 걸리면 서버가 감당하기 힘들다.

싱글톤 패턴의 한계

public class UserDao{
    private static UserDao INSTANCE;
    ...
    private UserDao(ConnetionMaker connetionMaker) {
        this.connetionMaker = connetionMaker;
    }
    
    public static synchronized UserDao getInstance() {
        if(INSTANCE == null) {
            INSTANCE == new UserDao(...);
        }
        
        return INSTANCE;
    }
}
  • 위는 간단히 구현한 싱글톤 코드이다.
  • 먼저 DaoFactory에서 UserDao를 생성해 ConnectionMaker 오브젝트를 넣어주는 것이 불가능해졌다.

그리고 다음과 같은 일반적인 문제들이 있다.

1. private 생성자를 갖고 있기 때문에 상속할 수 없다.

  • 객체지향의 장점인 상속과 이를 이용한 다형성을 적용할 수 없다.

2. 싱글톤은 테스트하기 힘들다.

  • 싱글톤은 만들어지는 방식이 제한적이기 때문에 테스트에 사용될 때 목 오브젝트 등으로 대체하기가 힘들다.
  • 초기화 과정에서 생성자등을 통해 오브젝트를 다이나믹하게 주입하기도 힘들다.

3. 서버 환경에서 싱글톤이 하나만 만들어지는 것을 보장하지 못한다.

  • 서버에서 클래스 로더를 어떻게 구성하고 있느냐에 따라서 싱글톤 클래스임에도 하나 이상의 오브젝트가 만들어 질 수 있다.

4. 싱글톤의 사용은 전역 상태를 만들 수 있기 때문에 바람직하지 못하다.

  • 아무 객체나 자유롭게 접근하고 수정하고 공유하는 전역 상태를 갖는 것은
    객체지향 프로그래밍에서는 권장되지 않는 프로그래밍 모델이다.

싱글톤 레지스트리

자바의 기본적인 싱글톤 패턴의 구현 방식에는 여러가지 단점이 있기에 스프링은 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공한다. 그것이 바로 싱글톤 레지스트리(singleton registry)다.
싱글톤 레지스트리는 스태틱 메소드와 private 생성자를 사용해야하는 비정상적인 클래스가 아니라 평범한 자바 클래스를 싱글톤으로 활용하게 해준다.

싱글톤과 오브젝트 상태

  • 기본적으로 싱글톤이 멀티스레드 환경에서 서비스 형태의 오브젝트로 사용되는 경우에는 상태정보를 내부에 갖고 있지 않는 무상태(stateless)방식으로 만들어져야 한다.
  • 무상태 방식으로 만들기 위해서는 파라미터와 로컬변수, 리턴값등을 이용하면 된다. 메소드 파라미터나, 메소드 안에서 생성되는 로컬 변수는 매번 새로운 값을 저장할 독립적인 공간이 만들어지기 때문에 싱글톤이라고 해도 여러 스레드 변수의 값을 덮어쓸 일은 없다.
  • 하지만, 자신이 사용하는 다른 싱글톤 빈을 저장하려는 용도라면 인스턴스 변수를 사용해도 좋다. 스프링이 한 번 초기화해주고 나면 이후에는 수정되지 않기 때문에 멀티스레드 환경에서 사용해도 아무런 문제가 없다.

스프링 빈의 스코프

  • 스프링이 관리하는 오브젝트, 즉 빈이 생성되고, 존재하고, 적용되는 범위를 빈의 스코프(scope)라고 한다. 스프링 빈의 기본 스코프는 싱글톤이다.
  • 경우에 따라 싱글톤 외에 다른 스코프를 가질수 있다. (prototype, request, session...)

0개의 댓글