Skip to content
Open
113 changes: 113 additions & 0 deletions ch1/1장_오브젝트와 의존 관계.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# 1장 오브젝트와 의존 관계
스프링을 사용하는 개발자들이 스프링을 통해 얻게 되는 두 가지 중요한 가치
- 단순함(Simplicity): 스프링은 자바의 잃어버린 본질인 객체지향 언어라는 특징을 다시 살릴 수 있도록 도와주는 도구, POJO 프로그래밍
- 유연성(Flexibility): 많은 프레임워크와 편리하게 접목하여 사용할 수 있음

스프링의 철학 ?
```항상 프레임워크 기반의 접근 방법을 사용하라```

## 1.1 초난감 DAO
사용자 정보를 JDBC API 를 통해 DB 에 저장하고 조회할 수 있는 간단한 DAO 를 만든다.
````
DAO(Data Access Object): DB 를 사용해 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 오브젝트를 말한다.
````

해당 코드의 문제점이 있다고 한다. 물론 기능은 정상적으로 동작한다. 근데 왜 이 코드에 문제가 많다고 하는 걸까 ? 잘 동작하는 코드를 굳이 수정하고 개선해야 하는 이유가 뭘까 ? 그렇게 DAO 코드를 개선했을 때의 장점은 무엇일까 ? 그런 장점들이 당장에, 또는 미래에 주는 유익은 무엇일까 ? 또 객체지향 설계의 원칙과는 무슨 상관이 있을까 ? 이 DAO 를 개선하는 경우와 그대로 사용하는 경우, 스프링을 사용하는 개발에서 무슨 차이가 있을까 ?
-> 스프링을 공부한다는 것은 바로 이런 문제 제기와 의문에 대한 답을 찾아나가는 과정이다.

## 1.2 DAO 의 분리
변화가 한 번에 한 가지 관심에 집중되어 일어난다면, 우리가 준비해야 할 일은 한 가지 관심이 한 군데에 집중되게 하는 것이다.
즉, 관심이 같은 것끼리는 모으고, 관심이 다른 것은 따로 떨어져 있게 하는 것이다.
```
관심사의 분리(Separation of Concerns)
관심이 같은 것끼리는 하나의 객체 안으로 또는 친한 객체로 모이게 하고,
관심이 다른 것은 가능한 한 따로 떨어져서 서로 영향을 주지 않도록 분리하는 것이다.
```

DB 커넥션을 가져오는 코드가 여기저기에 계속 중복되어 나타난다. 이렇게 하나의 관심사가 방만하게 중복되어 있고, 여기저기 흩어져 있어서 다른 관심의 대상과 얽혀 있으면, 변경이 일어날 때 엄청난 고통을 일으키는 원인이 된다. 지저분하게 꼬여 있는 스파게티 코드가 된다는 뜻이다.
이 경우 커넥션을 가져오는 중복된 코드를 분리하는 것으로 해결할 수 있다.
```
메소드 추출(Extract Method)
공통의 기능을 담당하는 메소드로 중복된 코드를 뽑아내는 것을 리팩토링에서는 메소드 추출 기법이라고 부른다.
```

위와 같이 메소드 추출을 진행하면 어느 정도의 문제 해결이 된다. 하지만 사용하는 DB 를 다르게 사용하는 경우는 어떻게 해야 하는가 ?
`getConnection()` 메소드를 abstract method 로 수정하고, 그 구현부를 상속받아 구현하는 식으로 리팩토링을 진행한다.
```
템플릿 메소드 패턴(Template Method Pattern)
수퍼클래스에 기본적인 로직의 흐름을 만들고, 그 기능의 일부를 추상 메소드나 오버라이딩이 가능한 protected 메소드 등으로 만든 뒤
서브클래스에서 이런 메소드를 필요에 맞게 구현해서 사용하도록 하는 방법
```

이때 DAO 의 `getConnection()` 메소드는 어떤 Connection 클래스를 생성할지 경정하는 방법이라고 볼 수 있다. 이를 팩토리 메소드 패턴이라 한다.
```
팩토리 메소드 패턴(Factory Method Pattern)
템플릿 메소드 패턴과 원리는 같으나, 서브클래스에서 구체적인 오브젝트 생성 방법에 대해 결정하게 하는 방법
```

위의 방법들로 관심사항이 다른 코드를 분리해내고, 서로 독립적으로 변경 또는 확장할 수 있도록 만드는 것은 간단하면서도 매우 효과적인 방법이다. 그러나 여전히 다음과 같은 문제가 남아있다.
1. DAO 로직을 어떻게 만들 것인가 ? (상속은 문제가 발생한다)
2. DB 커넥션을 생성하는 코드를 다른 DAO 클래스에 적용할 수 없다.

