From 07fd09ee6757f6ddba6ff69706822a530e4d922f Mon Sep 17 00:00:00 2001 From: taekkykim Date: Tue, 27 Apr 2021 17:57:24 +0900 Subject: [PATCH] # modified --- st.md | 114 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/st.md b/st.md index ac8b41d..34db40c 100644 --- a/st.md +++ b/st.md @@ -1,21 +1,21 @@ -#1.오브젝트와 의존 관계 +# 1.오브젝트와 의존 관계 ## 1.1 -####스프링은 자바를 기반으로 한 기술, 가장 중요하게 가치를 두는 것은 객체 지향 프로그래밍이 가능한 언어라는 점. -####스프링이 가장 관심을 두는 대상은 오브젝트. 그렇기 때문에 오브젝트의 기술적인 특징과 사용방법을 넘어 오브젝트의 설계로 발전하게됨. -####객체지향설계의 기초와 원칙을 비롯하여 다양한 목적을 위해 재활용 가능한 설계 방법인 디자인 패턴, 리팩토링, 테스트와 같은 오브젝트 설계와 구현에 관한 기술, 지식이 요구됨 - -###DAO(DATA ACCESS OBJECT) -####DB를 이용해 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 오브젝트 -###자바빈(JAVA Bean) -####원래 비주얼 툴에서 조작가능한 컴포넌트를 말하나, 요즘은 비주얼 컴포넌트라기보다는 다음 두 가지 관례를 따라 만들어진 오브젝트를 가리키며 간단히 빈이라고도 한다. +#### 스프링은 자바를 기반으로 한 기술, 가장 중요하게 가치를 두는 것은 객체 지향 프로그래밍이 가능한 언어라는 점. +#### 스프링이 가장 관심을 두는 대상은 오브젝트. 그렇기 때문에 오브젝트의 기술적인 특징과 사용방법을 넘어 오브젝트의 설계로 발전하게됨. +#### 객체지향설계의 기초와 원칙을 비롯하여 다양한 목적을 위해 재활용 가능한 설계 방법인 디자인 패턴, 리팩토링, 테스트와 같은 오브젝트 설계와 구현에 관한 기술, 지식이 요구됨 + +### DAO(DATA ACCESS OBJECT) +#### DB를 이용해 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 오브젝트 +### 자바빈(JAVA Bean) +#### 원래 비주얼 툴에서 조작가능한 컴포넌트를 말하나, 요즘은 비주얼 컴포넌트라기보다는 다음 두 가지 관례를 따라 만들어진 오브젝트를 가리키며 간단히 빈이라고도 한다. * 디폴트생성자 : 자바빈은 파라미터가 없는 디폴트 생성자를 갖고 있어야 한다. 툴이나 프레임워크에서 리플렉션을 이용해 오 브젝트를 생성하기 때문에 필요 * 프로퍼티 : 자바빈이 노출하는 이름을 가진 속성, set으로 시작하는 수정자 메소드(setter)와 get으로 시작하는 접근자 메소드(getter)를 이용해 수정 또는 조회를 할 수 있다. -###User class(domain), UserDao class 생성 +### User class(domain), UserDao class 생성 * UserDao의 경우 사용자 정보를 DB에 넣고 관리할 수 있는 DAO 클래스로 getter, setter가 있으며 JDBC를 통해 DB접근을 한다. -###JDBC를 이용하는 작업의 일반적 순서 +### JDBC를 이용하는 작업의 일반적 순서 1. DB 연결을 위한 Connection을 가져온다. 2. SQL을 담은 Statement 또는 PreparedStatement를 만든다. 3. 만들어진 Statement를 실행한다. @@ -23,20 +23,20 @@ 5. 작업 중 생성된 Connection,Statement,ResultSet 같은 리소스는 작업 후 반드시 닫아준다. 6. JDBC API가 만들어내는 예외를 잡아 직접 처리하거나 메소드에 throws를 선언하여 예외 발생시 메소드 밖으로 던지게 한다.(예외는 메소드 밖으로 다 던지는게 간단하다.) -####해당 클래스가 제대로 동작하는지 확인하려면 DAO의 기능을 사용하는 웹 애플리케이션을 만들어 서버에 배치하고 웹브라우저를 통해 DAO기능을 사용해보는 것이 맞으나, 부담이 크다. 가장 간단한 방법은 main()을 이용한 DAO 테스트 코드 작성(리스트1-3) +#### 해당 클래스가 제대로 동작하는지 확인하려면 DAO의 기능을 사용하는 웹 애플리케이션을 만들어 서버에 배치하고 웹브라우저를 통해 DAO기능을 사용해보는 것이 맞으나, 부담이 크다. 가장 간단한 방법은 main()을 이용한 DAO 테스트 코드 작성(리스트1-3) #### Main메소드 생성 후 그 안에서 UserDao의 오브젝트를 생성하여 add()와 get() 메소드 검증을 하면된다. --- ## 1.2 DAO의 분리 ### 1.2.1 관심사의 분리 -####객체지향의 세계에서는 모든게 변한다. 변수나 오브젝트 필드값이 변하는 것이 아닌 오브젝트에 대한 설계와 이를 구현한 코드가 변한다는 뜻. -####개발자가 객체를 설계할 때 가장 염두해야할 것이 미래의 변화를 어떻게 대비할 것인가이다. -####변화가 한 번에 한 가지 관심에 집중되어 일어난다면 , 우리가 준비할 것은 한 가지 관심이 한 군데에 집중되게 하는 것. 즉, 관심이 같은 것끼리는 모으고 관심이 다른 것끼리는 따로 떨어져 있게 하는것. -####프로그래밍의 기초 개념 중 관심사의 분리라는 것이 있다. SoC(Separation of Concerns) : 관심이 같은 것끼리는 하나의 객체 안으로 또는 친한 객체로 모이게 하고 관심이 다른 것은 가능한 한 따로 떨어져서 서로 영향을 주지 않도록 분리하는 것. +#### 객체지향의 세계에서는 모든게 변한다. 변수나 오브젝트 필드값이 변하는 것이 아닌 오브젝트에 대한 설계와 이를 구현한 코드가 변한다는 뜻. +#### 개발자가 객체를 설계할 때 가장 염두해야할 것이 미래의 변화를 어떻게 대비할 것인가이다. +#### 변화가 한 번에 한 가지 관심에 집중되어 일어난다면 , 우리가 준비할 것은 한 가지 관심이 한 군데에 집중되게 하는 것. 즉, 관심이 같은 것끼리는 모으고 관심이 다른 것끼리는 따로 떨어져 있게 하는것. +#### 프로그래밍의 기초 개념 중 관심사의 분리라는 것이 있다. SoC(Separation of Concerns) : 관심이 같은 것끼리는 하나의 객체 안으로 또는 친한 객체로 모이게 하고 관심이 다른 것은 가능한 한 따로 떨어져서 서로 영향을 주지 않도록 분리하는 것. ### 1.2.2 커넥션 만들기의 추출 -####UserDao의 구현된 메소드를 살펴보면 add()에서만 적어도 세 가지 관심사항 확인 가능 +#### UserDao의 구현된 메소드를 살펴보면 add()에서만 적어도 세 가지 관심사항 확인 가능 1. DB와 연결을 위한 커넥션을 어떻게 가져올지, 어떤 DB, 드라이버, 로그인 정보 등.. 2. 사용자 등록을 위해 DB에 보낼 Statement를 만들고 실행하는 것. 3. 작업이 끝난 후 사용한 리소스인 statement와 connection 오브젝트를 닫아줘서 공유리소스를 시스템에 돌려주는 것. @@ -44,62 +44,62 @@ 가장 문제가 되는 것은 첫째 관심사인 디비연결을 위한 Connection 오브젝트를 가져오는 부분. 현재 db커넥션을 가져오는 코드는 다른 관심사와 섞여 같은 add() 메소드에 담겨있는데 더 큰 문제는 add() 메소드에 있는 디비 커넥션을 가져오는 코드와 동일한 코드가 get() 메소드에도 중복되어 있다는 점. 이는 스파게티 코드의 위험이 있다. 이것을 해결하기 위한 중복코드의 메소드 추출 - 리팩토링 -###리팩토링 -####리팩토링은 기존 코드를 외부의 동작 방식에는 변화없이 내부 구조를 변경하여 재구성하는 작업으로 리팩토링 시 코드 내부의 설계가 개선되어 코드를 이해하기 더 편해지고 변화에 효율적인 대응 가능. 생산성 업, 품질 업, 유지보수하기도 편함 +### 리팩토링 +#### 리팩토링은 기존 코드를 외부의 동작 방식에는 변화없이 내부 구조를 변경하여 재구성하는 작업으로 리팩토링 시 코드 내부의 설계가 개선되어 코드를 이해하기 더 편해지고 변화에 효율적인 대응 가능. 생산성 업, 품질 업, 유지보수하기도 편함 ### 1.2.3. 커넥션만들기의 독립. -####서로다른 db를 사용할 때 db커넥션을 가져오는데 있어 독자적인 방법을 적용하고 싶다면 어떻게할까? UserDao의 소스를 모두 제공하고 필요시 getConnection()메소드를 수정해서 사용할 수도 있으나 고객에게는 미리 컴파일된 클래스 바이너리 파일만 제공한다면.. +#### 서로다른 db를 사용할 때 db커넥션을 가져오는데 있어 독자적인 방법을 적용하고 싶다면 어떻게할까? UserDao의 소스를 모두 제공하고 필요시 getConnection()메소드를 수정해서 사용할 수도 있으나 고객에게는 미리 컴파일된 클래스 바이너리 파일만 제공한다면.. 1. 상속을 통한 확장 * UserDao 코드를 한단계 더 분리한다. getConnection()을 추상메소드로 만들어 놓는다. 추상 메소드라 메소드 코드는 없으나 메소드 자체는 존재하며 따라서 add(), get() 메소드에서 getConnection()을 호출하는 코드는 유지할 수 있다. 또한 추상클래스인 UserDao를 고객에게 판매한다. 그 이후 UserDao클래스를 상속하게 하여 서브클래스를 만들고 서브클래스 밑에 존재하는 getConnection()메소드를 원하는대로 구현 가능하다. 이런식으로 슈퍼클래스에 기본적인 로직의 흐름(커넥션가져오기, sql생성, 실행, 반환) 을 만들고 그 기능의 일부를 추상메소드나 오버라이딩이 가능한 protected 메소드 등으로 만든 뒤 서브클래스에서 이 메소드를 필요에 맞게 구현하여 활용하도록 하는 방법을 디자인 패턴에서는 템플릿 메소드 패턴이라고 한다. 이는 스프링에서 애용되는 디자인 패턴 중 하나. -###디자인 패턴 -####소프트웨어 설계 시 특정 상황에서 자주 만나는 문제를 해결하기 위해 사용할 수 있는 재사용 가능한 솔루션을 말한다. 주로 객체지향 설계에 관한 것이고 대부분 객체지향적 설계 원칙을 이용해 문제를 해결한다. 패턴의 설계구조를 보면 대부분 비슷한데 그 이유는 객체지향적인 설계로부터 문제를 해결하기 위해 적용할 수 있는 확장성 추구 방법이 대부분 클래스상속, 오브젝트 합성 두가지로 정리되기 때문이다. -###템플릿 메소드 패턴 -####상속을 통해 슈퍼클래스의 기능을 확장할때 사용하는 가장 대표적인 방법. 변하지 않는 기능은 슈퍼클래스에 만들고 자주 변경되며 확장할 기능은 서브클래스에서 만들도록 한다. 슈퍼클래스에서는 미리 추상메소드 또는 오버라이딩 가능한 메소드를 정의해두고 이를 활용해 코드의 기본 알고리즘을 담고 있는 템플릿 메소드를 만든다. 슈퍼클래스에서 디폴트 기능을 정의해두거나 서브클래스에서 선택적으로 오버라이드할 수 있도록 만들어둔 메소드를 훅 메소드라고 한다. 서브클래스에서는 추상메소드를 구현하거나 훅 메소드를 오버라이드 하는 방법을 이용해 그 기능을 확장한다. +### 디자인 패턴 +#### 소프트웨어 설계 시 특정 상황에서 자주 만나는 문제를 해결하기 위해 사용할 수 있는 재사용 가능한 솔루션을 말한다. 주로 객체지향 설계에 관한 것이고 대부분 객체지향적 설계 원칙을 이용해 문제를 해결한다. 패턴의 설계구조를 보면 대부분 비슷한데 그 이유는 객체지향적인 설계로부터 문제를 해결하기 위해 적용할 수 있는 확장성 추구 방법이 대부분 클래스상속, 오브젝트 합성 두가지로 정리되기 때문이다. +### 템플릿 메소드 패턴 +#### 상속을 통해 슈퍼클래스의 기능을 확장할때 사용하는 가장 대표적인 방법. 변하지 않는 기능은 슈퍼클래스에 만들고 자주 변경되며 확장할 기능은 서브클래스에서 만들도록 한다. 슈퍼클래스에서는 미리 추상메소드 또는 오버라이딩 가능한 메소드를 정의해두고 이를 활용해 코드의 기본 알고리즘을 담고 있는 템플릿 메소드를 만든다. 슈퍼클래스에서 디폴트 기능을 정의해두거나 서브클래스에서 선택적으로 오버라이드할 수 있도록 만들어둔 메소드를 훅 메소드라고 한다. 서브클래스에서는 추상메소드를 구현하거나 훅 메소드를 오버라이드 하는 방법을 이용해 그 기능을 확장한다. -###팩토리 메소드 패턴 -####템플릿 메소드 패턴과 마찬가지로 상속을 통해 기능을 확장하게 하는 패턴이라 구조도 비슷하다. 슈퍼클래스 코드에서는 서브클래스에서 구현할 메소드를 호출하여 필요한 타입의 오브젝트를 가져와 사용한다. 이 메소드는 주로 인터페이스 타입으로 오브젝트를 리턴하므로 서브클래스에서 정확히 어떤 클래스의 오브젝트를 만들어 리턴할 지는 슈퍼클래스에서는 알지 못한다. 서브클래스는 다양한 방법으로 오브젝트를 생성하는 메소드를 재정의할 수 잇다. 이렇게 서브클래스에서 오브젝트 생성 방법과 클래스를 결정할 수 있도록 미리 정의해둔 메소드를 팩토리 메소드라고 하고, 이방식을 통해 오브젝트 생성 방법을 나머지 로직, 즉 슈퍼클래스의 기본 코드에서 독립시키는 방법을 팩토리 메소드 패턴이라고 한다. +### 팩토리 메소드 패턴 +#### 템플릿 메소드 패턴과 마찬가지로 상속을 통해 기능을 확장하게 하는 패턴이라 구조도 비슷하다. 슈퍼클래스 코드에서는 서브클래스에서 구현할 메소드를 호출하여 필요한 타입의 오브젝트를 가져와 사용한다. 이 메소드는 주로 인터페이스 타입으로 오브젝트를 리턴하므로 서브클래스에서 정확히 어떤 클래스의 오브젝트를 만들어 리턴할 지는 슈퍼클래스에서는 알지 못한다. 서브클래스는 다양한 방법으로 오브젝트를 생성하는 메소드를 재정의할 수 잇다. 이렇게 서브클래스에서 오브젝트 생성 방법과 클래스를 결정할 수 있도록 미리 정의해둔 메소드를 팩토리 메소드라고 하고, 이방식을 통해 오브젝트 생성 방법을 나머지 로직, 즉 슈퍼클래스의 기본 코드에서 독립시키는 방법을 팩토리 메소드 패턴이라고 한다. 위와 같은 방법은 상속을 이용한다는 단점이 있다. 상속이 간단해보이고 편해보이나 한계점이 있다. 만약 이미 UserDao가 다른 목적을 위해 상속을 하고 있다면 클래스의 다중상속을 허용하지 않는 자바에서는 불가능. 또다른 문제는 상속을 통한 상하위 클래스 관계는 생각보다 밀접하여, 서브클래스가 슈퍼클래스 기능을 직접 사용할 수 있기에 슈퍼클래스 내부 변경 시 서브클래스들에게도 영향을 미쳐 서브클래스를 변경해야할 수도 있다. --- ## 1.3 DAO의 확장 ### 1.3.1 클래스의 분리 -####관심사가 다르고 변화의 성격이 다른 코드를 분리하는 방법 중 하나. db커넥션과 관련된 부분을 서브클래스가 아니라 아예 별도의 클래스에 담은 후 그 클래스를 UserDao가 사용하게 하는 방법. -####SimpleConnectionMaker()라는 클래스를 생성하여 db연결기능을 만들었는데 이러면 고객이 db연결방법을 변경할 수 없음. 문제 해결을 위해 SimpleConnectionMaker()의 메소드가 문제인데 우리가 만든 거에선 makeNewConnection()을 사용해 db커넥션을 가져오게 되는데 만약 고객이 만든 db커넥션 제공 클래스는 openConnection()이라는 이름을 사용한다면 UserDao내에 있는 add, get메소드의 커넥션을 가져오는 코드를 일일이 변경해야한다. 두번째 문제는 db커넥션을 제공하는 클래스가 어떤 것인지 UserDao가 구체적으로 알아야 한다는 것. -####이 문제의 근본 원인은 UserDao가 바뀔 수 있는 정보, 즉 db커넥션을 가져오는 클래스에 대해 너무 많이 알고있다는 것이다. 어떤 클래스가 쓰이는지, 그 클래스에서 커넥션을 가져오는 메소드의 이름이 무엇인지까지 일일이 알고 있어야 하기 때문에 결국 UserDao가 db커넥션을 가져오는 구체적인 방법에 종속되어버린다. +#### 관심사가 다르고 변화의 성격이 다른 코드를 분리하는 방법 중 하나. db커넥션과 관련된 부분을 서브클래스가 아니라 아예 별도의 클래스에 담은 후 그 클래스를 UserDao가 사용하게 하는 방법. +#### SimpleConnectionMaker()라는 클래스를 생성하여 db연결기능을 만들었는데 이러면 고객이 db연결방법을 변경할 수 없음. 문제 해결을 위해 SimpleConnectionMaker()의 메소드가 문제인데 우리가 만든 거에선 makeNewConnection()을 사용해 db커넥션을 가져오게 되는데 만약 고객이 만든 db커넥션 제공 클래스는 openConnection()이라는 이름을 사용한다면 UserDao내에 있는 add, get메소드의 커넥션을 가져오는 코드를 일일이 변경해야한다. 두번째 문제는 db커넥션을 제공하는 클래스가 어떤 것인지 UserDao가 구체적으로 알아야 한다는 것. +#### 이 문제의 근본 원인은 UserDao가 바뀔 수 있는 정보, 즉 db커넥션을 가져오는 클래스에 대해 너무 많이 알고있다는 것이다. 어떤 클래스가 쓰이는지, 그 클래스에서 커넥션을 가져오는 메소드의 이름이 무엇인지까지 일일이 알고 있어야 하기 때문에 결국 UserDao가 db커넥션을 가져오는 구체적인 방법에 종속되어버린다. ### 1.3.2 인터페이스의 도입 -####클래스를 분리하면서도 이 문제를 해결하기 위해서 가장 좋은 방법은 두 클래스가 서로 긴밀하게 연결하지 않도록 중간에 추상적인 느슨한 연결고리를 만들어 주는것. -####자바가 추상화를 위해 제공하는 가장 유용한 도구는 바로 인터페이스. 자신을 구현한 클래스에 대한 구체적 정보는 모두 감출 수 있으므로. -####결국 오브젝트를 만들기 위해 구체적인 클래스를 하나 선택해야하나 인터페이스로 추상화해놓은 최소한의 통로를 통해 접근하는 쪽에서는 오브젝트를 만들 때 사용할 클래스가 무엇인지 몰라도 된다. -####인터페이스는 어떤 일을 하겠다는 기능만 정의해놓았기 때문에 이를 구현한 클래스들이 알아서 결정할 수 있다.but 이 방법도 문제가 있는 게 UserDao생성 자 호출 시 고객사의 클래스 이름이 나오게된다. +#### 클래스를 분리하면서도 이 문제를 해결하기 위해서 가장 좋은 방법은 두 클래스가 서로 긴밀하게 연결하지 않도록 중간에 추상적인 느슨한 연결고리를 만들어 주는것. +#### 자바가 추상화를 위해 제공하는 가장 유용한 도구는 바로 인터페이스. 자신을 구현한 클래스에 대한 구체적 정보는 모두 감출 수 있으므로. +#### 결국 오브젝트를 만들기 위해 구체적인 클래스를 하나 선택해야하나 인터페이스로 추상화해놓은 최소한의 통로를 통해 접근하는 쪽에서는 오브젝트를 만들 때 사용할 클래스가 무엇인지 몰라도 된다. +#### 인터페이스는 어떤 일을 하겠다는 기능만 정의해놓았기 때문에 이를 구현한 클래스들이 알아서 결정할 수 있다.but 이 방법도 문제가 있는 게 UserDao생성 자 호출 시 고객사의 클래스 이름이 나오게된다. ### 1.3.3 관계 설정 책임의 분리 -####위에서 UserDao와 ConnectionMaker라는 두개의 관심을 인터페이스를 사용하여 분리했는데도 UserDao가 구체적인 클래스(DconnectionMaker)까지 알아야했다. 그 이유는 여전히 UserDao에는 어떤 ConnectionMaker 구현 클래스를 사용할지 결정하는 코드가 남아 있기 때문 (new DConnectionMaker()) -####UserDao클래스 내에서 해당 정보를 삭제하기 위해서 클라이언트에게 그 책임을 떠넘기면 된다. UserDao클래스의 main 메소드가 UserDao클라이언트라고 볼 수 있으며 해당 오브젝트가 파라미터로 넘겨주도록 변경하면 UserDao내에서 구체적인 클래스 이름을 제거할 수 있다. 이렇게 인터페이스를 도입하고 클라이언트의 도움을 받으면 상속을 이용해 비슷한 시도를 했을 경우에 비해 훨씬 유연하다. +#### 위에서 UserDao와 ConnectionMaker라는 두개의 관심을 인터페이스를 사용하여 분리했는데도 UserDao가 구체적인 클래스(DconnectionMaker)까지 알아야했다. 그 이유는 여전히 UserDao에는 어떤 ConnectionMaker 구현 클래스를 사용할지 결정하는 코드가 남아 있기 때문 (new DConnectionMaker()) +#### UserDao클래스 내에서 해당 정보를 삭제하기 위해서 클라이언트에게 그 책임을 떠넘기면 된다. UserDao클래스의 main 메소드가 UserDao클라이언트라고 볼 수 있으며 해당 오브젝트가 파라미터로 넘겨주도록 변경하면 UserDao내에서 구체적인 클래스 이름을 제거할 수 있다. 이렇게 인터페이스를 도입하고 클라이언트의 도움을 받으면 상속을 이용해 비슷한 시도를 했을 경우에 비해 훨씬 유연하다. ### 1.3.4 원칙과 패턴 ### 개방 폐쇄 원칙 (OCP, Open-Closed Principle) -####개방 폐쇄원칙을 이용하면 지금까지 해온 리팩토링 작업의 특징과 최종적으로 개선된 설계와 코드의 장점이 무엇인지 효과적으로 설명할 수 있다. 간단히 정의하면 '클래스나 모듈은 확장에는 열려있어야 하고 변경에는 닫혀있어야 한다'라고 할 수 잇다. +#### 개방 폐쇄원칙을 이용하면 지금까지 해온 리팩토링 작업의 특징과 최종적으로 개선된 설계와 코드의 장점이 무엇인지 효과적으로 설명할 수 있다. 간단히 정의하면 '클래스나 모듈은 확장에는 열려있어야 하고 변경에는 닫혀있어야 한다'라고 할 수 잇다. ### 높은 응집도와 낮은 결합도 -####개방폐쇄 원칙은 높은 응집도와 낮은 결합도라는 소프트웨어 개발의 고전적인 원리로도 설명 가능. +#### 개방폐쇄 원칙은 높은 응집도와 낮은 결합도라는 소프트웨어 개발의 고전적인 원리로도 설명 가능. * 높은 응집도 : 응집도가 높다는 것은 변화가 일어날 때 해당 모듈에서 변하는 부분이 크다는 것, 즉 변경이 일어날 때 모듈의 많은 부분이 바뀐다면 응집도가 높다고 말할 수 있다. * 낮은 결합도 : 낮은 결합도는 높은 응집도보다 더 민감한 원칙으로, 책임과 관심사가 다른 오브젝트 또는 모듈과는 낮은 결합도, 즉 느슨하게 연결된 형태를 유지하는 것이 바람직. 느슨한 연결은 관곌르 유지하는데 꼭 필요한 최소한의 방법만 간접적인 형태로 제공하고, 나머지는 서로 독립적이고 알 필요도 없게 만들어주는 것이다. 결합도가 낮아지면 변화에 대응하는 속도가 높아지고, 구성이 깔끔해진다. 여서 결합도란 하나의 오브젝트가 변경이 일어날 때 관계를 맺고 있는 다른 오브젝트에게 변화를 요구하는 정도를 말한다고 할 수 있다. -###전략 패턴 -####전략 패턴은 자신의 기능 맥락에서 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔서 사용할 수 있게 하는 디자인 패턴. +### 전략 패턴 +#### 전략 패턴은 자신의 기능 맥락에서 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔서 사용할 수 있게 하는 디자인 패턴. --- ## 1.4 제어의 역전 (IoC : Inversion of Control) -###1.4.1 오브젝트 팩토리 +### 1.4.1 오브젝트 팩토리 이전에 만든 UserDaoTest를 클라이언트로 사용했었는데 해당 클래스는 원래 UserDao기능이 잘 동작하는지를 테스트하려고 한것이라 클라이언트의 책임까지 맡기에는 문제가 있어 분리해야한다. 이렇게 분리될 기능은 UserDao와 ConnectionMaker 구현 클래스의 오브젝트를 만드는 것과, 그렇게 만들어진 두개의 오브젝트가 연결돼 사용될 수 있도록 관계를 맺어주는 것이다. -###팩토리 +### 팩토리 객체의 생성 방법을 결정하고 그렇게 만들어진 오브젝트를 돌려주는 것인데, 이런 일을 하는 오브젝트를 흔히 팩토리라고 한다. 이는 디자인 패턴에서 말하는 특별한 문제를 해결하기 위해 사용되는 추상팩토리 패턴이나 팩토리 메소드 패턴과는 다르니 혼동하지 말자. 단지 오브젝트를 생성하는 쪽과 생성된 오브젝트를 사용하는 쪽의 역할과 책임을 깔끔하게 분리하기 위한 목적으로 사용하는 것. @@ -110,10 +110,10 @@ UserDao : 데이터 로직 ConnectionMaker : 기술 로직 DaoFactory : 어플리케이션의 오브젝트들을 구성하고 그 관계를 정의하는 책임, 간단히 말하면 어떤 오브젝트가 어떤 오브젝트를 사용하는지 정의해놓은 코드.; 고객에게 UserDao공급 시 UserDao, ConnectionMaker와 함께 DaoFactory도 함께 제공하여 새로운 ConnectionMaker구현 클래스로 변경이 필요하면 DaoFactory를 수정해서 변경된 클래슬르 생성 , 설정하도록 코드를 수정해주면 된다. UserDao는 수정이 필요없고, DBㅇ녀결방식은 알아서 확장 가능. -###1.4.2 오브젝트 팩토리의 활용 +### 1.4.2 오브젝트 팩토리의 활용 DaoFactory에 UserDao가 아닌 다른 DAO 생성 기능을 넣을 경우 각 Dao호출시마다 new DconnectionMaker()를 넣어야하기 때문에 이또한 리팩토링을 통해 connectionMaker()타입의 오브젝트 생성 코드를 생성해 적용하면 된다. -###1.4.3 제어권의 이전을 통한 제어관계 역전 +### 1.4.3 제어권의 이전을 통한 제어관계 역전 일반적으로 프로그램의 흐름은 main() 메소드와 같이 프로그램이 시작되는 지점에서 다음에 사용할 오브젝트를 결정하고, 결정한 오브젝트를 생성하고, 만들어진 오브젝트에 있는 메소드를 호출하고 그 오브젝트 메소드 안에서 다음에 사용할 것을 결정하고 호출하는 식의 작업이 반복된다. 이러한 프로그램 구조에서 각 오브젝트는 프로그램 흐름을 결정하거나 사용할 오브젝트를 구성하는 작업에 능동적으로 참여한다. @@ -122,25 +122,25 @@ DaoFactory에 UserDao가 아닌 다른 DAO 생성 기능을 넣을 경우 각 Da 우리가 만든 UserDao와 DaoFactory에도 제어의 역전이 적용돼있는데, 원래 ConnectionMaker구현 클래스를 결정하고 오브젝트를 만드는 제어권이 UserDao에게 있었으나, 지금은 DaoFactory에 있다. 자신이 어떠한 ConnectionMaker 구현 클래스를 만들고 사용할지 결정할 권한을 DaoFactory에 넘겼으니 UserDao는 이제 수동적인 존재가 된 것. UserDao 자신도 DaoFactory가 공급해주는 것을 수동적으로 사용해야 한다. 자연스럽게 관심을 분리하고, 책임을 나누고ㅓ 유연하게 확장 가능한 구조를 만들기 위해 DaoFactory를 도입했던 과정이 바로 IoC를 적용하는 작업이다. -##1.5 스프링의 IoC +## 1.5 스프링의 IoC 스프링의 핵심은 바로 빈 팩토리 또는 어플리케이션 컨텍스트라고 불리는 것. 이 두가지는 우리가 만든 DaoFactory가 하는 일을 좀 더 일반화 한 것이라 볼 수 있다. -###1.5.1 오브젝트 팩토리를 이용한 스프링 IoC +### 1.5.1 오브젝트 팩토리를 이용한 스프링 IoC 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트를 빈(Bean)이라 부른다. 동시에 스프링 빈은 스프링 컨테이너가 생성과 관계 설정, 사용 등을 제어해주는 제어의 역전이 적용된 오브젝트를 가리키는 말이다. 그래서 스프링에서 빈의 생성과 관계 설정 같은 제어를 담당하는 IoC 오브젝트를 빈 팩토리라 한다. 보통 빈 팩토리보다는 이를 좀더 확장한 애플리케이션 컨텍스트를 주로 사용한다. 이는 IoC방식을 따라 만들어진 일종의 빈 팩토리라 생각하면 된다. 애플리케이션 컨텍스트는 별도의 정보를 참고해 빈 생성, 관계 설정등의 제어 작업을 총괄한다. DaoFactory를 스프링의 빈 팩토리가 사용할 수 있는 본격적인 설정정보로 만들기 위해 스프링이 빈 팩토리를 위한 오브젝트 설정을 담당하는 클래스라고 인식할 수 있도록 @Configuration이라는 애노테이션을 추가하고 그 뒤 오브젝트를 만들어주는 메소드에 @Bean이라는 애노테이션을 붙여준다. -###1.5.2 애플리케이션 컨텍스트의 동작 방식 +### 1.5.2 애플리케이션 컨텍스트의 동작 방식 애플리케이션 컨텍스트는 애플리케이션에서 IoC를 적용해 관리할 모든 오브젝트에 대한 생성과 관계설정을 담당하며 DaoFactory와는 달리 직접 오브젝트를 생성하고 관계를 맺어주는 코드가 없고, 그런 생성정보과 연관관계 정보를 별도의 설정정보를 통해 얻는다. 이때 장점은 1. 클라이언트가 구체적인 팩토리 클래스를 알 필요가 없다. 2. 애플리케이션 컨텍스트는 종합 IoC 서비스를 제공 3. 애플리케이션 컨텍스트는 빈을 검색하는 다양한 방법을 제공한다. -###1.5.3 스프링 IoC의 용어 정리 +### 1.5.3 스프링 IoC의 용어 정리 * 빈 스프링이 IoC 방식으로 관리하는 오브젝트, 스프링을 사용하는 애플리케이션에서 만들어지는 모든 오브젝트가 다 빈은 아니며, 스프링이 직접 그 생성과 제어를 담다하는 오브젝트만을 빈이라 부른다. @@ -153,18 +153,18 @@ DaoFactory를 스프링의 빈 팩토리가 사용할 수 있는 본격적인 * 스프링 프레임워크 IoC 컨테이너, 애플리케이션 컨텍스트를 포함해 스프링이 제공하는 모든 기능을 통틀어 말할때 사용. -##1.6 싱글톤 레지스트리와 오브젝트 스코프 +## 1.6 싱글톤 레지스트리와 오브젝트 스코프 * 오브젝트의 동일성과 동등성 자바에서 두개의 오브젝트가 같은가라는 말은 주의해야 하는데, 두 오브젝트가 완전히 같은 동일한(identical) 오브젝트라고 말하는 것과 동일한 정보를 가진(equivalent) 오브젝트라고 말하는것은 분명한 차이가 있다. ==, equals()로 비교 가능 -###1.6.1 싱글톤 레지스트리로서의 애플리케이션 컨텍스트 +### 1.6.1 싱글톤 레지스트리로서의 애플리케이션 컨텍스트 애플리케이션 컨텍스트는 싱글톤을 저장하고 관리하는 싱글톤 레지스트리라고도 함. 스프링은 기본적으로 별다른 설정을 안하면 내부에서 생성하는 빈 오브젝트를 모두 싱글톤으로 만든다. 여기서 싱글톤은 싱글톤 디자인 패턴의 싱글톤 패턴과 비슷한 개념이나 구현방법은 확연히 다르다. * 싱글톤으로 빈을 만드는 이유 : 매번 클라이언트에서 요청올때마다 각 로직을 담당하는 오브젝트를 새로 만들면 부하가 걸림.. 서버환경에서는 서비스 싱글톤 사용이 권장되나 사용하기 힘들고 여러 문제점이 있어 싱글톤 패턴을 피해야할 패턴이라는 의미인 안티패턴이라고 부르는 사람도 있음. 싱글톤 패턴을 사용하면 생성자가 private으로 바뀌었기 때문에 외부 호출이 불가하여 DaoFactory에서 UserDao를 생성하여 ConnectionMaker 오브젝트를 넣어주는 것이 불가능. -###싱글톤패턴 구현방식의 문제 +### 싱글톤패턴 구현방식의 문제 - private 생성자를 갖고 있기 때문에 상속할 수 없다. - 테스트하기가 힘들다. - 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다 ; 서버에서 클래스 로더를 어떻게 구성하냐에 따라 싱글톤 클래스임에도 하나 이상의 오브젝트가 만들어질 수도 있다. @@ -173,20 +173,20 @@ DaoFactory를 스프링의 빈 팩토리가 사용할 수 있는 본격적인 스프링은 서버환경에서 싱글톤이 만들어져 서비스 오브젝트 방식으로 사용되는 것은 괜찮다. 하지만 자바의 기본적인 싱글톤패턴 구현방식은 여러 단점이 있어 스프링은 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공하는데 이것이 싱글톤 레지스트리이다. 스프링의 싱글톤 레지스트리 덕분에 싱글톤 방식으로 사용될 애플리케이션 클래스라도 public 생성자를 가질 수 있다. -###1.6.2 싱글톤과 오브젝트의 상태 +### 1.6.2 싱글톤과 오브젝트의 상태 싱글톤은 멀티스레드 환경이라면 여러 스레드가 동시에 접근하여 사용될 수 있어 주의를 기울여야 한다. 기본적으로 멀티스레드 환경에서 싱글톤이 서비스 형태의 오브젝트로 사용되는 경우 상태정보를 내부에 갖고 있지 않은 무상태방식으로 만들어져야 한다. 이 때 파라미터와 로컬 변수, 리턴값을 이용한다. 메소드 파라미터나 메소드 안에서 생기는 로컬 변수는 매번 새로운 값을 저장할 독립적인 공간이 만들어져 싱글톤이라 해도 여러 스레드가 변수의 값을 덮어쓸 일이 없다. -###1.6.3 스프링 빈의 스코프 +### 1.6.3 스프링 빈의 스코프 스프링이 관리하는 오브젝트, 즉 빈이 생성되고 존재하는 적용되는 범위를 빈의 스코프라고 한다. --- -##1.7 의존관계 주입(DI : Dependency Injection) -###1.7.1 제어의 역전(IoC)과 의존관계 주입 +## 1.7 의존관계 주입(DI : Dependency Injection) +### 1.7.1 제어의 역전(IoC)과 의존관계 주입 IoC라는 말은 되게 느슨하게 정의되어 스프링이 제공하는 기능의 특징을 명확하게 설명하지 못한다. 스프링이 서블릿 컨테이너처럼 서버에서 동작하는 서비스 컨테이너라는 뜻인지, 단순히 IoC 개념이 적용된 템플릿 메소드 패턴을 이용해 만들어진 프레임워크인지 파악하기 힘들다. 그래서 쓰기 시작한 용어가 의존관계 주입(DI) - 스프링 IoC기능의 대표적인 동작원리. -###1.7.2 런타임 의존관계 설정 +### 1.7.2 런타임 의존관계 설정 A->B라면 A가 B에 의존하고 있다는 듯.. 즉 B가 변하면 그것이 A에 영향을 미친다는 뜻이다. 대표적인 예로 A가 B를 사용하는 경우 A가 B에서 정의된 메소드를 호출해서 사용하는 경우이다. 이럴 땐 '사용에 대한 의존관계'가 있다고 말할 수 있다. 하지만 의존관계에는 방향성이 있어 B는 A에 의존하지 않는다. 즉 B는 A의 변화에 영향을 받지 않는다는 뜻 UserDao의 예 @@ -199,13 +199,13 @@ UserDao가 ConnectionMaker에 의존하고 있는 형태. 따라서 ConnectionMa DI의 핵심은 설계시점에서는 알지 못했던 두 오브젝트의 관계를 맺도록 도와주는 제 3의 존재가 있다는 것. -###UserDao의 인터페이스 주입 +### UserDao의 인터페이스 주입 인터페이스를 사이에 두고 UserDao와 ConnectionMaker 구현 클래스 간의 의존관계를 느슨하게 만들긴 했으나 마지막으로 남은 문제는 userDao가 사용할 구체적인 클래스를 알고 있어야 한다는 점이었다. 기존에는 UserDao에서 connectionMaker = newDConnectionMaker()를 통해 모델링 때의 의존관계, 즉 ConnectionMaker라는 인터페이스 관계 뿐 아니라 런타임 의존관계, 즉 DConnectionMaker 오브젝트를 사용하겠다는 것까지 UserDao가 알고 있었다. 그래서 IoC 방식을 사용해 UserDao로부터 런타임 의존관계를 드러내는 코드를 제거하고 제 3의 존재에게 런타임 의존관계 결정 권한을 위임하기 위해 DaoFactory를 만든 것이다. DaoFactory는 런타임 시점에 UserDao가 사용할 ConnectionMaker 타입의 오브젝트를 결정하고 이를 생성후 UserDao의 생성자 파라미터로 주입하여 UserDao가 DConnectionMaker의 오브젝트와 런타임 의존관계를 맺게 해준다. 따라서 의존관계 주입의 세가지 조건을 모두 충족한다고 볼 수 있고 이미 DaoFactory를 만든 시점에서 의존 관계 주입을 이용한 셈이 된다. -###1.7.3 의존관계 검색과 주입 +### 1.7.3 의존관계 검색과 주입 스프링의 IoC 컨테이너인 애플리케이션 컨텍스트는 getBean()이라는 메소드를 제공한다. 바로 이 메소드가 의존관계 검색에 사용되어 UserDao는 리스트 1-27과 같이 애플리케이션 컨텍스트를 사용해 의존관계 검색 방식으로 ConnectionMaker오브젝트를 가져올 수도 있다. ### DI받는다의 의미