인생을 코딩하다.

[토비의 스프링 1장 정리] 오브젝트와 의존관계 본문

Spring

[토비의 스프링 1장 정리] 오브젝트와 의존관계

Hyung1 2021. 6. 4. 20:56
728x90
반응형

1장, 오브젝트와 의존관계

p.64)

  • 프로그래밍 기초 개념 중에 관심사의 분리라는 게 있다. 이를 객체지향에 적용해보면, 관심이 같은 것끼리는 하나의객체 안으로 또는 친한 객체로 모이게 하고, 관심이 다른 것은 가능한 한 따로 떨어져서 서로 영향을 주지 않도록 분리하는 것이라고 생각할 수 있다.
  • 리팩토링은 기존의 코드를 외부의 동작방식에는 변화 없이 내부 구조를 변경해서 재구성하는 작업 또는 기술을 말한다.
  • 공통의 기능을 담당하는 메소드로 중복된 코드를 뽑아내는 것을 리팩토링에서는 메소드 추출 기법이라고 부른다.

p.67)

  • 기능의 일부를 초상 메소드나 오버라이딩이 가능한 protected 메소드 등으로 만든 뒤 서브 클래스에서 이런 메소드를 필
    요에 맞게 구현해서 사용하도록 하는 방법을 디자인 패턴에서 템플릿 메소드 패턴이라고 한다.
  • 서브클래스에서 구체적인 오브젝트 생성 방법을 결정하게 하는 것을 팩토리 메소드 패턴이라고 부르기도 한다.

p.69)

디자인 패턴은 소프트웨어 설계 시 특정 상황에서 자주 만나는 문제를 해결하기 위해 사용할 수 있는 재사용 가능한
솔루션을 말한다.

  • 확장성 추구 방법이 대부분 두 가지 구조로 정리되기 떄문이다. 하나는 클래스 상속이고 다른 하나는 오브젝트 합성이다.

템플릿 메소드 패턴

  • 상속을 통해 슈퍼클래스의 기능을 확장할 떄 사용하는 가장 대표적인 방법이다.
  • 슈퍼클래스에서 디폴트 기능을 정의해두거나 비워뒀다가 서브클래스에서 선택적으로 오버라이드를 할 수 있도록 만들어둔
    메소드를 훅 메소드라고 한다. 서브클래스에서는 추상 메소드를 구현하거나. 훅 메소드를 오버라이드 하는 방법을 이용해 기능
    의 일부를 확장한다.
    public void templateMethod() {
          // 기본 알고리즘 코드
          hookMethod()
          abstractMethod();
          }
    기본 알고리즘 골격을 담은 메소드를 템플릿 메소드라 부른다. 템플릿 메소드는 서브클래스에서 오버라이드하거나 구현할 메소드를
    사용한다.

팩토리 메소드 패턴

  • 서브클래스에서 오브젝트 생성 방법과 클래스를 결정할 수 있도록 미리 정의해둔 메소드를 팩토리 메소드라 하고,
    이 방식을 통해 오브젝트 생성 방법을 나머지 로직, 즉 슈퍼클래스의 기본 코드에서 독립시키는 방법을 팩토리 메소드 패턴
    이라고 한다.

p.83 ~ 87)

개방 폐쇄 원칙(OCP, Open-Closed Principle)

  • 클래스나 모듈은 확장에는 열려 있어야 하고 변경에는 닫혀있어야 한다.

객체지향 설계 5원칙(SOLID)

객체지향 설계 원칙은 객체지향의 특징을 잘 살릴 수 있는 설계의 특징을 말한다.

  • SRP(The Single Respnsibility Principle) : 단일 책임의 원칙
  • OCP(THE Open CLosed Principle) : 개방 폐쇄 원칙
  • LSP(The Liskov Subsitution Principle) : 리스코프 치환 원칙
  • ISP(The Interface Segregation Principle) : 인터페이스 분리 원칙
  • DIP(The Dependency Inversion Principle) : 의존관계 역전 원칙

낮은 응집도와 낮은 결합도

