개요
스프링을 이해하려면 오브젝트에 관심을 가져야 한다.
오브젝트가 생성되고, 관계를 맺고, 소멸되기까지의 과정을 이해하고 생각해야 한다.
더 나아가 오브젝트가 어떻게 설계되고, 어떤 단위로 만들어지는지, 언제 존재를 나타내는지에 대해서도 살펴봐야 한다.
스프링은 이러한 오브젝트를 누구나 솝쉽게 적용할 수 있도록 프레임워크 형태로 제공한다.
그리고 객체는 항상 변화한다. 그리고 개발자는 변화하는 객체를 위해 미래지향적으로 설계를 해야한다.
객체에 대한 작업이 한 곳에 집중될 경우 매번 분리와 확장에 골머리를 썩을 수 있다.
그래서 관심사의 분리가 필요하고, 그 관심사의 분리를 위해 알아야할 몇가지가 있다.
인터페이스
- 클래스 간 서로 긴밀하게 연결되지 않도록 중간에 추상적인 연결고리를 만들어 주는것
- 자신을 구현할 클래스에 대한 구체적인 정보는 감춰야함
- 어떤 것을 하겠다는 기능만 정의해 놓은 것 -> 즉, 어떻게 구현하겠다는 것은 명시되어 있지 않음
* 추상화
공통적인 성격을 뽑아내여 따로 분리하는 작업
관심사의 분리 예제
가정.
- UserDao: 유저 정보를 담은 도메인 존재
- DbConnection: DB 커넥션을 설정하는 Config 존재
UserDao에서 DbConnection과의 관계를 설정하는 메소드가 있다면, 이것은 독립적으로 확장 가능한 클래스가 아니다.
이는 어떻게 분리할 수 있을까?
UserDao의 클라이언트 오브젝트에서 DbConnection과 UserDao의 관계를 결정하는 기능을 두는 것이다.
이렇게 되면 UserDao와 DbConnection 사이의 기능을 완전히 분리시킬 수 있다.
방법.
1. 서비스의 파라미터로 인터페이스를 받게함
2. 서비스의 클라이언트에서 인터페이스의 구현체를 생성
3. 그 구현체를 서비스를 생성하면서 파라미터로 넘겨주는 것
왜 이러한 관심사의 분리가 필요한가?
높은 확장성을 지니기 위해서이다.
생각해보자. 만약, UserDao 생성자에특정 DB와의 커넥션을 생성하도록 구현되어 있다면 다른 도메인들을 생성할때마다 DB 커넥션 관련 코드를 작성해야한다.
이는 중복 코드를 유발하고, 낮은 유지보수성을 가지게 된다.
OCP (개방 폐쇄의 원칙)
SOLID 원칙 중에 하나
(SRP - 단일 책임 원칙, OCP, LSP - 리스코프 치환 법칙, ISP - 인터페이스 분리 법칙, DIP - 의존관계 역전 원칙)
클래스나 모듈의 확장은 열려있어야 하고, 변경에는 닫혀 있어야한다.
위의 예시를 보면, 클라이언트에서 Db커넥션 구현체를 늘렸을 때, UserDao의 도메인에는 전혀 영향을 주지않게 된다.
이러한 특징을 우리는 높은 응집도와 낮은 결합도와 연관 지을 수 있다.
높은 응집도
변화가 일어날 때 모듈에서 변하는 부분이 크다.
즉, 변경이 일어날 때 모듈의 많은 부분이 함께 바뀐다면 응집도가 높다고 할 수 있다.
만약, 도메인 내부 응집도가 낮다면 문제가 발생했을 때 일일이 디버깅해야하는 귀찮은 일이 생긴다.
예를 들어, 빵을 주문하는 서비스 하나에
- 빵 재고 확인
- 빵 상태 확인
- 빵 주문
각 서비스가 낮은 응집도를 지닌다면 빵의 주문 시스템이 변경될 때마다 일일이 수정사항을 찾아 나가야 할 것이다.
낮은 결합도
책임과 관심사가 타 모듈과 낮은 결합도를 가지게 되는 것. 즉, 느슨한 연결 형태.
그래서 구현체들은 독립적이며, 서로 알 필요가 없어지게 된다.
그래서 높은 확장성을 지니게 된다.
이는 위의 예제에서 나타내고 있다.