Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions ch1/1장_오브젝트와 의존 관계.md
Original file line numberDiff line numberDiff 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