응집도가 높다는 건 하나의 모듈 ,클래스가 하나의 책임 또는 관심사에만 집중되어 있다는 뜻이다.

  • 높은 응집도
    • 변화가 일어날 떄 해당 모듈에서 변하는 부분이 크다는 것으로 설명할 수 있다. 즉 변경이 일어날 때 모듈의 많은
      부분이 함께 바뀐다면 응집도가 높다고 말할수 있다.
  • 낮은 결합도
    • 낮은 결합도란 결국, 하나의 변경이 발생할 때 마치 파문이 이는 것처럼 여타 모듈과 객체로 변경에 대한
      요구가 전파되지 않는 상태를 말한다.

전략 패턴

전략패턴은 자신의 기능 맥락에서, 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통쨰로 외부로 분리시키고, 이를
구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔서 사용할 수 있게 하는 디자인 패턴이다.

  • 컨텍스트는 자신의 기능을 수행하는데 필요한 기능 중에서 변경 가능한, DB 연결 방식이라는 알고리즘을 ConnectionMaker라는
    인터페이스로 정의하고, 이를구현한 클래스, 즉 전략을 바꿔가면서 사용할 수 있게 분리했다.

p.88)

팩토리

  • 이 클래스의 역할은 객체의 생성 방법을 결정하고 그렇게 만들어진 오브젝트를 돌려주는 것인데, 이런 일을 하는 오브젝트를흔히 팩토리라고 부른다.
  • 디자인 패턴에서 말하는 특별한 문제를 해결하기 위해 사용되는 추상 팩토리 패턴이나, 팩토리 메서드 페턴과는 다르니 혼동 X
  • 단지 오브젝트를 생성하는 쪽과 생성된 오브젝트를 사용하는 쪽의 역할과 책임을 깔끔하게 분리하려는 목적으로 사용하는 것이다.

제어의 역전

  • 제어의 역전에서 자신이 사용할 오브젝트를 스스로 선택하지 않는다. 당연히 생성하지도 않는다. 또 자신도 어떻게 만들어지고 어디서 사용되는지를 알 수 없다. 모든 제어 권한을 자신이 아닌 다른 대상에게 위임하기 떄문이다.
  • 서블릿에 대한 제어 권한을 가진 컨테이너가 적절한 시점에 서블릿 클래스의 오브젝트를 만들고 그 안의 메소드를 호출한다.
  • 제어권을 상위 템플릿 메소드에 넘기고 자신은 필요할 때 호출되어 사용한다. 템플릿 메소드는 제어의 역전이라는 개념을 활용해 문제를 해겨하는 디자인 패턴이라고 볼 수 있다.
  • 라이브러리를 사용하는 애플리케이션의 코드는 애플리케이션의 흐름을 직접 제어한다. 단지 동작하는 중에 필요한 기능이 있을 때 능동적으로 라이브러리를 사용할 뿐이다.
  • 반면에 프레임워크는 거꾸로 애플리케이션 코드가 프레임워크에 사용된다. 보통 프레임워크 위에 개발한 클래스를 등록 해두고, 프레임 워크가 흐름을 주도하는 중에 개발자가 만든 애플리케이션 코드를 사용하도록 하는 방식이다.

p.95)

  • 스프링에서는 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트를 빈이라고 부른다. 자바빈 또는 엔터프라이즈 자바 빈에서 말하는 빈과 비슷한 오브젝트 단위의 애플리케이션 컴포넌트를 말한다.
  • 동시에 스프링 빈은 스프링 컨테이너가 생성과 관계설정, 사용 등을 제어해주는 제어의 역전이 적용된 오브젝트를 가리키는 말이다.

빈 팩토리

  • 스프링에서는 빈의 생성과 관계설정 같은 제어를담당하는 IoC 오브젝트를 빈 팩토리라고 부른다.

애플리케이션 컨텍스트

  • 애플리케이션 컨텍스트라고 말할 떄는 애플리케이션 전반에 걸쳐 모든 구성요소의 제어 작업을담당하는 IoC 엔진이라라고 간단하게 말할 수 있다.
  • 별도의 정보를 참고해서 빈(오브젝트)의 생성, 관계설정 등의 제어 작업을 총괄한다.