## 1.3 DAO 의 확장
현재 UserDao 는 관심사가 너무 많다.
- `UserDao` 는 사실 어떤 DB 를 사용하는지 관심 없다.
- DB 에서 데이터만 가져오면 된다.
- 따라서 DB 를 연결하는 부분을 아예 다른 클래스로 분리해보자.

그렇게 클래스가 구현되어 의존관계에 있게 되었고, 더 유연한 관계를 위해 도입된 것이 인터페이스이다.

### 1.3.2 인터페이스의 도입
인터페이스는 어떤 일을 하겠다는 기능만 정의해놓은 것이다. 따라서 인터페이스에는 어떻게 하겠다는 구현 방법은 나타나 있지 않다. 그것은 인터페이스를 구현한 클래스들이 알아서 결정할 일이다. UserDao 가 인터페이스를 사용하게 한다면 인터페이스의 메소드를 통해 알 수 있는 기능에만 관심을 가지면 되지, 그 기능을 어떻게 구현했는지에는 관심을 둘 필요가 없다.

### 1.3.3 원칙과 패턴
```
개방 폐쇄 원칙(OCP, Open-Closed Principle)
클래스나 모듈은 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다
- UserDao 의 경우 인터페이스를 구현한 어떤 구현체든 생성자에 주입할 수 있으니 확장에 열려 있음
- UserDao 의 경우 자신의 핵심 기능을 구현한 코드는 그런 변화에 영향을 받지 않고 유지할 수 있으므로 변경에 닫혀 있음
```

```
객체지향 설계 원칙(SOLID)
1. SRP(The Single Responsibility Principle): 단일 책임 원칙
2. OCP(The Open-Closed Principle): 개방 폐쇄 원칙
3. LSP(The Liskov Substitution Principle): 리스코프 치환 원칙
4. ISP(The Interface Segregation Principle): 인터페이스 분리 원칙
5. DIP(The Dependency Inversion Principle): 의존관계 역전 원칙
```
-> 공부, 정리 다시 필요,,

1. 높은 응집도
- 어떤 한 관심사를 한 클래스에 모아놓은 것이다.
- 변경이 일어날 때 모듈의 많은 부분이 함께 바뀐다면 응집도가 높다고 말할 수 있다.
2. 낮은 결합도
- 느슨하게 연결된 형태를 유지하는 것이 바람직하다.
-- 클래스와 클래스를 연결할 떄, 인터페이스를 활용하는 것이 느슨한 결합에 유리하다.

**전략 패턴**
위에서 작성했던 구조가 전략 패턴이라 한다. OCP 에도 적합하다.

## 1.4 제어의 역전(IoC)
```
Ioc(Inversion of Control)
```
지금까지 리팩토링한 Dao 에서 개선을 할 사항이 남아 있다. 바로 Dao 를 사용하는 클라이언트가 문제다.
클라이언트는 기존에 Dao 가 직접 담당하던 기능이었던 ** ConnectionMaker 구현 클래스** 를 떠맡고 있다.

팩토리
위의 두 기능을 DaoFactory 라는 객체를 새로 만들어 맡기자.
```
팩토리(Factory)
분리시킬 기능을 담당할 클래스의 역할은 객체의 생성 방법을 결정학고 그렇게 만들어진 오브젝트를 돌려 주는 것인데, 이런 일을 하는 오브젝트를 팩토리라 한다.
```

클라이언트는 팩토리 객체를 통해 Dao 를 생성할 것이고, 이를 통해 두 가지 기능이 분리되었다.
UserDao 와 ConnectionMaker 는 각각 애플리케이션의 핵심적인 데이터 로직과 기술 로직을 담당하고 있고, DaoFactory 는 이런 애플리케이션의 오브젝트들을 구성하고 그 관계를 정의하는 책임을 맡고 있음을 알 수 있다.
즉, 전자는 실질적인 로직을 담당하는 컴포넌트라면, 후자는 애플리케이션을 구성하는 컴포넌트의 구조와 관계를 정의한 설계도 같은 역할을 한다고 볼 수 있다.

### 1.4.2 오브젝트 팩토리의 활용
DaoFactory 에서 여러 Dao 를 생성한다면 어떻게 되나 ?
각 팩토리 메소드마다 ConnectionMaker 을 생성하는 코드가 중복되어 나타난다. 코드 중복이 발생하면 이 코드를 수정할 때 의미없이 반복적으로 같은 코드를 수정해야 하기 때문에 이 부분 역시 DaoFactory 안의 새로운 메소드로 빼내는 것이 좋다.


Loading