내용을 정리한 글은 워낙 많아서 깨달음을 얻은 부분 위주로 정리했다.
개발자가 객체를 설계할 때 가장 염두에 둬야 할 사항은 바로 미래의 변화를 어떻게 대비할 것인가이다.
- 변경이 일어날 때 필요한 작업을 최소화하고, 그 변경이 다른 곳에 문제를 일으키지 않게 하기 위해서는 설계를 할 때 분리와 확장을 고려해야 한다.
- 변화가 한 번에 한 가지 관심에 집중돼서 일어난다면, 우리가 준비해야 할 일은 한 가지 관심이 한 군데에 집중되게 하는 것이다.
- 하나의 관심사가 방만하게 중복되어 있고, 여기저기 흩어져 있어서 다른 관심의 대상과 얽혀 있으면, 변경이 일어날 때마다 엄청난 고통을 일으키는 원인이 된다.
- UserDao는 Connection 인터페이스 타입의 오브젝트라는 것 외에는 관심을 두지 않는다. → 그저 Connection 인터페이스에 정의된 메서드를 사용할 뿐이다. NUserDao, DUserDao에서 어떤 식으로 Connection 기능을 제공하는지에 관심을 두고 있지 않다.
템플릿 메서드 패턴이란?
- 상속을 통해 슈퍼클래스의 기능을 확장할 때 사용하는 가장 대표적인 방법이다.
- 변하지 않는 기능은 슈퍼클래스에 만들어두고, 자주 확장하거나 변경될 기능은 서브클래스에서 만들도록 한다.
- 슈퍼클래스에는 미리 추상 메서드 또는 오버라이드 가능한 메서드를 정의해 두고, 이를 활용하여 코드의 기본 알고리즘을 담고 있는 템플릿 메서드를 만든다.
- 서브클래스에서는 추상 메서드를 구현하거나, 오버라이드할 수 있도록 만들어둔 훅 메서드를 오버라이딩하여 기능의 일부를 확장한다.
- 훅 메서드 vs 추상 메서드
- 훅 메서드는 선택적으로 오버라이딩이 가능하다.
- 추상 메서드는 반드시 상속받아 구현해야 한다.
팩토리 메서드 패턴이란?
- 템플릿 메서드 패턴과 마찬가지로 상속을 통해 기능을 확장하는 방법이다.
- 이 메서드는 주로 인터페이스 타입으로 오브젝트를 리턴하므로, 서브클래스에서 정확히 어떤 클래스의 오브젝트를 만들어 리턴할지는 슈퍼클래스에서 알 수 없다. 사실 관심도 없다.
- 서브클래스는 다양한 방법으로 오브젝트를 생성하는 메서드를 재정의할 수 있다.
- 서브클래스에서 오브젝트 생성 방법과 클래스를 결정할 수 있도록 미리 정의해 둔 메서드를 팩토리 메서드라고 하며, 이 방식을 통해 나머지 로직을 독립시키는 방법을 팩토리 메서드 패턴이라고 한다.
전략 패턴이란?
- 디자인 패턴의 꽃이라 불릴 만큼 자주 사용되는 패턴이다. 개방 폐쇄 원칙을 가장 잘 실현한 패턴이다.
- 자신의 기능 맥락에서 필요에 따라 자주 변경이 발생하는 기능은 인터페이스를 통해 통째로 분리시키고, 이를 구현한 구체적인 클래스를 바꿔서 사용할 수 있게 하는 디자인 패턴이다.
- 책에서는 DB 연결 방식을 인터페이스로 정의하고, 이를 구체적으로 구현한 클래스를 바꿔가면서 사용할 수 있도록 구현하였다.
프레임워크는 제어의 역전이 적용된 대표적인 기술이다.
- 프레임워크는 라이브러리의 다른 이름이 아니다.
- 라이브러리를 사용하는 애플리케이션 코드는 흐름을 직접 제어한다.
- 프레임워크에는 분명한 제어의 역전 개념이 적용되어 있어야 한다.
- 애플리케이션 코드는 프레임워크가 짜놓은 틀에서 수동적으로 동작해야 한다.
- 스프링은 이러한 IoC를 극한까지 적용하고 있는 프레임워크이다.
오브젝트 팩토리 대신 Application Context를 썼을 때 얻는 이점
- 클라이언트는 구체적인 팩토리 클래스를 알 필요가 없다.
- Application Context는 종합 IoC 서비스를 제공해 준다.
- Application Context는 빈을 검색하는 다양한 방법을 제공한다.
- 여러 번에 걸쳐 빈을 요청하더라도 매번 동일한 오브젝트를 반환한다. 즉, 싱글톤 레지스트리이다.
- 안티 패턴으로 불리는 싱글톤 패턴이지만, 스프링의 싱글톤 레지스트리 덕분에 싱글톤 방식으로 사용될 클래스라도 public 생성자를 가질 수 있다.
- 덕분에 테스트 환경에서 자유롭게 오브젝트를 만들 수 있다.
싱글톤과 멀티스레드 환경에 따른 상태 관리 주의점
- 싱글톤이 멀티스레드 환경에서 서비스 형태의 오브젝트로 사용된다면, 상태 정보를 내부에 담고 있지 않은 무상태 방식으로 만들어져야 한다.
- 다중 사용자의 요청을 한꺼번에 처리하는 스레드들이 동시에 싱글톤 오브젝트의 변수에 접근하는 것은 매우 위험하다.
- 때문에 싱글톤은 기본적으로 인스턴스 필드의 값을 변경하고 유지하는 상태 유지 방식으로 만들지 않는다.
- 메서드 파라미터나 메서드 안에서 생성되는 로컬 변수를 활용하면 독립적인 저장 공간이 만들어지기 때문에 여러 스레드가 변수의 값을 덮어쓸 일은 없다.
- 또는 읽기 전용의 속성을 가진 정보라면 인스턴스 변수로 사용해도 괜찮다.
- 스프링 빈의 기본 스코프는 싱글톤이며, 컨테이너 내에 한 개의 오브젝트만 만들어져 강제로 제거되지 않는 한 스피링 컨테이너가 존재하는 동안 계속 유지된다.
DI의 조건
- 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. 오직 인터페이스에 의존해야 한다.
- 런타임 시점의 의존관계는 컨테이너 같은 제3의 존재가 결정한다.
- 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 주입해 줌으로써 만들어진다.
DI의 장점
- 런타임 전까지는 코드에 의존관계가 나타나지 않기 때문에 결합도가 낮다.
- 의존관계에 있는 (다른 책임을 가진) 대상이 변경되더라도 영향을 받지 않는다.
'Book > 토비의 스프링' 카테고리의 다른 글
[토비의 스프링] 다이내믹 프록시를 이해해보자 (0) | 2024.04.23 |
---|---|
[토비의 스프링] 4장 예외 (0) | 2024.04.18 |
[토비의 스프링] 3장 템플릿 (0) | 2024.04.18 |
[토비의 스프링] 2장 테스트 (0) | 2024.04.16 |