p.97)

ApplicationContext를 구현한 클래스는 여러 가지가 있는데 @Configuration이 붙은 자바 코드를 설정 정보로
사용하려면 ApplicationConfigApplicationContext를 이용하면 된다.

  • 이렇게 준비된 ApplicationContext의 getBean()이라는 메소드를 이용해 오브젝트를 가져올 수 있다.
  • getBean() 메소드는 ApplicationContext가 관리하는 오브젝트를 요청하는 메소드다.
  • @Bean이라는 애노테이션을 userDao라는 이름의 메소드에 붙였는데, 이 메소드 이름이 바로 빈의 이름이 된다.
  • 메소드의 이름을 myPreciousUserDao()라고 헀다면 getBean("myPreciousUserDao". UserDao.class)로 가져올 수 있다.

그런데 UserDao를 가져오는 메소드는 하나뿐인데 왜 굳이 이름을 사용할까? 그것은 UserDao를 생성하는 방식이나 구성을 다르게 가져가는 메소드를 추가할 수 잇기 떄문이다. 그때는 specialUserDao()라는 메소드로 만들고 getBean("specialUserDao", UserDao.class)로 가져오면 된다.

p.99)

스프링에서는 이 애플리케이션 컨텍스트를 IoC컨테이너라 하기도 하고, 간단히 스프링 컨테이너라고 부르기도 한다. 또는 빈 팩토리라고 부를 수도 있다. 애플리케이션 컨텍스트는 ApplicationContext 인터페이스를 구현하라는데,

 

ApplicationContext는 빈 팩토리가 구현하는 BeanFactory 인터페이스를 상속했으므로 애플리케이션 컨텍스트는 일종의 빈 팩토리인 셈이다. 애플리케이션 컨텍스트가 스프링의 가장 대표적인 오브젝트이므로, 애플리케이션 컨텍스트를 그냥 스프링이라고 부르는 개발자도 있다.

 

@Configuration이 붙은 클래스는 이 애플리케이션 컨텍스트가 활용하는 IoC 설정정보다.

오브젝트 팩토리로 직접 사용했을 떄와 비교해서 애프리케이션 컨텍스트를 사용했을 때 얻을 수 있는 장점은 다음과 같다.

  • 클라이언트는 구체적인 팩토리 클래스를 알 필요가 없다.
    • 클라이언트가 필요한 오브젝를 가져오렴려면 어떤 팩토리 클래스를 사용해야할지 알아야 하고, 필요할 때마다
      팩토리 오브젝트를 생성해야하는 번거로움이 있다. 애플리케이션 컨텍스트를 사용하면 오브젝트 팩토리가 아무리 많아져도 이를 알아야 하거나 직접 사용할 필요가 없다.
  • 애플리케이션 컨텍스트는 종합 IoC 서비스를 제공해준다.
    • 애플리케이션 컨텍스트의 역할은 단지 오브젝트 생성과 다른 오브젝트와의 관계설정만이 전부가 아니다. 오브젝트가 만들어지는 방식, 시점과 전략을 다르게 가져갈수도 있고, 이에 부가적으로 자동생성, 오브젝트에 대한 후처리, 정보의 조합, 설정 방식의 다변화, 인터셉팅 등 오브젝트를 효과적으로 활용할 수 있는 다양한 기능을 제공한다.(부가적인 기능)
  • 애플리케이션 컨텍스트는빈을 검색하는 다양한 방법을 제공한다.
    • getBean() 메소드를 이용해 빈의 이름이나 타입만으로 빈을 검색하는 것이 가능.

p. 101)

스프링 IoC 용어 정리

  • 빈 또는 빈 오브젝트는 스프링이 IoC 방식으로 관리하는 오브젝트라는 뜻이다. 관리 되는 오브젝트라고 부르기도 한다. 스프링을 사용하는 애플리케이션에서 만들어지는 모든 오브젝트가 다 빈은 아니고 그 중에 스츠링이 직접 그 생성과 제어를 담당하는 오브젝트만을 빈이라고 부른다.

