❗️❗️ 개인적인 해석과 생각이 들어갈 수 있어서 잘못된 정보가 있을 수 있습니다! 잘못된 정보는 지적 부탁드립니다!
잘만 실행되는 DAO를 보고 왜 초난강 DAO라고 부르는 걸까?
미래를 생각하지 않는 코드라는 점 현재의 DAO에 변화가 있거나 기능이 추가됐을 때 현재 코드에서 변경되는 부분을 생각해 보자 Connetion 만약 여러 DAO가 있고 메서드가 수백 개일 때 DB를 변경하게 된다면 수백 줄의 Connection 생성 코드를 일일이 바꿔야 하는 불상사가 생길 수 있다.
그럼 이제 초난감 DAO를 나눠보자 크게 나눈다면 아래 3가지로 나눌 수 있다.
이렇게 3가지로 나누어 리팩토링해보자
먼저 메서드로 분리하는 방법도 있을 것이다. 하지만 확장을 좀 더 편리하게 하기 위해서 상속을 통해서 클래스로 코드를 분리해 보자
이렇게 변하는 부분을 따로 서브 클래스로 빼내는 것을 템플릿 메서드 패턴이라고 하고 마찬가지로 dao에서 사용하고 있는 getConnection은 팩토리 메서드 패턴이라고 할 수 있다.
모든 객체는 변한다.
어떻게 확장할것인가??
Connection을 생성해 주는 클래스를 따로 분리하고 DAO가 해당 메서드를 의존하도록 만든다.
상속을 사용하면 되지 굳이 클래스를 분리한 이유는 뭘까?
예를 들어 superDAO에 어떤 메서드가 추가되거나 변경될 시에 하위 DAO에 변경이 일어날 수 있다. 이외에도 상속이 가지는 단점이 있다.
때문에 아예 Connection을 담당하는 클래스로 분리시켜보자
객체지향의 설계 원칙(SOLID)
아직 완성되진 않았지만 초난감 DAO에서 단일 책임 원칙을 지키도록 리팩토링했다고 볼 수 있다.
OCP를 잘 지키면 자연스럽게 응집도는 높아지고 결합 도는 낮아진다.
DAO에서 ConnectionMaker를 의존하도록 설계하고 필요할 때마다 설정을 바꿔서 사용하는 이런 패턴을 전략 패턴이라고 한다. ConnectionMaker의 구체 클래스들은 DAO가 사용할 수 있는 여러 전략들이라고 생각할 수 있다.
제어의 역전이 뭘까?
앞서 봤듯이 DAO 자신이 ConnectionMaker의 구현체를 생성해서 사용할 수 있다. 하지만 지금의 제어권은 DAO가 아닌 다른 제3의 객체가 이를 제어한다.
이렇게 제어의 흐름을 거꾸로 뒤집어놓은 것을 제어의 역전이라고 한다.
TestCode에서 사용하던 DAO 설정을 분리해 DAO를 세팅하고 관계를 설정해 주는 Factory 클래스를 만들어 보자
싱글톤 패턴 : 인스턴스가 오직 1개만 생성되는 패턴
spirng은 별다른 설정을 하지 않으면 대부분의 빈을 싱글톤 스코프로 사용한다
싱글톤 패턴의 단점
그럼 스프링은 왜? 싱글톤 객체로 빈을 생성할까?
보통 spring은 웹같이 멀티 스레드 환경에서 자주 사용되는데 이때 각 request마다 객체를 생성한다면 아마 서버의 자원이 남아나지 않을 것이다.
어떻게 사용해야 할까?
가장 중요한 부분이다. spring에서 빈을 등록할 때 싱글톤으로 등록한다면 static 변수 혹은 인스턴스 변수를 값을 바뀌는 정보를 담는 변수로 사용했다가는 큰일 날 수 있다. 즉 인스턴스가 하나인데 그 인스턴스 변수에 여러 스레드들이 달려들어서 해당 변수의 값을 변경하거나 조회한다면 사용자는 정확한 데이터와 정보를 제공받을 수 없게 된다.
스프링의 싱글톤 레지스트리
앞서본 싱글톤은 private 키워드를 사용해야 하기 때문에 상속이 불가능한대 스프링은 이러한 문제 없이 private 키워드가 아닌 평범한 클래스도 싱글톤으로 사용할 수 있게 스프링이 관리해 준다.
이처럼 싱글톤 레지스트리는 싱글톤 패턴의 단점을 제거하고 객체를 만들고 관리해 주는 역할을 수행한다
런타임 의존관계 설정이란 뭘까 말 그대로 실행될 때 의존관계가 생성된다는 것이다. DAO 입장에서 본다면 코드가 실행되기 전까지는 어떤 ConnectionMaker를 의존할지 전혀 모른다. 제3자에 의해서 의존관계가 설정되기 때문이다.
의존관계 주입의 3가지 조건
의존관계를 사용할 오브젝트는 외부에서 제공해 준다.
DI(의존관계 주입)은 말 그대로 주입받는다는 걸 알겠는데 그럼 검색은 뭘까?
의존관계 검색은 자신이 필요한 의존 오브젝트를 능동적으로 찾는 행위라 할 수 있다.
DL이 필요한 경우는 다음처럼 Test 할 때(getBean) 사용할 수 있다.