개발/java

[Spring 기본] 4. 싱글톤 컨테이너

ebang 2024. 1. 6. 23:05
반응형

4. 싱글톤 컨테이너

1. java는 웹 애플리케이션 서비스 용 언어

  • 요청이 있을 때마다 새로 new 를 해서 객체를 반환하는 문제
    • 클라이언트가 요청할 때 매번 객체가 새로 생긴다
    • 요청을 수행하기 위해 스레드가 하나 생기고, 독립적인 인스턴스가 생기기 때문에 그런 것이다.

2. 싱글톤 패턴

  • 싱글톤 패턴을 이용하여, 하나의 객체를 가지고 요청을 처리하도록 할 수 있다.
    • 생성자 private 화, 그리고 static 멤버 변수로 미리 생성해둔 후 getInstance() 로 반환.

3. 싱글톤 패턴의 문제점

  • 싱글톤 패턴을 구현하는데 코드를 많이 필요로 한다.
  • 의존관계상 클라이언트가 구현체에 의존하게 된다. DIP 위반
    • 따라서 OCP 도 위반하게 된다.
  • 유연한 테스트를 하기 어렵다.
  • 내부 속성을 변경하거나 초기화하기 어렵다.
  • private 생성자를 사용하므로 자식 클래스를 생성하기 어렵다.
  • 결과적으로 효율적인 코드를 작성하기 어렵다.
  • 안티패턴으로도 불린다.

4. 싱글톤 컨테이너

  • 스프링 컨테이너는 위의 싱글톤 패턴의 문제를 모두 해결하면서도, 싱글톤 컨테이너를 유지한다.
    • 스프링 컨테이너가 생길 때 모든 스프링 빈을 등록한다.
      • 이렇게 빈을 생성하고 등록하는 것을 싱글톤 레지스트리라고 부른다.
      • 이렇게 함으로써 OCP, DIP, 테스트, private 생성자로부터 자유로워지게 된다. (직접 코드를 작성하지 않아도 됨.)
  • 싱글톤 방식의 주의점 (매우 중요한 내용!)
    • 여러 클라이언트가 하나의 객체 인스턴스에 의존하기 때문에 상태를 유지하면 안된다.
    • stateless 컨테이너로 만들어야 한다.
      • 특정 클라이언트에 의존적인 필드가 있으면 안된다.
      • 특정 클라이언트가 값을 변경할 수 있는 필드가 있어서는 안된다.
      • 가급적 읽기만 가능해야 한다.
      • 필드 대신 자바에서 공유되지 않는 지역변수, 파라미터, ThreadLocal 등을 사용해야 한다.
    • 발생하는 문제
      • 나의 아이디로 다른 사람의 결제 내역이 보이는 문제 발생
  • @Configuration
    • @Configuration 어노테이션이 붙은 AppConfig는 어떻게 동작하는 걸까?
      • 각 객체를 등록하기 위해 메소드를 호출하면, new MemoryMemberRepository() 는 여러번 호출된다.
        • meberServiceImpl, orderServiceImpl 에서 모두 memberRepository()를 호출하기 때문이다.
  • @Configuration과 바이트 코드
    • AppConfig 클래스를 전달하고 ApplicationContext 구현체 즉 컨테이너가 만들어질 때, CGLIB 라이브러리를 활용해서 AppConfig@CGLIB 클래스가 만들어진다.
    • CGLIB : 바이트코드 조작 라이브러리
    • AppConfig@CGLIB : AppConfig를 상속한 자식 클래스.
      • 메소드 호출 시, 이미 등록된 빈이라면 등록된 빈을 반환하고 그렇지 않으면 기존 로직을 호출해서 반환된 객체를 등록하고 반환하는 로직을 수행할 것이다.
    • @Configuration이 없으면, AppConfig@CGLIB 이 아니라 AppConfig를 통해서 빈 등록이 되는데, 싱글톤으로 관리가 되지 않고 기존 코드가 매번 호출되면서 새로운 객체가 등록된다.
    • 따라서 각 객체가 참조하는 memberRepository 는 애초에 스프링 컨테이너가 관리하는 빈이 아닌 것이다.
반응형