빈 팩토리

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

애플리케이션 컨텍스트

  • 빈 팩토리를 확장한 IoC 컨테이너다. 빈을 등록하하고 관리하는 기본적인 기능은 빈 팩토리와 동일하다.
  • 여기에 스프링이 제공하는 각종 부가 서비스를 추가로 제공한다.(빈 팩토리말고 애플리케이션 컨텍스트를 사용하는 이유)
  • IoC 방식으로 빈을 관리한다는 의미에서 애플리케이션 컨텍스트나 빈 팩토리를 컨테이너 또는 IoC 컨테이너라고도 한다.
    그냥 컨테이너 또는 스프링 컨테이너라고 할 때는 애플리케이션 컨텍스트를 가리키는 것이라고 보면 된다.

설정정보

  • 애플리케이션 컨텍스트가 IoC를 적용하기 위해 사용하는 메타정보로, 컨테이너의 어떤 기능을 세팅하거나 조정하는
    경우에도 사용하지만 보통 IoC 컨테이너에 의해 관리되는 객체를 생성하고 구성할 때 사용된다.

컨테이너 또는 IoC 컨테이너

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

p.102 ~ 111)

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

 

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

 

두 개의 오브젝트가 동일하다면 사실은 하나의 오브젝트만 존재하는 것이고 두 개의 오브젝트 레퍼런스 변수를 갖고 있을 뿐이다.


두 개의 오브젝트가 동일하지는 않지만 동등한 경우에는 두 개의 각기 다른 오브젝트가 메모리상에 존재하는 것인데, 오브젝트의 동등성 기준에 따라 두 오브젝트의 정보가 동등하다고 판단하는 것일 뿐이다. 물론 동일한 ㅇ브젝ㅌ는 동등하기도 할 것이다. 그 반대는 항상 참은 아니다.

 

자바 클래스를 만들 때 equals() 메소드를 따로 구현하지 않았다면, 최상위 클래스인 Object 클래스에 구현되어 있는 equals()메소드가 사용된다. Object의 equals() 메소드는 두 오브젝트의 동일성을 비교해서 그 결과를 돌려준다. 따라서 이떄는 동일한 오브젝트여야지만 동등한 오브젝트라고 여겨질 것이다.

 

오브젝트 팩토리와 스프링 애플리케이션 컨텍스트 동작방식의 차이

  • 오브젝트 팩토리는 getBean()을 실핼할 떄마다 매번 new에 의해 새로운 객체가 만들어진다.
  • 스프링은 여러 번에 걸쳐 빈을 요청하더라도 매번 똑같은 오브젝트를 돌려준다.

왜 일까?


애플리케이션 컨텍스트는 싱글통을 저장하고 관리하하는 싱글톤 레지스트리이기 떄문이다.

 

싱글톤 사용 이유

 

매번 클라이언트에 요청이 올 때마다 각 로직을 담당하는 오브젝트를 새로 만들어서 사용한다고 가정해보자.


요청 한 번에 5개의 오브젝트가 새로 만들어지고 초당 500개의 요청이 들어오면, 초당 2500개의 새로운 오브젝트가 생성된다.


1분이면 십오만 개, 한 시간이면 9백만 개의 새로운 오브젝트가 만들어진다. 아무리 자바의 오브젝트 생성과 가비지 컬렉션의 성능이 좋아졌다고 한들 이렇게 부하가 걸리면 서버가 감당하기가 힘들다.

 

서블릿은 대부분 멀티스레드 환경에서 싱글톤으로 동작한다. 서블릿 클래스당 하나의 오브젝트만 만들어두고, 사용자의 요청을 담당하는 여러 스레드에서 하나의 오브젝트를 공유해 동시에 사용한다.

 

싱글톤 패턴

 

싱글톤 패턴은 어떤 클래스를 애플리케이션 내에서 제한된 인스턴스 개수, 이름처럼 주로 하나만 존재하도록
강제하는 패턴이다. 이렇게 만들어지는 클래스의 오브젝트는 애플리케이션 내에서 전역적으로 접근이 가능하다. 단일 오브젝트만 존재해야 하고, 이를 애플리케이션 여러 곳에서 공유하는 경우에 주로 사용한다.

 

하지만 싱글톤 패턴에는 다음과 같은 문제점이 있다.

  • private 생성자를 갖고 있기 때문에 상속할 수 없다.
    • 객체지향적인 설계의 장점을 적용하기가 어렵다. 또한 상속과 다형성 같은 객체 지향의 특징이 적용되지 않는
      스태틱 필드와 메소드를 사용하는 것도 역시 동일한 문제를 발생시킨다.
  • 싱글톤은 테스트하기가 힘들다
    • 싱글톤은 만들어지는 방식이 제한적이기 떄문에 테스트에서 사용될 때 목 오브젝트 등으로 대체하기가 힘들다.
    • 싱글톤은 초기화 과정에서 생성자 등을 통해 사용할 오브젝트를 다이나믹하게 주입하기도 힘들기 때문에 필요한 오브젝트는
      직접 오브젝트를 만들어 사용할 수 밖에 없다.
  • 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다.
  • 싱글톤 사용은 전역적인 상태를 만들 수 있기 떄문에 바람직하지 못하다.
    • 싱글톤을 사용하는 클라이언트가 정해져 있지 않다. 싱글톤의 스태틱 메소드를 이용해 언제든지 싱글톤에 쉽게
      접근할 수 있기 때문에 애플리케이션 어디서든지 사용될 수 있고, 그러다보면 자연스럽게 전역 상태로 사용되기 쉽다. 전역상태를 갖는 것은 객체지향 프로그래밍에서는 권장되지 않는 프로그래밍 모델이다.

싱글톤 레지스트리 자바의 기본적인 싱글톤 패턴의 구현 방식은 여러 가지 단점이 있기 때문에, 스프링은 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공한다. 그것이 바로 싱글톤 레지스트리다.

  • 싱글톤 레지스트리의 장점은 스태틱 메소드와 private 생성자를 사용해야하는 비정상적인 클래스가 아니라 평범한 자바 클래스를 싱글 튼으로 활요앟게 해준다는 점이다.
  • 스프링의 싱글톤 레지스트리 덕분에 싱글톤 방식으로 사용될 애플리케이션 클래스라도 public 생성자를 가질 수 있다. 싱글톤으로 사용돼야 하는 환경이 아니라면 간단히 오브젝트를 생성해서 사용할 수 있다. 따라서 테스트 환경에서 자유롭게 오브젝트를 만들 수 있고, 테스트를 위한 목 오브젝트로 대체하는 것도 간단하다.

스프링이 빈을 싱글톤으로 만드는 것은 결국 오브젝트의 생성 밥법을 제어하는 IoC 컨테이너로서의 역할이다.

 

싱글톤과 오브젝트의 상태

 

기본적으로 싱글톤이 멀티스레드 환경에서 서비스 형태의 오브젝트로 사용되는 경우에는 상태정보를 내부에 갖고 있지 않은 무상태 방식으로 만들어져야 한다.

  • 다중 사용자의 요청을 한꺼번에 처리하는 스레드드들이 동시에 싱글톤 오브젝트의 인스턴스 변수를 수정하는 것은 매우 위험하다.
    저장될 곤간이 하나뿐이니 서로 값을 덮어쓰고 자신이 저장하지 않은 값을 일겅올 수 있기 떄문이다. 따라서 싱글톤은 기본적으로 인스턴스 필드의 값을 변경하고 유지하는 상태유지 방식으로 만들지 않는다.

스프링의 싱글톤 빈으로 사용되는 클래스를만들 떄는 기존 UserDao처럼 개별적으로 바뀌는 정보는 로컬 변수로 정의하거나, 파라미터로 주고 받으면서 사용하게 해야한다.

  • 인스턴스 변수는 외부 API에 의해 바뀔 가능성이 있다.
    • 하지만 동일하게 읽기전용의 속성을 가진 정보라면 싱글톤에서 인스턴스 변수로 사용해도 좋다.
728x90
반응형
Comments